def test_lstsq_returns_expected_values(self, arrays): m_ss, m_sb, m_bb, m_bs = arrays hy.assume(hn.wide(m_sb)) cond_bs = np.linalg.cond(m_bs).max() cond_sb = np.linalg.cond(m_sb).max() # overconstrained x_sb = gfl.lstsq(m_bs, m_bb) m_bst = la.dagger(m_bs) # with self.subTest(msg='lstsq(over)'): self.assertArrayAllClose(m_bst @ m_bs @ x_sb, m_bst @ m_bb, cond=cond_bs) x_bs = gfl.rlstsq(m_bb, m_sb) m_sbt = la.dagger(m_sb) # with self.subTest(msg='rlstsq(over)'): self.assertArrayAllClose(x_bs @ m_sb @ m_sbt, m_bb @ m_sbt, cond=cond_sb) # underconstrained x_bs = gfl.lstsq(m_sb, m_ss) # with self.subTest(msg='lstsq(under)'): self.assertArrayAllClose(m_sb @ x_bs, m_ss, cond=cond_sb) x_sb = gfl.rlstsq(m_ss, m_bs) # with self.subTest(msg='rlstsq(under)'): self.assertArrayAllClose(x_sb @ m_bs, m_ss, cond=cond_bs)
def test_rlstsq_flexible_signature_with_vectors_mv(self, arrays): m_sb, m_bs = arrays[:-2] v_s, v_b = hn.core_only(*arrays[-2:], dims=1) wide, tall = [arr.shape for arr in arrays[:-2]] hy.assume(hn.wide(m_sb)) self.assertArrayShape(gfl.rlstsq(m_sb, v_b), wide[:-1]) self.assertArrayShape(gfl.rlstsq(m_bs, v_s), tall[:-1]) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rlstsq(m_bs, v_b)
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_rlstsq_flexible_signature_with_vectors_vm(self, arrays): m_sb, m_bs = arrays[:-2] v_s, v_b = hn.core_only(*arrays[-2:], dims=1) wide, tall = [arr.shape for arr in arrays[:-2]] hy.assume(hn.wide(m_sb)) off_b, y_one = utn.make_off_by_one(m_sb, m_bs) self.assertArrayShape(gfl.rlstsq(v_b, m_sb), wide[:-1]) self.assertArrayShape(gfl.rlstsq(v_s, m_bs), tall[:-1]) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rlstsq(v_b, m_bs) with self.assertRaisesRegex(*utn.core_dim_err): # This would succeed/broadcast error if interpreted as vM: gfl.rlstsq(m_bs[y_one], m_sb[off_b])
def test_rlstsq_qr_returns_expected_values_with_wide(self, arrays, fun): m_ss, m_sb, m_bb = arrays hy.assume(hn.wide(m_sb)) hy.assume(hn.all_well_behaved(m_sb)) cond = np.linalg.cond(m_sb).max() # overconstrained x0_bs = gfl.rlstsq(m_bb, m_sb) # overconstrained x_bs, x_f, tau = fun(m_bb, m_sb) # with self.subTest('rlstsq_qr(under,' + suffix): self.assertArrayAllClose(x_bs, x0_bs, cond=cond) # overconstrained xx_bs = gfl.rqr_lstsq(m_bb, x_f, tau) # with self.subTest('rqr_rlstsq(under,' + suffix): self.assertArrayAllClose(xx_bs, x0_bs, cond=cond) # underconstrained y_bs = gfl.qr_lstsq(x_f, tau, m_ss) # with self.subTest('qr_rlstsq(over,' + suffix): self.assertArrayAllClose(m_sb @ y_bs, m_ss, cond=cond)
def test_rlstsq_flexible_signature_with_vectors_vv(self, v_s, v_b): hy.assume(len(v_s) != len(v_b)) self.assertArrayShape(gfl.rlstsq(v_s, v_s), ()) with self.assertRaisesRegex(*utn.core_dim_err): gfl.rlstsq(v_s, v_b)