예제 #1
0
    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)
예제 #2
0
    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)