Пример #1
0
def sympy_solver(expr):
    # Sympy is buggy and slow.  Use Transforms.
    symbols = get_symbols(expr)
    if len(symbols) != 1:
        raise ValueError('Expression "%s" needs exactly one symbol.' %
                         (expr, ))

    if isinstance(expr, Relational):
        result = sympy.solveset(expr, domain=sympy.Reals)
    elif isinstance(expr, sympy.Or):
        subexprs = expr.args
        intervals = [sympy_solver(e) for e in subexprs]
        result = sympy.Union(*intervals)
    elif isinstance(expr, sympy.And):
        subexprs = expr.args
        intervals = [sympy_solver(e) for e in subexprs]
        result = sympy.Intersection(*intervals)
    elif isinstance(expr, sympy.Not):
        (notexpr, ) = expr.args
        interval = sympy_solver(notexpr)
        result = interval.complement(sympy.Reals)
    else:
        raise ValueError('Expression "%s" has unknown type.' % (expr, ))

    if isinstance(result, sympy.ConditionSet):
        raise ValueError('Expression "%s" is not invertible.' % (expr, ))

    return result
Пример #2
0
def transform_set(x, expr, sympy_set):
    """ Transform a sympy_set by an expression

    >>> x = sympy.Symbol('x')
    >>> domain = sympy.Interval(-sympy.pi / 4, -sympy.pi / 6, False, True) | sympy.Interval(sympy.pi / 6, sympy.pi / 4, True, False)
    >>> transform_set(x, -2 * x, domain)
    [-pi/2, -pi/3) U (pi/3, pi/2]
    """

    if isinstance(sympy_set, sympy.Union):
        return sympy.Union(
            transform_set(x, expr, arg) for arg in sympy_set.args)
    if isinstance(sympy_set, sympy.Intersection):
        return sympy.Intersection(
            transform_set(x, expr, arg) for arg in sympy_set.args)

    f = sympy.Lambda(x, expr)
    if isinstance(sympy_set, sympy.Interval):
        left, right = f(sympy_set.left), f(sympy_set.right)

        if left < right:
            new_left_open = sympy_set.left_open
            new_right_open = sympy_set.right_open
        else:
            new_left_open = sympy_set.right_open
            new_right_open = sympy_set.left_open

        return sympy.Interval(sympy.Min(left, right), sympy.Max(left, right),
                              new_left_open, new_right_open)

    if isinstance(sympy_set, sympy.FiniteSet):
        return sympy.FiniteSet(list(map(f, sympy_set)))
Пример #3
0
 def get_domain(self, vector):
     """Combine the constraints into a single domain."""
     domain = self.global_domain
     for cond in self.constraint.exprs:
         new_constraint = self.solve_constraint(cond, vector)
         if new_constraint is not True:
             domain = sp.Intersection(domain, new_constraint)
     return list(domain.boundary)
Пример #4
0
def manualSolveALessBLessC(A,B,C):
	"""B is number, A and C are linear functions of X
	returns set of allowed X so A <= B <= C"""
	int1 = manualSolveSystem(A,B)
	int2 = manualSolveSystem(-C,-B)
	intersection = sympy.Intersection(int1, int2)
	if int1 == intersection:
		return (intersection, True)
	elif int2 == intersection:
		return (intersection, False)
	else:
		raise "This should never happen"
Пример #5
0
def solve_poly_equality_symbolically(expr, b):
    soln_lt = solve_poly_inequality_symbolically(expr, b, False)
    soln_gt = solve_poly_inequality_symbolically(-expr, -b, False)
    return sympy.Intersection(soln_lt, soln_gt)
