def test_return_array_types(self, arrays): m_sb_n, m_bs_n = arrays[:2] m_sb, m_bs, m_ss, m_bb = view_as(*arrays) m_bs_m, m_ss_m, m_bb_m = hn.core_only(m_bs, m_ss, m_bb) hy.assume(hn.all_well_behaved(m_ss, m_bb)) hy.assume(m_sb.ndim != m_ss.ndim - 1) # np..solve's broadcasting issue self.assertIsInstance(m_sb @ m_bs, la.lnarray) self.assertIsInstance(m_sb_n @ m_bs, la.lnarray) expect = utn.array_return_shape('(a,b),(b,c)->(a,c)', m_bs, m_sb) tw_o = np.empty(expect, m_bs.dtype) tw_r = la.matmul(m_bs, m_sb_n, tw_o) self.assertIsInstance(tw_r, np.ndarray) self.assertIsInstance(tw_o, np.ndarray) self.assertIsInstance(np.matmul(m_bs, m_sb_n), np.ndarray) self.assertIsInstance(la.solve(m_ss, m_sb_n), la.lnarray) self.assertIsInstance(nl.solve(m_ss, m_sb_n), np.ndarray) self.assertIsInstance(la.lstsq(m_bs, m_bb), la.lnarray) self.assertIsInstance( nl.lstsq(m_bs_m, m_bb_m, rcond=None)[0], np.ndarray) self.assertIsInstance(la.lu(m_ss)[0], la.lnarray) self.assertIsInstance(la.lu(m_bs_n)[0], np.ndarray) self.assertIsInstance(la.qr(m_ss)[0], la.lnarray) self.assertIsInstance(la.qr(m_bs_n)[0], np.ndarray) self.assertIsInstance(la.lq(m_ss)[0], la.lnarray) self.assertIsInstance(la.lq(m_bs_n)[0], np.ndarray) self.assertIsInstance(la.lqr(m_ss)[0], la.lnarray) self.assertIsInstance(la.lqr(m_bs_n)[0], np.ndarray) self.assertIsInstance(nl.qr(m_ss_m)[0], np.ndarray)
def test_functions_lstsq(self, arrays): m_ss, m_sb, m_bb, m_bs = arrays[:-1] v_b = hn.core_only(arrays[-1], dims=1) hy.assume(hn.wide(m_sb)) cond_sb = np.linalg.cond(m_sb).max() cond_bs = np.linalg.cond(m_bs).max() # with self.subTest('lstsq'): self.assertArrayAllClose(la.lstsq(m_bs, m_bb), gf.lstsq(m_bs, m_bb), cond=cond_bs) self.assertArrayAllClose(la.lstsq(m_sb, m_ss), gf.lstsq(m_sb, m_ss), cond=cond_sb) lsq_sh = utn.array_return_shape('(a,b),(a,c)->(b,c)', m_bs, m_bb) lsq_out = np.empty(lsq_sh, m_bs.dtype) lsq_r = la.lstsq(m_bs, m_bb, out=lsq_out) self.assertArrayAllClose(lsq_out, lsq_r) # with self.subTest('rlstsq'): self.assertArrayAllClose(la.rlstsq(m_ss, m_bs), gf.rlstsq(m_ss, m_bs), cond=cond_bs) self.assertArrayAllClose(la.rlstsq(v_b, m_sb), gf.rlstsq(v_b, m_sb), cond=cond_sb)
def test_rtrue_divide_returns_expected_shapes(self, arrays): a_bs, m_bs = arrays a_bs[np.abs(a_bs) < 1e-5] += 1. expect = utn.array_return_shape('(),()->()', a_bs, m_bs) self.assertArrayShape(self.gfm.rtrue_divide(a_bs, m_bs), expect) with self.assertRaisesRegex(*utn.broadcast_err): self.gfm.rtrue_divide(*utn.make_bad_broadcast(m_bs, a_bs))
def test_rlstsq_returns_expected_shape(self, arrays): m_ss, m_sb, m_bb, m_bs = arrays hy.assume(hn.wide(m_sb)) # with self.subTest('underconstrained'): expect = utn.array_return_shape('(m,n),(p,n)->(m,p)', m_ss, m_bs) self.assertArrayShape(gfl.rlstsq(m_ss, m_bs), expect) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rlstsq(m_sb, m_bs) with self.assertRaisesRegex(*utn.broadcast_err): gfl.rlstsq(*utn.make_bad_broadcast(m_ss, la.transpose(m_sb))) # with self.subTest('overconstrained'): expect = utn.array_return_shape('(m,n),(p,n)->(m,p)', m_bb, m_sb) self.assertArrayShape(gfl.rlstsq(m_bb, m_sb), expect) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rlstsq(m_bs, m_sb) with self.assertRaisesRegex(*utn.broadcast_err): gfl.rlstsq(*utn.make_bad_broadcast(m_bb, la.transpose(m_bs)))
def test_rmatmul_returns_expected_values(self, arrays): m_sb, m_bs = arrays expect = utn.array_return_shape('(a,b),(b,c)->(a,c)', m_sb, m_bs) pout = np.empty(expect, m_sb.dtype) pres = self.gfm.rmatmul(m_bs, m_sb, out=pout) prod = np.matmul(m_sb, m_bs) self.assertArrayAllClose(pres, prod) self.assertArrayAllClose(pout, prod)
def test_rqr_lstsq_returns_expected_shape_wide(self, arrays, fun): m_ss, m_sb, m_bb, m_bs = arrays hy.assume(hn.wide(m_sb)) hy.assume(hn.all_well_behaved(m_sb)) _, x_f, tau = fun(m_bb, m_sb) expect = utn.array_return_shape('(n,m),(m,p)->(n,p)', x_f, m_ss) self.assertArrayShape(gfl.qr_lstsq(x_f, tau, m_ss), expect) expect = utn.array_return_shape('(m,n),(n,p)->(m,p)', m_bb, x_f) self.assertArrayShape(gfl.rqr_lstsq(m_bb, x_f, tau), expect) with self.assertRaisesRegex(*utn.core_dim_err): gfl.qr_lstsq(x_f, tau, m_bs) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rqr_lstsq(m_bs, x_f, tau) with self.assertRaisesRegex(*utn.broadcast_err): gfl.qr_lstsq(x_f, *utn.make_bad_broadcast(tau, m_ss, (1, 2))) x_f, tau = unbroadcast_factors(m_sb, x_f, tau) expect = utn.array_return_shape('(m,n),(m,p)->(n,p)', m_sb, m_ss) self.assertArrayShape(gfl.qr_lstsq(x_f, tau, m_ss), expect)
def test_rtrue_divide_returns_expected_values(self, arrays): a_bs, m_bs = arrays expect = utn.array_return_shape('(),()->()', a_bs, m_bs) zout = np.empty(expect, m_bs.dtype) a_bs[np.abs(a_bs) < 1e-5] += 1. zres = self.gfm.rtrue_divide(a_bs, m_bs, out=zout) zzz = m_bs / a_bs self.assertArrayAllClose(zres, zzz) self.assertArrayAllClose(zout, zzz)
def test_rmatmul_returns_expected_shapes(self, arrays): m_sb, m_bs = arrays hy.assume(hn.nonsquare(m_sb)) hy.assume(hn.nonsquare(m_bs)) expect = utn.array_return_shape('(a,b),(b,c)->(a,c)', m_sb, m_bs) self.assertArrayShape(self.gfm.rmatmul(m_bs, m_sb), expect) with self.assertRaisesRegex(*utn.core_dim_err): self.gfm.rmatmul(m_bs, m_bs) with self.assertRaisesRegex(*utn.broadcast_err): self.gfm.rmatmul(*utn.make_bad_broadcast(m_bs, m_sb))
def test_rlu_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_bb)) _, x_f, i_p = gfl.rsolve_lu(m_sb, m_bb) expect = utn.array_return_shape('(a,b),(b,b)->(a,b)', m_sb, x_f) self.assertArrayShape(gfl.rlu_solve(m_sb, x_f, i_p), expect) expect = utn.array_return_shape('(a,a),(a,b)->(a,b)', x_f, m_bs) self.assertArrayShape(gfl.lu_solve(x_f, i_p, m_bs), expect) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rlu_solve(m_ss, x_f, i_p) with self.assertRaisesRegex(*utn.core_dim_err): gfl.lu_solve(x_f, i_p, m_sb) _, x_f, i_p = gfl.rsolve_lu(m_sb, m_bb) with self.assertRaisesRegex(*utn.broadcast_err): gfl.rlu_solve(*utn.make_bad_broadcast(m_sb, x_f), i_p) x_f, i_p = unbroadcast_factors(m_bb, x_f, i_p) expect = utn.array_return_shape('(a,a),(a,b)->(a,b)', m_bb, m_bs) self.assertArrayShape(gfl.lu_solve(x_f, i_p, m_bs), expect)
def test_rsolve_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_bb)) expect = utn.array_return_shape('(a,b),(b,b)->(a,b)', m_sb, m_bb) self.assertArrayShape(gfl.rsolve(m_sb, m_bb), expect) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rsolve(m_bs, m_bb) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rsolve(m_bs, m_sb) with self.assertRaisesRegex(*utn.broadcast_err): gfl.rsolve(*utn.make_bad_broadcast(m_bs, m_ss))
def test_rlstsq_qr_returns_expected_shape_wide(self, arrays, fun): _, m_sb, m_bb, m_bs = arrays hy.assume(hn.wide(m_sb)) hy.assume(hn.all_well_behaved(m_sb)) wide = m_sb.shape expect = utn.array_return_shape('(m,n),(p,n)->(m,p),(n,p)', m_bb, m_sb) tau = expect[1][:-2] + tau_len(m_sb, fun) result = fun(m_bb, m_sb) self.assertArrayShapesAre(result, expect + (tau, )) self.assertArrayShapesAre(unbroadcast_factors(m_sb, *result[1:]), (utn.trnsp(wide), wide[:-2] + tau[-1:])) with self.assertRaisesRegex(*utn.core_dim_err): fun(m_bs, m_sb) with self.assertRaisesRegex(*utn.broadcast_err): fun(*utn.make_bad_broadcast(m_bb, la.transpose(m_bs)))
def test_lstsq_qr_returns_expected_shape_tall(self, arrays, fun): m_sb, m_bb, m_bs = arrays hy.assume(hn.tall(m_bs)) hy.assume(hn.all_well_behaved(m_bs)) tall = m_bs.shape expect = utn.array_return_shape('(m,n),(m,p)->(n,p),(n,m)', m_bs, m_bb) tau = expect[1][:-2] + tau_len(m_bs, fun) result = fun(m_bs, m_bb) self.assertArrayShapesAre(result, expect + (tau, )) self.assertArrayShapesAre(unbroadcast_factors(m_bs, *result[1:]), (utn.trnsp(tall), tall[:-2] + tau[-1:])) with self.assertRaisesRegex(*utn.core_dim_err): fun(m_bs, m_sb) with self.assertRaisesRegex(*utn.broadcast_err): fun(*utn.make_bad_broadcast(m_bs, m_bb))
def test_functions_solve(self, arrays): m_ss, m_sb, m_bs = arrays hy.assume(hn.all_well_behaved(m_ss)) cond = np.linalg.cond(m_ss).max() # with self.subTest('solve'): self.assertArrayAllClose(la.solve(m_ss, m_sb), gf.solve(m_ss, m_sb), cond=cond) slv_sh = utn.array_return_shape('(a,a),(a,b)->(a,b)', m_ss, m_sb) slv_out = np.empty(slv_sh, m_ss.dtype) slv_r = la.solve(m_ss, m_sb, out=slv_out) self.assertArrayAllClose(slv_out, slv_r) # with self.subTest('rsolve'): self.assertArrayAllClose(la.rsolve(m_bs, m_ss), gf.rsolve(m_bs, m_ss), cond=cond)
def test_rsolve_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_bb)) expect = utn.array_return_shape('(a,b),(b,b)->(a,b)', m_sb, m_bb) expect_f = expect[:-2] + m_bb.shape[-2:] result = gfl.rsolve_lu(m_sb, m_bb) self.assertArrayShapesAre(result, (expect, expect_f, expect_f[:-1])) self.assertArrayShapesAre(unbroadcast_factors(m_bb, *result[1:]), (m_bb.shape, m_bb.shape[:-1])) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rsolve_lu(m_bs, m_bb) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rsolve_lu(m_bs, m_sb) with self.assertRaisesRegex(*utn.broadcast_err): gfl.rsolve_lu(*utn.make_bad_broadcast(m_bs, m_ss))
def test_functions_matldiv(self, arrays): m_ss, m_sb, m_bb, m_bs = arrays hy.assume(hn.all_well_behaved(m_ss)) hy.assume(hn.wide(m_sb)) # with self.subTest('solve'): self.assertArrayAllClose(la.matldiv(m_ss, m_sb), gf.solve(m_ss, m_sb)) slv_sh = utn.array_return_shape('(a,a),(a,b)->(a,b)', m_ss, m_sb) slv_out = np.empty(slv_sh, m_ss.dtype) slv_r = la.matldiv(m_ss, m_sb, out=slv_out) cond = np.linalg.cond(m_ss).max() self.assertArrayAllClose(slv_out, slv_r, cond=cond) # with self.subTest('lstsq'): cond = np.linalg.cond(m_bs).max() self.assertArrayAllClose(la.matldiv(m_bs, m_bb), gf.lstsq(m_bs, m_bb), cond=cond) cond = np.linalg.cond(m_sb).max() self.assertArrayAllClose(la.matldiv(m_sb, m_ss), gf.lstsq(m_sb, m_ss), cond=cond)
def test_rqr_lstsq_flexible_signature_with_vectors_mv(self, arrays, fun): m_sb, m_bs = hn.core_only(*arrays[:-1]) v_s = hn.core_only(arrays[-1], dims=1) wide, tall = [arr.shape[-2:] for arr in arrays[:-1]] hy.assume(hn.wide(m_sb)) hy.assume(la.norm(v_s) > 0.) _, x_f, tau = fun(m_bs, v_s) expect = utn.array_return_shape('(m,n),(n,p)->(m,p)', m_bs, m_sb)[:-1] self.assertArrayShape(gfl.qr_lstsq(x_f, tau, m_sb), expect) self.assertArrayShape(gfl.rqr_lstsq(m_bs, x_f, tau), tall[:-1]) with self.assertRaisesRegex(*utn.core_dim_err): gfl.qr_lstsq(x_f, tau, m_bs) self.assertArrayShape(gfl.rqr_lstsq(v_s, x_f, tau), tall[:-2]) m_sb, m_bs = arrays[:-1] wide, tall = [arr.shape for arr in arrays[:-1]] _, x_f, tau = fun(m_bs, v_s) x_f, tau = unbroadcast_factors(v_s, x_f, tau) self.assertArrayShape(gfl.qr_lstsq(x_f, tau, m_sb), utn.drop(wide)) self.assertArrayShape(gfl.rqr_lstsq(m_bs, x_f, tau), tall[:-1])
def test_lnarray_operations_return_expected_values(self, arrays): m_bs, m_ss, vec = view_as(*arrays) m_bs_m = hn.core_only(m_bs) vec = hn.core_only(vec, dims=1) hy.assume(hn.tall(m_bs)) hy.assume(m_ss.ndim != 3) # causes np..solve's broadcasting issue hy.assume(hn.all_well_behaved(m_ss, m_bs_m)) expect = utn.array_return_shape('(a,b),(b,c)->(a,c)', m_bs, m_ss) ts_o = np.empty(expect, m_ss.dtype) ts_r = la.matmul(m_bs, m_ss, ts_o) self.assertArrayAllClose(ts_r, ts_o) self.assertArrayAllClose(m_bs @ m_ss, np.matmul(m_bs, m_ss)) self.assertArrayAllClose(m_bs @ m_ss, np.matmul(m_bs, m_ss)) self.assertArrayAllClose(m_bs @ vec, np.matmul(m_bs, vec)) cond = np.linalg.cond(m_ss).max() self.assertArrayAllClose(gf.solve(m_ss, vec), nl.solve(m_ss, vec.c).uc, cond=cond) cond = np.linalg.cond(m_bs_m).max() self.assertArrayAllClose(gf.lstsq(m_bs_m.t, vec), nl.lstsq(m_bs_m.t, vec, rcond=None)[0], cond=cond) self.assertArrayAllClose(gf.rmatmul(m_ss, m_bs), np.matmul(m_bs, m_ss))