Exemple #1
0
    def get_R_i_for(self, coeffs, var):
        # TODO: Rewrite this function in a more pythonic way.
        N_p = 0
        numerator = 0.0
        denominator = 0.0

        for k in [
                x for x in self.clean_c_matrix.expectances
                if not x == sympy.S(1.0)
        ]:
            degree = sum(list(sympy.degree_list(k)))
            N_p = max([degree, N_p])  # Isn't this the same as 'self.order'?

        for k in [
                x for x in self.clean_c_matrix.expectances
                if not x == sympy.S(1.0)
        ]:
            if list(sympy.degree_list(k, gens=var))[0] == N_p:
                numerator = (coeffs.get(k, 0.0)**
                             2) * self.clean_c_matrix.expectances[k]
            if sum(list(sympy.degree_list(k))) == N_p:
                denominator += (coeffs.get(k, 0.0)**
                                2) * self.clean_c_matrix.expectances[k]

        numerator = [
            (coeffs.get(x, 0.0)**2) * self.clean_c_matrix.expectances[x]
            for x in self.clean_c_matrix.expectances if not x == sympy.S(1.0)
            and list(sympy.degree_list(x, gens=var))[0] == self.order
        ][0]

        if denominator == 0: return 0
        return numerator / denominator
Exemple #2
0
    def __init__(self, polynomials, variables):
        """
        A class that takes two lists, a list of polynomials and list of
        variables. Returns the Dixon matrix of the multivariate system.

        Parameters
        ----------
        polynomials : list of polynomials
            A  list of m n-degree polynomials
        variables: list
            A list of all n variables
        """
        self.polynomials = polynomials
        self.variables = variables

        self.n = len(self.variables)
        self.m = len(self.polynomials)

        a = IndexedBase("alpha")
        # A list of n alpha variables (the replacing variables)
        self.dummy_variables = [a[i] for i in range(self.n)]

        # A list of the d_max of each variable.
        self.max_degrees = [
            max(degree_list(poly)[i] for poly in self.polynomials)
            for i in range(self.n)
        ]
Exemple #3
0
def get_sos(poly, max_mult_power=3, epsilon=0.001):
    """
    :param poly: sympy polynomial
    :param max_mult_power:
    :param dsdp_solver:
    :param dsdp_options:
    :param eig_tol:
    :param epsilon:
    :return: string with status whether poly is a sum of squares of polynomials, and a sympy expression that is
    the SOSRF decomposition of the poly
    """

    # check polynomial is nonconstant and even-degreed in every variable
    if poly == 0:
        _status = 'Zero polynomial.'
        return _status, nan
    else:
        _poly_expanded = expand(poly)
        _degree_list = degree_list(_poly_expanded)
        _coeffs = _poly_expanded.coeffs()
        if np.all([_d == 0 for _d in _degree_list]):
            _status = 'Constant polynomial.'
            return _status, nan
        elif np.any([_d % 2 for _d in _degree_list]):
            _status = 'One of the variables in the polynomial has odd degree. Not a sum of squares.'
            return _status, nan
        elif np.all([_f >= 0 for _f in _coeffs]):
            _status = 'Exact SOS decomposition found.'
            return _status, _poly_expanded

    indices = np.array(list(poly.as_dict().keys()))
    monoms = get_pts_in_cvx_hull(indices)
    num_alpha = monoms.shape[0]
    if not num_alpha:
        _status = 'Error in computing monomial indices.'
        return _status, nan

    coeff_leading, max_even_divisor, remainder = get_max_even_divisor(poly)
    if remainder == 1:
        _status = 'Exact SOS decomposition found.'
        sos = coeff_leading * max_even_divisor
        return _status, sos
    else:
        _status = 'No exact SOS decomposition found.'
        sos = nan

        # let's try clearing denominators
        _mult = get_special_sos_multiplier(remainder)
        for r in range(max_mult_power):
            # r=1
            print(f'Trying multiplier power: {r}')
            status_, sos_ = get_sos_helper(poly=(_mult**r *
                                                 remainder).as_poly(),
                                           epsilon=epsilon)
            if status_ == 'Exact SOS decomposition found.':
                _status = status_
                sos = (1 / _mult**
                       r) * coeff_leading * max_even_divisor * sos_.as_expr()
                return _status, sos
    return _status, sos
    def __init__(self, polynomials, variables):
        """
        A class that takes two lists, a list of polynomials and list of
        variables. Returns the Dixon matrix of the multivariate system.

        Parameters
        ----------
        polynomials : list of polynomials
            A  list of m n-degree polynomials
        variables: list
            A list of all n variables
        """
        self.polynomials = polynomials
        self.variables = variables

        self.n = len(self.variables)
        self.m = len(self.polynomials)

        a = IndexedBase("alpha")
        # A list of n alpha variables (the replacing variables)
        self.dummy_variables = [a[i] for i in range(self.n)]

        # A list of the d_max of each variable.
        self.max_degrees = [
            max(degree_list(poly)[i] for poly in self.polynomials)
            for i in range(self.n)]
