コード例 #1
0
    def simplify(self):
        """ Simplify into standard form: ((const) * (params))*(var) """

        c, p, v = self.symbol_groups()

        coeffs = c[0] if len(c) > 0 else sym.Constant(1)
        vars   = v[0] if len(v) > 0 else None

        for const in c[1:]:
            coeffs = smul(coeffs, const, simple = True)

        for param in p:
            coeffs = smul(coeffs, param, simple = True)

        for variable in v[1:]:
            vars = smul(vars, variable, simple = True)

        if vars is not None:
            self.args[0] = coeffs
            self.args[1] = vars

        else:

            # Adopt inner arguments if no variables
            if hasattr(coeffs, 'args'):
                self.args[0] = coeffs.args[0]
                self.args[1] = coeffs.args[1]

            else:
                self.args[0] = coeffs
                self.args[1] = sym.Constant(1)

        return self  # no guarantees that this return will have an audience
コード例 #2
0
    def __init__(self, epigraph_axes, dimensions):
        """
            Mathematical Background:
                Let Q[p] = {(t,x) in R x R[p-1] | norm2(x) <= t}

                This thing, Q is known as a "second order cone" of dimension p.
                We see that t is a scalar which bounds the 2 norm of x

                How does the solver know how to embed t and x in the same cone?
                What does that mean mathematically?

                We can see from the above statements that we should constrain:
                    t >= 0
                    x_i <= 0 for x_i in range(x)
        """

        self.dims = dimensions

        # First constraint always >= 0, because cone of dimension 1 is cone R+,
        # the cone of non-negative reals

        self.constraints = [epigraph_axes[0] >= sym.Constant(0)]

        # Rest of constraints always <= 0
        self.constraints += [ax <= sym.Constant(0) for ax in epigraph_axes[1:]]
コード例 #3
0
ファイル: __init__.py プロジェクト: wuyou33/Convex_Symbolic
def mul(a, b):
    """ Select what "kind" of multiplication to do, based on shape! """

    if type(a) in [float, int]:
        a = sym.Constant(a)

    if type(b) in [float, int]:
        b = sym.Constant(b)

    if a.shape == scalar_shape or b.shape == scalar_shape:
        return muls.smul(a, b)

    else:
        return matrix.matmul(a, b)
コード例 #4
0
    def curvature(self):
        """ Get the curvature of the expression, disregarding parameter sign """

        const,_,var = self.symbol_groups()

        if var == []:
            return 0 # AFFINE

        if const != []:
            const = const[0]
        else:
            const = sym.Constant(1)  # only used for curvature analysis

        v = var[0]  # we know that vars is at most of length 1
                     # because var * var is not valid DCP!

        if const.value > 0:
            return v.curvature  # POSITIVE * (CONVEX/CONCAVE)

        elif const.value < 0:
            if v.curvature > 0:  # NEGATIVE * CONVEX
                return -1

            elif v.curvature < 0:  # NEGATIVE * CONCAVE
                return +1

        return 0
コード例 #5
0
ファイル: sums.py プロジェクト: wuyou33/Convex_Symbolic
    def simplify(self):
        """ Simplify the sum by simplifying the insides and flattening """

        # Ensure all constants are Constant symbols
        to_remove = []
        for n, arg in enumerate(self.args):

            if type(arg) in [float, int] and arg != 0:
                self.args[n] = sym.Constant(arg)

            elif type(arg) is sym.Constant and arg.value == 0:
                to_remove.append(n)

        for rm in to_remove:
            self.args.pop(rm)

        # Inner simplify
        for n, arg in enumerate(self.args):
            self.args[n] = arg.simplify()

        # Flatten into this sum
        new_args = []
        for arg in self.args:
            if type(arg) is sum:
                new_args += arg.args
            else:
                new_args += [arg]

        self.args = new_args
        self.take_stock()

        return self  # no guaranteed audience for this
