def solve(self, B): # modified Algorithm 2.3.4 of Cohen's book """ Return solution X for self * X = B (B is a vector). This function returns tuple (V, M) below. V: one solution as vector M: kernel of self as list of basis vectors. If you want only one solution, use 'inverseImage'. Warning: B should not be a matrix instead of a vector """ M_1 = self.copy() M_1.insertColumn(self.column + 1, B.compo) M_1._cohensSimplify = types.MethodType(parallel_cohens, M_1) V = M_1.kernel() ker = [] flag = False if not V: raise NoInverseImage("no solution") n = V.row for j in range(1, V.column + 1): if not bool(V[n, j]): # self's kernel ker.append(vector.Vector([V[i, j] for i in range(1, n)])) elif not (flag): d = -ring.inverse(V[n, j]) sol = vector.Vector([V[i, j] * d for i in range(1, n)]) flag = True if not (flag): raise NoInverseImage("no solution") return sol, ker
def parallel_cohens(self): """ NS: Add some parallel processing to the cohensSimplify procedure _cohensSimplify is a common process used in image() and kernel() Return a tuple of modified matrix M, image data c and kernel data d. """ print >>sys.stderr, "Parallel Cohens simplify %dx%d" % (self.row, self.column) M = self.copy() c = [0] * (M.row + 1) d = [-1] * (M.column + 1) Mpr = [pack_vector(M.getRow(i)) for i in range1(M.row)] for k in range(1, M.column + 1): for j in range(1, M.row + 1): if not c[j] and Mpr[j - 1][0][k - 1]: break else: # not found j such that m(j, k)!=0 and c[j]==0 d[k] = 0 continue Mj = unpack_vector(Mpr[j - 1]) top = -ring.inverse(Mj[k]) Mj[k] = -self.coeff_ring.one for s in range(k + 1, M.column + 1): Mj[s] = top * Mj[s] Mjp = pack_vector(Mj) Mpr[j - 1] = Mjp work = [(Mpr[i - 1], Mjp, k) for i in range(1, M.row + 1) if i != j] result = pool.pool().map(cohens_worker, work) i = 1 for v in result: if i != j: Mpr[i - 1] = v else: i += 1 Mpr[i - 1] = v i += 1 c[j] = k d[k] = j for i in range(1, M.row + 1): M.setRow(i, unpack_vector(Mpr[i - 1])) return (M, c, d)
def reduce_groebner(gbasis, order): """ Return the reduced Groebner basis constructed from a Groebner basis. 1) lb(f) divides lb(g) => g is not in reduced Groebner basis 2) monic """ reduced_basis = [] lb_rel = dict([(order.leading_term(g)[0], g) for g in gbasis]) lbs = sorted([order.leading_term(g)[0] for g in gbasis])[::-1] for i, lbi in enumerate(lbs): for lbj in lbs[(len(lbs) - 1) : i : -1]: if lbi == lbj.lcm(lbi): # divisor found break else: g = lb_rel[lbi] if g[lbi] != ring.getRing(g[lbi]).one: # make it monic g = g.scalar_mul(ring.inverse(g[lbi])) reduced_basis.append(g) return reduced_basis
def reduce_groebner(gbasis, order): """ Return the reduced Groebner basis constructed from a Groebner basis. 1) lb(f) divides lb(g) => g is not in reduced Groebner basis 2) monic """ reduced_basis = [] lb_rel = dict([(order.leading_term(g)[0], g) for g in gbasis]) lbs = sorted([order.leading_term(g)[0] for g in gbasis])[::-1] for i, lbi in enumerate(lbs): for lbj in lbs[(len(lbs) - 1):i:-1]: if lbi == lbj.lcm(lbi): # divisor found break else: g = lb_rel[lbi] if g[lbi] != ring.getRing(g[lbi]).one: # make it monic g = g.scalar_mul(ring.inverse(g[lbi])) reduced_basis.append(g) return reduced_basis
def testRational(self): self.assertEqual(rational.Rational(3, 2), ring.inverse(rational.Rational(2, 3)))
def testComplex(self): self.assertEqual(-1j, ring.inverse(1j))
def testFloat(self): self.assertEqual(0.5, ring.inverse(2.0))
def testInt(self): self.assertEqual(rational.Rational(1, 2), ring.inverse(2))