Exemple #5
0
    def check_condition_one(self, coeffs, j_k):
        numerator = sum([(coeffs[k]**2) * self.clean_c_matrix.expectances[k]
                         for k in coeffs if not k == sympy.S(1.0)
                         and sum(list(sympy.degree_list(k))) == self.order])
        denominator = sum([(coeffs[k]**2) * self.clean_c_matrix.expectances[k]
                           for k in coeffs if not k == sympy.S(1.0)])

        if denominator == 0:
            return False  # The number is a constant! No need to partition here

        eta_k = numerator / denominator
        return (eta_k**self.alpha) * j_k >= self.theta_1
Exemple #6
0
    def get_max_degrees(self, polynomial):
        r"""
        Returns a list of the maximum degree of each variable appearing
        in the coefficients of the Dixon polynomial. The coefficients are
        viewed as polys in x_1, ... , x_n.
        """
        deg_lists = [degree_list(Poly(poly, self.variables))
                     for poly in polynomial.coeffs()]

        max_degrees = [max(degs) for degs in zip(*deg_lists)]

        return max_degrees
Exemple #7
0
def get_sos(polynomial, max_mult_power=3, dsdp_solver='dsdp', dsdp_options=DSDP_OPTIONS, eig_tol=-1e-07, epsilon=1e-07):
    """
    :param polynomial: sympy polynomial
    :param max_mult_power:
    :param dsdp_solver:
    :param dsdp_options:
    :param eig_tol:
    :param epsilon:
    :return: string with status whether poly is a sum of squares of polynomials, and a sympy expression that is
    the SOSRF decomposition of the poly
    """
    if polynomial == 0:
        _status = 'Zero polynomial.'
        return _status, nan

    # check polynomial is nonconstant
    if np.all([_d == 0 for _d in degree_list(polynomial)]):
        _status = 'Constant polynomial.'
        return _status, nan

    poly_indices = np.array(list(polynomial.as_poly().as_dict().keys()))
    monoms = get_pts_in_cvx_hull(poly_indices)
    num_alpha = monoms.shape[0]

    if not num_alpha:
        _status = 'Error in computing monomial indices.'
        return _status, nan

    degree = polynomial.as_poly().degree()
    if degree % 2:
        _status = 'Polynomial has odd degree. Not a sum of squares.'
        return _status, nan

    coeff_leading, max_even_divisor, remainder = get_max_even_divisor(polynomial)
    if remainder == 1:
        _status = 'Exact SOS decomposition found.'
        sos = coeff_leading * max_even_divisor
    else:
        _mult = get_poly_multiplier(remainder)
        for r in range(max_mult_power):
            print(f'Trying multiplier power: {r}')
            status_, sos_ = get_sos_helper2((_mult ** r * remainder).as_poly())
            if status_ == 'Exact SOS decomposition found.':
                _status = 'Exact SOS decomposition found.'
                sos = (1 / _mult ** r) * coeff_leading * max_even_divisor * sos_.as_expr()
                break
        else:
            _status = 'No exact SOS decomposition found.'
            sos = nan
    return _status, sos