Пример #6
0
def maximum_2(max_f, max_solution, max_combination, max_feasible_interval,
              max_interval, max3_f, max3_solution, max3_combination,
              max3_feasible_interval, max3_interval):
    # this function gets two arrays of maximum intervals and returns an overall maximum interval array
    # the concept is simillar to the function maximum_f() above. Only the starting point is the first
    # array, max_interval (instead the total feasible reagion of the constant ),
    # and the loop is over the second array (max3_interval)
    # this is used to combine intervals and maximums caculated by diffrent processors in case of parallel processing.

    # loop over all inetrvals in max3_interval
    for i_max3 in range(len(max3_interval)):

        # temporary storage for intervals and their values
        max2_f = []
        max2_solution = []
        max2_combination = []
        max2_feasible_interval = []
        max2_interval = []

        # loop over all inetrvals in max_interval to be updated by max3_interval
        for i_max in range(len(max_interval)):
            # intersection of current maximum interval with each new maximum interval
            inter1 = sp.Intersection(max_interval[i_max],
                                     max3_interval[i_max3])
            if inter1 == sp.EmptySet:  # if there is no intersection keep current value
                max2_f.append(max_f[i_max])
                max2_solution.append(max_solution[i_max])
                max2_combination.append(max_combination[i_max])
                max2_feasible_interval.append(max_feasible_interval[i_max])
                max2_interval.append(max_interval[i_max])
            else:  # if there is intesection
                # check in which interval the new maximum is larger than the current one
                exp1 = sp.sympify(max3_f[i_max3] - max_f[i_max] > 0)
                exp1 = exp1.subs(
                    {'s': 'd'}
                )  # becuase sympy is stupid and sometimes considers same 's' two variables.
                exp1 = exp1.subs({'d': 's'})
                if exp1 == False:
                    sol1_set = sp.EmptySet
                elif exp1 == True:
                    sol1_set = sp.UniversalSet
                else:
                    sol1 = solve(exp1)
                    sol1_set = sol1.as_set()

                new_max_inter = sp.Intersection(
                    inter1, sol1_set
                )  # intersection of interval that the new one is bigger and feasible
                if new_max_inter != sp.EmptySet:  # if not empty make a new interval and keep the new maximum value as its maximum
                    max2_f.append(max3_f[i_max3])
                    max2_solution.append(max3_solution[i_max3])
                    max2_combination.append(max3_combination[i_max3])
                    max2_feasible_interval.append(
                        max3_feasible_interval[i_max3])
                    max2_interval.append(new_max_inter)

                    max_comp_inter = sp.Complement(
                        max_interval[i_max],
                        new_max_inter)  # complement of the updated interval
                    if max_comp_inter != sp.EmptySet:  # if complemet is not emty, ratain the previous maximum value for this complement interval
                        max2_f.append(max_f[i_max])
                        max2_solution.append(max_solution[i_max])
                        max2_combination.append(max_combination[i_max])
                        max2_feasible_interval.append(
                            max_feasible_interval[i_max])
                        max2_interval.append(max_comp_inter)
                else:  # if there is no intersection between current interval and the interval that the new one is bigger ratin the current value
                    max2_f.append(max_f[i_max])
                    max2_solution.append(max_solution[i_max])
                    max2_combination.append(max_combination[i_max])
                    max2_feasible_interval.append(max_feasible_interval[i_max])
                    max2_interval.append(max_interval[i_max])

        # move from temporary storage to permanent
        max_f = max2_f.copy()
        max_solution = max2_solution.copy()
        max_combination = max2_combination.copy()
        max_feasible_interval = max2_feasible_interval.copy()
        max_interval = max2_interval.copy()

    return max_f, max_solution, max_combination, max_feasible_interval, max_interval