コード例 #6
0
ファイル: sums.py プロジェクト: wuyou33/Convex_Symbolic
    def factor_coefficients(self):
        """ Factoring for variables. At this point there are no sub-sums

            Cache the factors for later retrieval. Do not replace args.

            This is because replacing args would require smul to handle
                variable distribution differently than other distribution.

            In other words, smul's standard form of ((const) * (params))*(var)
                cannot capture factorization for variables.
        """

        factors = {n: [] for n, var in enumerate(self.vars) if var is not None}

        for n, var in enumerate(self.vars):
            #print('>>>',var)
            for arg in self.args:
                #print('...',arg)
                if type(arg) == ops.atoms.muls.smul:

                    coeff = arg.coefficient_of(var)

                    if coeff.value != 0:
                        #print('   -->',coeff)
                        factors[n].append(coeff)

                elif arg is var:
                    #print('   -->',1)
                    factors[n].append(sym.Constant(1))

        return factors
コード例 #7
0
    def coefficient_of(self, var):
        """ Get the coefficient of this variable. Assumes standard form. """
        """ If you're expecting a factored coefficient, you're doing it wrong!
                Instead, use the factor_coefficients() method of sums.sum """

        if var is self.args[1]:
            return self.args[0]
        else:
            return sym.Constant(0)
コード例 #8
0
    def __init__(self, a, b, simple = False):

        self.args = [a, b]

        # Determine and cache the shape
        self.shape = util.determine_shape(self.args)

        # maintains parity with sum when getting offsets
        self.offset = sym.Constant(0)

        if not simple:
            self.simplify()
コード例 #9
0
ファイル: sums.py プロジェクト: wuyou33/Convex_Symbolic
    def offsets(self):

        offsum = []

        for n, var in enumerate(self.vars):
            if var is None:
                offsum.append(self.args[n])

        if offsum != []:
            return offsum
        else:
            return sym.Constant(0)
コード例 #10
0
ファイル: sums.py プロジェクト: wuyou33/Convex_Symbolic
    def coefficient_of(self, var, failraise=True):
        """ Find all the coefficients of a specific variable. """

        self.take_stock_factors()
        var_index = self.find_var(var)

        if var_index is not None:
            factors = self.factor[var_index]
            return sum(*factors)

        else:
            return sym.Constant(0)
コード例 #11
0
ファイル: sums.py プロジェクト: wuyou33/Convex_Symbolic
    def __init__(self, *args, simple=False):

        self.args = list(args)

        for n, arg in enumerate(self.args):
            if type(arg) in [int, float]:
                self.args[n] = sym.Constant(arg)

        # Determine and cache the shape
        self.shape = util.determine_shape(self.args)

        if not simple:
            self.simplify()
コード例 #12
0
    def __new__(cls, *args, simple = False):
        """
            Base level simplifications:
                0 * x => 0
                1 * x => x
        """

        # 0 * Something
        if any([arg.value == 0 for arg in args]):
            return sym.Constant(0)

        # 1 * Something
        elif any([arg.value == 1 for arg in args]):
            for n, arg in enumerate(args):
                if arg.value == 1:
                    return args[not n]

        # Constant * Constant
        elif all([type(arg) is sym.Constant for arg in args]):
            return sym.Constant(args[0].value * args[1].value)

        # Something * (Sum of Things) --> Something*Thing0 + Something*Thing1...
        elif any([type(arg) is ops.atoms.sums.sum for arg in args]):

            if type(args[0]) is ops.atoms.sums.sum:
                return distribute(args[1], args[0])

            elif type(args[1]) is ops.atoms.sums.sum:
                return distribute(args[0], args[1])
        elif any([type(arg) is sym.Vector for arg in args]):

            if type(args[0]) is sym.Vector:
                return distribute_vector(args[1], args[0])

            elif type(args[1]) is sym.Vector:
                return distribute_vector(args[0], args[1])
        else:
            return super().__new__(cls)