Exemple #8
0
    def get_dixon_matrix(self, polynomial):
        r"""
        Construct the Dixon matrix from the coefficients of polynomial
        \alpha. Each coefficient is viewed as a polynomial of x_1, ...,
        x_n.
        """

        # A list of coefficients (in x_i, ..., x_n terms) of the power
        # products a_1, ..., a_n in Dixon's polynomial.
        coefficients = polynomial.coeffs()

        max_degrees = [
            max(
                degree_list(Poly(poly, self.variables))[i]
                for poly in coefficients) for i in range(self.n)
        ]

        print('max_degrees = ', max_degrees, '\n')
        monomials = list(itermonomials_degree_list(self.variables,
                                                   max_degrees))

        monomials = sorted(monomials,
                           reverse=True,
                           key=monomial_key('lex', self.variables))

        print('monomials - column headers :: ', monomials, '\n')

        dixon_matrix = Matrix(
            [[Poly(c, *self.variables).coeff_monomial(m) for m in monomials]
             for c in coefficients])

        keep = [
            column for column in range(dixon_matrix.shape[-1])
            if any([element != 0 for element in dixon_matrix[:, column]])
        ]
        return dixon_matrix[:, keep]
Exemple #9
0
def DixonMatrix_apply(polys, xlist, alist):

    res = DixonPolynomial_apply(polys, xlist, alist)
    if isinstance(res, String):
        return res

    xsym = [i.to_sympy() for i in xlist.leaves]
    asym = [i.to_sympy() for i in alist.leaves]
    xasym = asym + xsym  ###concatenating the a,x lists
    dix_pol = res.to_sympy()
    if dix_pol == sympy.sympify(0):  ###check for zero
        return from_sympy(dix_pol)
    pol = sympy.poly(dix_pol, xasym)  ##create sympy.poly object
    maxdegvec = sympy.degree_list(
        pol, xasym
    )  ###this is MaxDegVec function in mathematica. No function was written since
    ###its built in
    # print(maxdegvec)
    res_in = []
    res_out = []
    mat_dim_col = 1
    mat_dim_row = 1
    for i in range(len(maxdegvec) // 2):
        mat_dim_row = mat_dim_row * (
            maxdegvec[i] + 1
        )  ###Number of rows in the matrix equal to the monomials that can be
        #formed from the a list
    for i in range(len(maxdegvec) // 2, len(maxdegvec)):
        ###Number of collums in the matrix equal to the monomials that can be
        # formed from the x list
        mat_dim_col = mat_dim_col * (maxdegvec[i] + 1)
    A = sympy.zeros(mat_dim_row, mat_dim_col)
    #####The function lesslists is done by the command range which give a list with all the numbers less than the argument
    ####The itertools.products is essentially the cartesian product for the range lists that correspongd to different variables
    ####For example if the max degree in a,b is 1,2 we ll get two lists [0,1],[0,1,2] and the cartesian produst will be
    ###the couples [0,0],[0,1],[0,2],[1,0],[1,1],[1,2] this are the half-monomials as they represent the exponets for the
    ###a-list.
    ###The same proccess is repeated with the x list to get another half set of exponents
    for n, i in enumerate(
            itertools.product(
                *[range(i + 1)
                  for i in maxdegvec[:len(maxdegvec) // 2]])):  ##a-list exp
        for m, j in enumerate(
                itertools.product(
                    *[range(i + 1) for i in maxdegvec[len(maxdegvec) //
                                                      2:]])):  ##x-list exp
            # res_in.append()
            monomial = sympy.sympify(1)
            for e1, x1 in zip(
                    list(i) + list(j), xasym
            ):  ###this loop builds the monomials after the two half sets are joined
                monomial = monomial * x1**e1
            res_out.append(pol.coeff_monomial(monomial))
            A[n, m] = pol.coeff_monomial(
                monomial
            )  ##No problem with the constant term as with mathematica
    #####This if-statement is used only for a case where the matrix is a row vector or a col vector or a scalar
    ###In that case the "from_sympy" command will not return a 2d matrix but MAthematica alwyas gives 2d matrix(list of lists)
    if int(mat_dim_col) == 1 | int(mat_dim_row) == 1:
        res_in = from_sympy(A[0, 0])
        res_out = [Expression('List', *[res_in])]
        return Expression('List', *res_out)
    return from_sympy(A)