Hypnoz
Hypnoz

Reputation: 1136

what is good way to generate a "symmetric ladder" or "adjacent" matrix using tensorflow?

(Updated I forget to say the input is batched) Given a bool array, e.g. [[false, false, false, true, false, false, true, false, false], [false, true, false, false, false, false, true, false, false]], which "true" define the boundary of the separate sequence. I want to generate an adjacent matrix denoting the different group separated by the boundary. What is a good way to generate following "symmetric ladder" matrix using Tensorflow?

    [[
    [1 1 1 0 0 0 0 0 0]
    [1 1 1 0 0 0 0 0 0]
    [1 1 1 0 0 0 0 0 0]
    [0 0 0 0 0 0 0 0 0]
    [0 0 0 0 1 1 0 0 0]
    [0 0 0 0 1 1 0 0 0]
    [0 0 0 0 0 0 0 0 0]
    [0 0 0 0 0 0 0 1 1]
    [0 0 0 0 0 0 0 1 1]
    ]
    [
    [1 0 0 0 0 0 0 0 0]
    [0 0 0 0 0 0 0 0 0]
    [0 0 1 1 1 1 1 0 0]
    [0 0 1 1 1 1 1 0 0]
    [0 0 1 1 1 1 1 0 0]
    [0 0 1 1 1 1 1 0 0]
    [0 0 1 1 1 1 1 0 0]
    [0 0 0 0 0 0 0 0 0]
    [0 0 0 0 0 0 0 0 0]
    ]]

Update Jun 15 2018: Actually, I just have some progress on this problem, if I can convert the input senqence from [false, false, false, true, false, false, true, false, false] to [1, 1, 1, 0, 2, 2, 0, 3, 3], I can get some result using following Tensorflow code. But I am not sure is there a vector operation can convert [false, false, false, true, false, false, true, false, false] to [1, 1, 1, 0, 2, 2, 0, 3, 3]?

import tensorflow as tf
sess = tf.Session()

x = tf.constant([1, 1, 1, 0, 2, 2, 0, 3, 3], shape=(9, 1), dtype=tf.int32)
y = tf.squeeze(tf.cast(tf.equal(tf.expand_dims(x, 1), x), tf.int32))
print(sess.run(y))
[[1 1 1 0 0 0 0 0 0]
 [1 1 1 0 0 0 0 0 0]
 [1 1 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 1 0 0]
 [0 0 0 0 1 1 0 0 0]
 [0 0 0 0 1 1 0 0 0]
 [0 0 0 1 0 0 1 0 0]
 [0 0 0 0 0 0 0 1 1]
 [0 0 0 0 0 0 0 1 1]]

Update finally: I inspired a lot from @Willem Van Onsem. For batched version can be solved by modifying a little from @Willem Van Onsem solution.

import tensorflow as tf
b = tf.constant([[False, False, False, True, False, False, True, False, False], [False, True, False, False, False, False, False, False, False]], shape=(2, 9, 1), dtype=tf.int32)
x = (1 + tf.cumsum(tf.cast(b, tf.int32), axis=1))  * (1-b)
x = tf.cast(tf.equal(x, tf.transpose(x, perm=[0,2,1])),tf.int32) - tf.transpose(b, perm=[0,2,1])*b


with tf.Session() as sess:
  print(sess.run(x))

Upvotes: 2

Views: 142

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476739

But I am not sure is there a vector operation can convert [False, False, False, True, False, False, True, False, False] to [1, 1, 1, 0, 2, 2, 0, 3, 3]

There is, consider the following example:

b = tf.constant([False, False, False, True, False, False, True, False, False], shape=(9,), dtype=tf.int32)

then we can use tf.cumsum(..) to generate:

>>> print(sess.run(1+tf.cumsum(b)))
[1 1 1 2 2 2 3 3 3]

If we then multiply the values with the opposite of b, we get:

>>> print(sess.run((1+tf.cumsum(b))*(1-b)))
[1 1 1 0 2 2 0 3 3]

So we can store this expression in a variable, for example x:

x = (1+tf.cumsum(b))*(1-b)

I want to generate an adjacent matrix denoting the different group separated by the boundary. What is a good way to generate following "symmetric ladder" matrix using Tensorflow?

If we follow your approach, we only have to remove the points where both lists are 0 at the same time. We can do this with:

tf.cast(tf.equal(x, tf.transpose(x)),tf.int32) - tf.transpose(b)*b

So here we use your approach, where we basically broadcast x, and the transpose of x, and check for elementwise equality, and we subtract the element-wise multiplication of b from, it. This then yields:

>>> print(sess.run(tf.cast(tf.equal(x, tf.transpose(x)),tf.int32) - tf.transpose(b)*b))
[[1 1 1 0 0 0 0 0 0]
 [1 1 1 0 0 0 0 0 0]
 [1 1 1 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0]
 [0 0 0 0 1 1 0 0 0]
 [0 0 0 0 1 1 0 0 0]
 [0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 1 1]
 [0 0 0 0 0 0 0 1 1]]

Upvotes: 1

Related Questions