2
votes

I would like to create a lower triangular matrix with unit diagonal elements from a vector.

From a vector

[a_21, a_31, a_32, ..., a_N1, ... , a_N(N-1)]

how to convert it into a lower triangular matrix with unit diagonal elements of the form,

[[1, 0, ..., 0], [a_21, 1, ..., 0], [a_31, a_32, 1, ..., 0], ..., [a_N1, a_N2, ... , a_N(N-1), 1]]

So far with NumPy

import numpy
A = np.eye(N)
idx = np.tril_indices(N, k=-1)
A[idx] = X

The TensorFlow, however, doesn't support item assignment. I think fill_triangular or tf.reshape help solve the problem, but I'm not sure how to do it.

2

2 Answers

1
votes

I found the similar question and answer: Packing array into lower triangular of a tensor

Based on the page above, I made a function which transform a vector into a lower triangular with unit diagonal elements:

def flat_to_mat_TF(vector, n):
    idx = list(zip(*np.tril_indices(n, k=-1)))
    idx = tf.constant([list(i) for i in idx], dtype=tf.int64)
    values = tf.constant(vector, dtype=tf.float32)

    dense = tf.sparse_to_dense(sparse_indices=idx, output_shape=[n, n], \
                               sparse_values=values, default_value=0, \
                               validate_indices=True)
    mat = tf.matrix_set_diag(dense, tf.cast(tf.tile([1], [n]), dtype=tf.float32))
    return mat

If the input vector is already a Tensor, values = tf.constant() could be eliminated.

0
votes

You could use fill_triangular_inverse on an ascending array (e.g. like one from np.arange).

Then you have the indices how they end up in the lower triangle and you can apply them to your array to resort it and pass it to fill_triangular.