def right_qr_maxvol(nd): cr = nd.core.copy() r1, n, r2 = cr.shape Rv = nd.edges[1].Rv.copy() cr = np.tensordot(cr, Rv, 1) r2 = cr.shape[2] cr = reshape(cr, (r1, -1)) cr = cr.T q, Rv = np.linalg.qr(cr) ind, c = maxvol(q) Rv = np.dot(q[ind, :], Rv) #q = np.linalg.solve(q[ind, :].T, q.T).T q = c.copy() nd.edges[0].Rv = Rv.T.copy() q = reshape(q.T, (-1, n, r2)) nd.core = q.copy() nd.maxvol_right = np.unravel_index(ind, (n, r2), order='F') """ Recomputation of right indices goes here """ """ Finally, update indices """ i_right = nd.edges[1].ind_right w1 = mkron(np.ones((r2, 1), dtype=np.int32), reshape(np.arange(n, dtype=np.int32), (-1, 1))) try: w2 = mkron(i_right, np.ones((n, 1), dtype=np.int32)) i_next = np.hstack((w1, w2)) except: i_next = w1 i_next = reshape(i_next, (n * r2, -1)) i_next = i_next[ind, :] nd.edges[0].ind_right = i_next.copy() nd.edges[0].ind_right_add = i_next.copy()
def right_qr_maxvol(nd): cr = nd.core.copy() r1, n, r2 = cr.shape Rv = nd.edges[1].Rv.copy() cr = np.tensordot(cr, Rv, 1) r2 = cr.shape[2] cr = reshape(cr, (r1, -1)) cr = cr.T q, Rv = np.linalg.qr(cr) ind, c = maxvol(q) Rv = np.dot(q[ind, :], Rv) #q = np.linalg.solve(q[ind, :].T, q.T).T q = c.copy() nd.edges[0].Rv = Rv.T.copy() q = reshape(q.T, (-1, n, r2)) nd.core = q.copy() nd.maxvol_right = np.unravel_index(ind, (n, r2), order='F') """ Recomputation of right indices goes here """ """ Finally, update indices """ i_right = nd.edges[1].ind_right w1 = mkron(np.ones((r2, 1), dtype=np.int32), reshape(np.arange(n, dtype=np.int32),(-1, 1))) try: w2 = mkron(i_right, np.ones((n, 1), dtype=np.int32)) i_next = np.hstack((w1, w2)) except: i_next = w1 i_next = reshape(i_next, (n * r2, -1)) i_next = i_next[ind, :] nd.edges[0].ind_right = i_next.copy() nd.edges[0].ind_right_add = i_next.copy()
def left_qr_maxvol(nd): cr = nd.core.copy() r1, n1, r2 = cr.shape cr = np.tensordot(nd.edges[0].Ru, cr, 1) #nd.edges[0].Ru = np.ones((1, 1)) r1 = cr.shape[0] cr = reshape(cr, (r1 * n1, r2)) q, Ru = qr(cr) ind, c = maxvol(q) Ru = np.dot(q[ind, :], Ru) q = c.copy() nd.core = reshape(q, (r1, n1, r2)).copy() nd.edges[1].Ru = Ru.copy() nd.maxvol_left = np.unravel_index(ind, (r1, n1), order='F') #The philosophical question if this index should be stored on the edge or in the node #The typical recomputation: #Take left index somewhere and update. For the first node it comes from the left edge #So, we can store ind_left on an edge, whereas ind_left_add in the node """ This is a logically separate function """ i_left = nd.edges[0].ind_left #Update index w1 = mkron(np.ones((n1, 1), dtype=np.int32), i_left) w2 = mkron(reshape(np.arange(n1, dtype=np.int32), (-1, 1)), np.ones((r1, 1), dtype=np.int32)) i_next = np.hstack((w1, w2)) i_next = reshape(i_next, (r1 * n1, -1)) i_next = i_next[ind, :] nd.edges[1].ind_left = i_next.copy() nd.edges[1].ind_left_add = i_next.copy()
def left_qr_maxvol(nd): cr = nd.core.copy() r1, n1, r2 = cr.shape cr = np.tensordot(nd.edges[0].Ru, cr, 1) #nd.edges[0].Ru = np.ones((1, 1)) r1 = cr.shape[0] cr = reshape(cr, (r1 * n1, r2)) q, Ru = qr(cr) ind, c = maxvol(q) Ru = np.dot(q[ind, :], Ru) q = c.copy() nd.core = reshape(q, (r1, n1, r2)).copy() nd.edges[1].Ru = Ru.copy() nd.maxvol_left = np.unravel_index(ind, (r1, n1), order='F') #The philosophical question if this index should be stored on the edge or in the node #The typical recomputation: #Take left index somewhere and update. For the first node it comes from the left edge #So, we can store ind_left on an edge, whereas ind_left_add in the node """ This is a logically separate function """ i_left = nd.edges[0].ind_left #Update index w1 = mkron(np.ones((n1, 1), dtype=np.int32), i_left) w2 = mkron(reshape(np.arange(n1, dtype=np.int32),(-1, 1)), np.ones((r1, 1), dtype=np.int32)) i_next = np.hstack((w1, w2)) i_next = reshape(i_next, (r1 * n1, -1)) i_next = i_next[ind, :] nd.edges[1].ind_left = i_next.copy() nd.edges[1].ind_left_add = i_next.copy()