Reputation: 11
I'm looking for the best way to do the equivalent to scipy.linalg.circulant
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
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