def _get_element_nullspace(self, M): ## We take the domain where our elements will lie ## conversion->lazy domain->domain parent = self.__conversion.base().base() ## We assume the matrix is in the correct space M = self.__conversion.simplify(M) ## We clean denominators to lie in the polynomial ring lcms = [lcm([el.denominator() for el in row]) for row in M] R = M.parent().base().base() M = Matrix(R, [[el * lcms[i] for el in M[i]] for i in range(M.nrows())]) f = lambda p: self.__smart_is_null(p) try: assert (f(1) == False) except Exception: raise ValueError("The method to check membership is not correct") from sage.rings.polynomial.polynomial_ring import is_PolynomialRing as isUniPolynomial from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing as isMPolynomial ## Computing the kernell of the matrix if (isUniPolynomial(R) or isMPolynomial(R)): bareiss_algorithm = BareissAlgorithm(R, M, f) ker = bareiss_algorithm.syzygy().transpose() ## If some relations are found during this process, we add it to the conversion system self.__conversion.add_relations(bareiss_algorithm.relations()) else: ker = [v for v in M.right_kernel_matrix()] ## If the nullspace has high dimension, we try to reduce the final vector computing zeros at the end aux = [row for row in ker] i = 1 while (len(aux) > 1): new = [] current = None for j in range(len(aux)): if (aux[j][-(i)] == 0): new += [aux[j]] elif (current is None): current = j else: new += [ aux[current] * aux[j][-(i)] - aux[j] * aux[current][-(i)] ] current = j aux = [el / gcd(el) for el in new] i = i + 1 ## When exiting the loop, aux has just one vector sol = aux[0] sol = [self.__conversion.simplify(a) for a in sol] ## This steps for clearing denominator are no longer needed #lazyLcm = lcm([a.denominator() for a in sol]) #finalLazySolution = [a.numerator()*(lazyLcm/(a.denominator())) for a in sol] ## Just to be sure everything is as simple as possible, we divide again by the gcd of all our ## coefficients and simplify them using the relations known. fin_gcd = gcd(sol) finalSolution = [a / fin_gcd for a in sol] finalSolution = [self.__conversion.simplify(a) for a in finalSolution] ## We transform our polynomial into elements of our destiny domain finalSolution = [ self.__conversion.to_real(a).raw() for a in finalSolution ] return vector(parent, finalSolution)
def _get_element_nullspace(self, M): ## We take the Conversion System R = self.__conversion ## We assume the matrix is in the correct space M = Matrix(R.poly_field(), [[R.simplify(el.poly()) for el in row] for row in M]) ## We clean denominators to lie in the polynomial ring lcms = [self.__get_lcm([el.denominator() for el in row]) for row in M] M = Matrix(R.poly_ring(), [[el * lcms[i] for el in M[i]] for i in range(M.nrows())]) f = lambda p: R(p).is_zero() try: assert (f(1) == False) except Exception: raise ValueError("The method to check membership is not correct") ## Computing the kernell of the matrix if (len(R.map_of_vars()) > 0): bareiss_algorithm = BareissAlgorithm( R.poly_ring(), M, f, R._ConversionSystem__relations) ker = bareiss_algorithm.syzygy().transpose() ## If some relations are found during this process, we add it to the conversion system R.add_relations(bareiss_algorithm.relations()) else: ker = [v for v in M.right_kernel_matrix()] ## If the nullspace has high dimension, we try to reduce the final vector computing zeros at the end aux = [row for row in ker] i = 1 while (len(aux) > 1): new = [] current = None for j in range(len(aux)): if (aux[j][-(i)] == 0): new += [aux[j]] elif (current is None): current = j else: new += [ aux[current] * aux[j][-(i)] - aux[j] * aux[current][-(i)] ] current = j aux = [el / gcd(el) for el in new] i = i + 1 ## When exiting the loop, aux has just one vector sol = aux[0] sol = [R.simplify(a) for a in sol] ## Just to be sure everything is as simple as possible, we divide again by the gcd of all our ## coefficients and simplify them using the relations known. fin_gcd = gcd(sol) finalSolution = [a / fin_gcd for a in sol] finalSolution = [R.simplify(a) for a in finalSolution] ## We transform our polynomial into elements of our destiny domain realSolution = [R.to_real(a) for a in finalSolution] for i in range(len(realSolution)): try: realSolution[i].built = ("polynomial", (finalSolution[i], { str(key): R.map_of_vars()[str(key)] for key in finalSolution[i].variables() })) except AttributeError: pass return vector(R.base(), realSolution)