DTen
DTen

Reputation: 11

Tensorflow - equivalence of scipy.linalg.circulant

I'm looking for the best way to do the equivalent to scipy.linalg.circulant

scipy

I can use LinearOperatorCirculant and then call to_dense() but the performance is horrible compared to scipy.linalg.circulant when the dimensions are large.

I can also use multiple tf.stack with tf.roll but there must be a better and faster way.

I couldn't find a way to integrate with scipy.linalg.circulant because I'm using this operation on tf.Variable.

Does anyone have an idea?

Upvotes: 1

Views: 80

Answers (1)

John Jiang
John Jiang

Reputation: 955

You can use tf.scatter_nd instead of tf.roll, which requires knowing the static dimension of the matrix.

def circulant(elements):
    elements = tf.convert_to_tensor(elements)
    dim = tf.size(elements)
    range_t = tf.range(dim)    
    tiled = tf.reshape(tf.tile(tf.reshape(elements, [-1, 1]), [1, dim]), [-1])
    row_indices = tf.tile(range_t, [dim])
    col_indices = tf.mod(tf.reshape(tf.reshape(range_t, [-1, 1]) + tf.reshape(
        range_t, [1, -1]), [-1]), dim)
    indices = tf.stack([row_indices, col_indices], axis=1)
    return tf.scatter_nd(indices=indices, updates=tiled, shape=[dim, dim])

Result:

tf.Session().run(circulant([1,2,3,4,5,6]))

array([[1, 2, 3, 4, 5, 6],
       [6, 1, 2, 3, 4, 5],
       [5, 6, 1, 2, 3, 4],
       [4, 5, 6, 1, 2, 3],
       [3, 4, 5, 6, 1, 2],
       [2, 3, 4, 5, 6, 1]], dtype=int32)

Upvotes: 1

Related Questions