def test_lu_solve_returns_expected_shapes(self, arrays): m_ss, m_sb, m_bb, m_bs = arrays hy.assume(hn.nonsquare(m_sb)) hy.assume(hn.all_well_behaved(m_ss)) _, x_f, i_p = gfl.solve_lu(m_ss, m_sb) expect = utn.array_return_shape('(a,a),(a,b)->(a,b)', m_ss, m_sb) self.assertArrayShape(gfl.lu_solve(x_f, i_p, m_sb), expect) expect = utn.array_return_shape('(a,b),(b,b)->(a,b)', m_bs, x_f) self.assertArrayShape(gfl.rlu_solve(m_bs, x_f, i_p), expect) with self.assertRaisesRegex(*utn.core_dim_err): gfl.lu_solve(x_f, i_p, m_bb) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rlu_solve(m_sb, x_f, i_p) _, x_f, i_p = gfl.solve_lu(m_ss, m_sb) with self.assertRaisesRegex(*utn.broadcast_err): gfl.lu_solve(x_f, *utn.make_bad_broadcast(i_p, m_sb, (1, 2))) x_f, i_p = unbroadcast_factors(m_ss, x_f, i_p) expect = utn.array_return_shape('(a,b),(b,b)->(a,b)', m_bs, m_ss) self.assertArrayShape(gfl.rlu_solve(m_bs, x_f, i_p), expect)
def test_solve_lu_returns_expected_values(self, arrays): m_ss, m_sb, m_bs = arrays hy.assume(hn.all_well_behaved(m_ss)) cond = np.linalg.cond(m_ss).max() x0_sb = gfl.solve(m_ss, m_sb) x_sb, x_f, i_p = gfl.solve_lu(m_ss, m_sb) # with self.subTest('solve0'): self.assertArrayAllClose(x_sb, x0_sb, cond=cond) xx_sb = gfl.lu_solve(x_f, i_p, m_sb) # with self.subTest('solve(lu)'): self.assertArrayAllClose(xx_sb, x0_sb, cond=cond) x_bs = gfl.rlu_solve(m_bs, x_f, i_p) # with self.subTest('rsolve(lu)'): self.assertArrayAllClose(x_bs @ m_ss, m_bs, cond=cond)
def test_lu_solve_flexible_signature_with_vectors(self, arrays): m_ss = arrays[0] v_s, v_b = hn.core_only(*arrays[1:], dims=1) hy.assume(len(v_s) != len(v_b)) hy.assume(hn.all_well_behaved(m_ss)) # with self.subTest('lu_solve'): _, x_f, i_p = gfl.solve_lu(m_ss, v_s) self.assertArrayShape(gfl.lu_solve(x_f, i_p, v_s), m_ss.shape[:-1]) with self.assertRaisesRegex(*utn.core_dim_err): gfl.lu_solve(x_f, i_p, v_b) # with self.subTest('rlu_solve'): self.assertArrayShape(gfl.rlu_solve(v_s, x_f, i_p), m_ss.shape[:-1]) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rlu_solve(v_b, x_f, i_p)
def test_solve_lu_flexible_signature_with_vectors(self, arrays): m_ss, m_sb, m_bb, m_bs = arrays[:-1] v_s = hn.core_only(arrays[-1], dims=1) hy.assume(hn.nonsquare(m_sb)) hy.assume(hn.all_well_behaved(m_ss)) off_b, y_one = utn.make_off_by_one(m_bb, m_sb) # with self.subTest('solve_lu'): self.assertArrayShapesAre(gfl.solve_lu( m_ss, v_s), (m_ss.shape[:-1], m_ss.shape, m_ss.shape[:-1])) with self.assertRaisesRegex(*utn.core_dim_err): gfl.solve_lu(m_bb, v_s) with self.assertRaisesRegex(*utn.core_dim_err): gfl.solve_lu(m_bs, v_s) with self.assertRaisesRegex(*utn.core_dim_err): # This would succeed/broadcast error if interpreted as Mv: gfl.solve_lu(m_bb[off_b], m_sb[y_one])
def test_solve_lu_returns_expected_shapes(self, arrays): m_ss, m_sb, m_bb, m_bs = arrays hy.assume(hn.nonsquare(m_sb)) hy.assume(hn.all_well_behaved(m_ss)) expect = utn.array_return_shape('(a,a),(a,b)->(a,b)', m_ss, m_sb) expect_f = expect[:-2] + 2 * m_ss.shape[-1:] result = gfl.solve_lu(m_ss, m_sb) self.assertArrayShapesAre(result, (expect, expect_f, expect_f[:-1])) self.assertArrayShapesAre(unbroadcast_factors(m_ss, *result[1:]), (m_ss.shape, m_ss.shape[:-1])) with self.assertRaisesRegex(*utn.core_dim_err): gfl.solve_lu(m_bb, m_sb) with self.assertRaisesRegex(*utn.core_dim_err): gfl.solve_lu(m_bs, m_sb) with self.assertRaisesRegex(*utn.broadcast_err): gfl.solve_lu(*utn.make_bad_broadcast(m_ss, m_sb))