Пример #7
0
def maximum_f(feasible_f, feasible_solution, feasible_combination,
              feasible_interval, c2_exp, comm, p_n, p_i):
    # this function gets the array of optimum values and their feasible regions and comparing all of them finds
    # the maximum value for diffrent inetrvals of possible reagion of the constant.
    # the maximum value can be a number or a function of the constant.

    if c2_exp == []:  # if there is no constants
        sol1_set = sp.Interval(0, 0)  # set inetval
    else:
        # convert constarint on constants to set. This is the initial interval to be divided later for diffrent maximums
        sol1 = sp.solve(c2_exp)
        sol1_set = sol1.as_set()

    # here we define an array of intervals that have one interavl which is allowed region of the constant
    # We also set the optimum function value for this iterval to be negative infinity (-sp.oo)
    # later we update the arrays to have smaller inetrvals each with the optimum value for that interval
    # Outputs:
    # max_f: an array of maximum values for all the subintervals of possible interval of the constant
    # max_solution: to store the variable values for each interval
    # max_comb_id: keeping id for backward check
    # max_intersect_id: keeping id for backward check
    # max_opt_id: keeping id for backward check
    # max_feasible_id: keeping id for backward check
    # max_feasible_interval: list of intervals where the current maximum is feasible
    # (can be larger than interval below sincs below is both feasible and maximum)
    # max_interval: array of subintervals of the allowed region of the constant that has a distict maximum value save in max_f above.

    max_f = [-sp.oo]  # set the maximum value of function to negative infinity
    max_solution = ["No answer"
                    ]  # to store the variable values for each maximum
    max_combination = ["No answer"]
    max_feasible_interval = ["No answer"]
    max_interval = [
        sol1_set
    ]  # set array of interval to have one member which is the allowed reagion of constant

    # t_p = t_print
    # # used to caculate total caculate time
    # start = time.time()

    # loop over all feasible solutions
    for i_f in range(len(feasible_f)):
        # max_2* arrays are used as temporary storages of maximum intervals and at the end of the loop are
        # copied to max* arrays
        max2_f = []
        max2_sol = []
        max2_combination = []
        max2_feasible_interval = []
        max2_interval = []

        # loop over all previous intervals of maximum values saved in max* arrays
        for i_max in range(len(max_interval)):
            # intersection of current optimum interval with each previously calculated maximum interval
            inter1 = sp.Intersection(max_interval[i_max],
                                     feasible_interval[i_f])

            if inter1 == sp.EmptySet:  # if there is no intersection retain the current interval and associated maximum
                max2_f.append(max_f[i_max])
                max2_sol.append(max_solution[i_max])
                max2_combination.append(max_combination[i_max])
                max2_feasible_interval.append(max_feasible_interval[i_max])
                max2_interval.append(max_interval[i_max])
            else:  # if there is an intersection, find the interval that the new maximum is larger than the previous maximum
                exp1 = (
                    feasible_f[i_f] - max_f[i_max]
                ) > 0  # make an expersion to solve to see if current optimum is larger than previously found optimum for this interval
                exp1 = exp1.subs(
                    {'s': 'd'}
                )  # becuase sympy is stupid and sometimes considers same 's' two variables.
                exp1 = exp1.subs({'d': 's'})
                if exp1 == False:  # new optimum is not larger anywhere
                    sol1_set = sp.EmptySet
                elif exp1 == True:  # new interval is always bigger
                    sol1_set = sp.UniversalSet
                else:  # if only larger on some interval, find the interval
                    sol1 = solve(exp1)
                    sol1_set = sol1.as_set()

                new_max_inter = sp.Intersection(
                    inter1, sol1_set
                )  # define a new interval that is intersection of where the new optimum is larger and is feasible and whithin current maximum interval
                if new_max_inter != sp.EmptySet:  # if this new interval is not empty append this interval and its f value to the list of intervals for maximum
                    max2_f.append(feasible_f[i_f])
                    max2_sol.append(feasible_solution[i_f])
                    max2_combination.append(feasible_combination[i_f])
                    max2_feasible_interval.append(feasible_interval[i_f])
                    max2_interval.append(new_max_inter)

                    max_comp_inter = sp.Complement(
                        max_interval[i_max], new_max_inter
                    )  # find the complement of the inetvarl above to retain the previous maxium value for the remaining interval
                    if max_comp_inter != sp.EmptySet:  # if remaining is not empty set add it to the array of maximums and retain the previous value for the maximum
                        max2_f.append(max_f[i_max])
                        max2_sol.append(max_solution[i_max])
                        max2_combination.append(max_combination[i_max])
                        max2_feasible_interval.append(
                            max_feasible_interval[i_max])
                        max2_interval.append(max_comp_inter)

                else:  # if this new interval is empty retain the previous interval and its value as maximum
                    max2_f.append(max_f[i_max])
                    max2_sol.append(max_solution[i_max])
                    max2_combination.append(max_combination[i_max])
                    max2_feasible_interval.append(max_feasible_interval[i_max])
                    max2_interval.append(max_interval[i_max])

        # copy from temporary to permanent storage for the next iteration
        max_f = max2_f.copy()
        max_solution = max2_sol.copy()
        max_combination = max2_combination.copy()
        max_feasible_interval = max2_feasible_interval.copy()
        max_interval = max2_interval.copy()

        # print progress

    #     t = time.time() - start
    #
    #     # printing progress
    #     if t > t_p :
    #         perc = ((i_f+1)/(len(feasible_f)-1)*100)
    #         if perc > 0:
    #             t_left = t * (100 - perc) / perc
    #             print("process",p_i, "maximum", int(perc), "%  Time to finish:" , str(datetime.timedelta(seconds=int(t_left)) ) )
    #         t_p = t_p + t_print
    #
    # # caculate and print run time
    # end = time.time()
    #
    # print("process", p_i, " Maximum completed. Total time: ",  str(datetime.timedelta(seconds=(end-start))) )
    print("process", p_i, " Maximum completed.")
    # Outputs:
    # max_f: an array of maximum values for all the subintervals of possible interval of the constant
    # max_solution: to store the variable values for each interval
    # max_combination: keeping initial combination of constraints that lead to this.
    # max_feasible_interval: list of intervals where the current maximum is feasible
    # (can be larger than interval below sincs below is both feasible and maximum)
    # max_interval: array of subintervals of the allowed region of the constant that has a distict maximum value save in max_f above.
    return max_f, max_solution, max_combination, max_feasible_interval, max_interval
Пример #8
0
def ranging(
    DICp: Sequence[Sequence[Number]],
    c: Sequence[Number],
    dc: Sequence[Number],
    basic: Sequence[int],
    nonbasic: Sequence[int],
) -> None:
    DICp = np.array(DICp)
    c = np.array(c)
    dc = np.array(dc)
    basic = np.array(basic)
    nonbasic = np.array(nonbasic)

    zn = -DICp[0, 1:].reshape(-1, 1)

    basic = np.array(basic) - 1
    nonbasic = np.array(nonbasic) - 1

    dc_basic = dc[basic].reshape(-1, 1)
    dc_nonbasic = dc[nonbasic].reshape(-1, 1)

    BinvN = -DICp[1:, 1:]

    BinvNTcb = BinvN.T @ dc_basic
    dzn = BinvNTcb - dc_nonbasic

    print('Got dicitonary:')
    print_lp_dict(DICp, basic, nonbasic)

    print(f'\n-B{UTF["inv"]}N =')
    print(-BinvN)
    print()

    print(f'{UTF["Delta"]}c{UTF["T"]} = {dc.ravel()}')
    print(f'{UTF["Delta"]}c{UTF["_B"]}{UTF["T"]} = {dc_basic.ravel()}')
    print(f'{UTF["Delta"]}c{UTF["_N"]}{UTF["T"]} = {dc_nonbasic.ravel()}')

    print(f'\n(B{UTF["inv"]}N){UTF["T"]} =')
    print(BinvN.T)
    print()

    print(
        f'{UTF["Delta"]}z{UTF["_N"]}= '
        f'(B{UTF["inv"]}N){UTF["T"]}{UTF["Delta"]}c{UTF["_B"]} - c{UTF["_N"]} ='
    )
    print(
        f'{BinvNTcb.ravel()}{UTF["T"]} - {dc_nonbasic.ravel()}{UTF["T"]} = {dzn.ravel()}{UTF["T"]}'
    )

    print(
        f'\nz*{UTF["_N"]} + t{UTF["Delta"]}z{UTF["_N"]} {UTF["geq"]} 0 {UTF["rarrow"]} '
        f'{zn.ravel()}{UTF["T"]} + t{dzn.ravel()}{UTF["T"]} {UTF["geq"]} 0')
    print(UTF['rarrow'])
    for i, j in zip(zn.ravel(), dzn.ravel()):
        string = ''
        string += str(i)
        if j >= 0:
            string += ' +'
        elif j < 0:
            string += ' -'
        string += f' {abs(j)}t {UTF["geq"]} 0'
        print(string)

    t = sp.Symbol('t', real=True)
    polys = [(Poly(i + j * t), '>=') for i, j in zip(zn.ravel(), dzn.ravel())
             if j != 0]
    result = sp.Intersection(
        *[s for p in polys for s in solve_poly_inequality(*p)])

    # l for lower, u for upper
    l_bound, u_bound = result.left, result.right

    l_c = c + dc * l_bound
    u_c = c + dc * u_bound
    # Fix nans
    mask = l_c == sp.nan
    l_c[mask] = c[mask]

    mask = u_c == sp.nan
    u_c[mask] = c[mask]

    print()
    print(f'Respective to {UTF["Delta"]}c = {dc}')
    print(f'We see that we can vary c in:')
    print(l_c)
    print('to')
    print(u_c)