L i};ddlZddlZddlmZddlmZmZmZddl m Z ddl m Z m Z ddlmZddlmZd Zd Zddddd d Zy) N)VisibleDeprecationWarning) csc_arrayvstackissparse)_highs_wrapper)LinearConstraintBounds)OptimizeResult)_highs_to_scipy_status_messagecd}g}g}g}t|tr|g}n$ t|t |dk(r t|g}|D]}t|ts t|}|jt|j|jtj|jjtj|jtj|jjtjt |dkDr8t!|d}tj"|}tj"|} n|d}|d}|d} ||| fS#t$r}t ||d}~wwxYw#ttt f$rYhwxYw#t$r}t ||d}~wwxYw)a Convert sequence of constraints to a single set of components A, b_l, b_u. `constraints` could be 1. A LinearConstraint 2. A tuple representing a LinearConstraint 3. An invalid object 4. A sequence of composed entirely of objects of type 1/2 5. A sequence containing at least one object of type 3 We want to accept 1, 2, and 4 and reject 3 and 5. `constraints` (or each element within `constraints`) must be convertible into an instance of `scipy.optimize.LinearConstraint`.Nrcsc)formatr) isinstancer iter TypeError ValueErrorlenrappendrAnp atleast_1dlbastypefloat64ubr concatenate) constraintsmessageAsb_lsb_usexc constraintrb_lb_us Z/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/scipy/optimize/_milp.py_constraints_to_componentsr* s4G B D D+/0"m  /   { q  /=> " E *&67 3-z:  )JLL)* BMM*--077 CD BMM*--077 CD E 2w{ 2e $nnT"nnT" qE1g1g c3;E /W%3 . /z+DE   3 )s2 3s@ E5 FF-5 F> F  FF*)F*- G6 GGc t|r tdtj|j tj }|j dk7s7|jdk(s(tjtj|s d}t|t|r tdd}|d} tj||jj tj}|jdks|jdkDr t||tdtj }nt#|ts d} t|} tj|j&|jj tj }tj|j(|jj tj }|sSt+tj,d|jftj,d tj,d g} t/|\} } } | j| j|jfk7r d }t|| j0| j2| j4j tj }} } |xsi}hd }t7|j9|}|r"d|d}t;j<|t>d|jAdd|jAddd}|jC|||||| | || | |f S#t$r t|wxYw#t$$r}t||d}~wwxYw#tt$f$r}d }t||d}~wwxYw#t$r}d }t||d}~wwxYw)Nz`c` must be a dense array.rrzP`c` must be a one-dimensional array of finite numbers with at least one element.z$`integrality` must be a dense array.zJ`integrality` must contain integers 0-3 and be broadcastable to `c.shape`.rzI`bounds` must be convertible into an instance of `scipy.optimize.Bounds`.zQ`bounds.lb` and `bounds.ub` must contain reals and be broadcastable to `c.shape`.)rrz,The shape of `A` must be (len(b_l), len(c)).>disppresolve node_limit time_limit mip_rel_gapzUnrecognized options detected: z). These will be passed to HiGHS verbatim.) stacklevelr,Fr.)log_to_console mip_max_nodes)"rrrrrrndimsizeallisfinite broadcast_toshapeuint8minmaxr infrrrrr emptyr*indptrindicesdataset differencewarningswarnRuntimeWarningpopupdate)c integralityboundsr optionsr!r%rrrr'r(r?r@rAsupported_optionsunsupported_options options_ivs r)_milp_ivrPNs>{566 a +Avv{affk A)?0!! ?@@G "ook177;BB288L 1  1A 5!!~266"  '. /V_F+ __VYY 0 7 7 C __VYY 0 7 7 C '!QVV(=(*HI +0= 3 ww388QVV$$@!!HHaiirzz1JTGFmG(g,112CD45H4IJ== g~!<$+KK$>#*;;|T#BDJg k2r67D#sJ NNm "!!" /W%3 . /  "+4!s*+ +8!s* +sU9=MM( BNN*M%( N1 M==NN'N""N'* O3OO)rJrKr rLc  t|||||}|\ }}}}}} } } } }t||| | | | |||| } i}| jdd}| jdd}t||\}}||d<||d<|dk(|d<| jdd}|t j |nd|d<| jdd|d<| jdd|d<| jd d|d <| jd d|d <t |S) a Mixed-integer linear programming Solves problems of the following form: .. math:: \min_x \ & c^T x \\ \mbox{such that} \ & b_l \leq A x \leq b_u,\\ & l \leq x \leq u, \\ & x_i \in \mathbb{Z}, i \in X_i where :math:`x` is a vector of decision variables; :math:`c`, :math:`b_l`, :math:`b_u`, :math:`l`, and :math:`u` are vectors; :math:`A` is a matrix, and :math:`X_i` is the set of indices of decision variables that must be integral. (In this context, a variable that can assume only integer values is said to be "integral"; it has an "integrality" constraint.) Alternatively, that's: minimize:: c @ x such that:: b_l <= A @ x <= b_u l <= x <= u Specified elements of x must be integers By default, ``l = 0`` and ``u = np.inf`` unless specified with ``bounds``. Parameters ---------- c : 1D dense array_like The coefficients of the linear objective function to be minimized. `c` is converted to a double precision array before the problem is solved. integrality : 1D dense array_like, optional Indicates the type of integrality constraint on each decision variable. ``0`` : Continuous variable; no integrality constraint. ``1`` : Integer variable; decision variable must be an integer within `bounds`. ``2`` : Semi-continuous variable; decision variable must be within `bounds` or take value ``0``. ``3`` : Semi-integer variable; decision variable must be an integer within `bounds` or take value ``0``. By default, all variables are continuous. `integrality` is converted to an array of integers before the problem is solved. bounds : scipy.optimize.Bounds, optional Bounds on the decision variables. Lower and upper bounds are converted to double precision arrays before the problem is solved. The ``keep_feasible`` parameter of the `Bounds` object is ignored. If not specified, all decision variables are constrained to be non-negative. constraints : sequence of scipy.optimize.LinearConstraint, optional Linear constraints of the optimization problem. Arguments may be one of the following: 1. A single `LinearConstraint` object 2. A single tuple that can be converted to a `LinearConstraint` object as ``LinearConstraint(*constraints)`` 3. A sequence composed entirely of objects of type 1. and 2. Before the problem is solved, all values are converted to double precision, and the matrices of constraint coefficients are converted to instances of `scipy.sparse.csc_array`. The ``keep_feasible`` parameter of `LinearConstraint` objects is ignored. options : dict, optional A dictionary of solver options. The following keys are recognized. disp : bool (default: ``False``) Set to ``True`` if indicators of optimization status are to be printed to the console during optimization. node_limit : int, optional The maximum number of nodes (linear program relaxations) to solve before stopping. Default is no maximum number of nodes. presolve : bool (default: ``True``) Presolve attempts to identify trivial infeasibilities, identify trivial unboundedness, and simplify the problem before sending it to the main solver. time_limit : float, optional The maximum number of seconds allotted to solve the problem. Default is no time limit. mip_rel_gap : float, optional Termination criterion for MIP solver: solver will terminate when the gap between the primal objective value and the dual objective bound, scaled by the primal objective value, is <= mip_rel_gap. Returns ------- res : OptimizeResult An instance of :class:`scipy.optimize.OptimizeResult`. The object is guaranteed to have the following attributes. status : int An integer representing the exit status of the algorithm. ``0`` : Optimal solution found. ``1`` : Iteration or time limit reached. ``2`` : Problem is infeasible. ``3`` : Problem is unbounded. ``4`` : Other; see message for details. success : bool ``True`` when an optimal solution is found and ``False`` otherwise. message : str A string descriptor of the exit status of the algorithm. The following attributes will also be present, but the values may be ``None``, depending on the solution status. x : ndarray The values of the decision variables that minimize the objective function while satisfying the constraints. fun : float The optimal value of the objective function ``c @ x``. mip_node_count : int The number of subproblems or "nodes" solved by the MILP solver. mip_dual_bound : float The MILP solver's final estimate of the lower bound on the optimal solution. mip_gap : float The difference between the primal objective value and the dual objective bound, scaled by the primal objective value. Notes ----- `milp` is a wrapper of the HiGHS linear optimization software [1]_. The algorithm is deterministic, and it typically finds the global optimum of moderately challenging mixed-integer linear programs (when it exists). References ---------- .. [1] Huangfu, Q., Galabova, I., Feldmeier, M., and Hall, J. A. J. "HiGHS - high performance software for linear optimization." https://highs.dev/ .. [2] Huangfu, Q. and Hall, J. A. J. "Parallelizing the dual revised simplex method." Mathematical Programming Computation, 10 (1), 119-142, 2018. DOI: 10.1007/s12532-017-0130-5 Examples -------- Consider the problem at https://en.wikipedia.org/wiki/Integer_programming#Example, which is expressed as a maximization problem of two variables. Since `milp` requires that the problem be expressed as a minimization problem, the objective function coefficients on the decision variables are: >>> import numpy as np >>> c = -np.array([0, 1]) Note the negative sign: we maximize the original objective function by minimizing the negative of the objective function. We collect the coefficients of the constraints into arrays like: >>> A = np.array([[-1, 1], [3, 2], [2, 3]]) >>> b_u = np.array([1, 12, 12]) >>> b_l = np.full_like(b_u, -np.inf, dtype=float) Because there is no lower limit on these constraints, we have defined a variable ``b_l`` full of values representing negative infinity. This may be unfamiliar to users of `scipy.optimize.linprog`, which only accepts "less than" (or "upper bound") inequality constraints of the form ``A_ub @ x <= b_u``. By accepting both ``b_l`` and ``b_u`` of constraints ``b_l <= A_ub @ x <= b_u``, `milp` makes it easy to specify "greater than" inequality constraints, "less than" inequality constraints, and equality constraints concisely. These arrays are collected into a single `LinearConstraint` object like: >>> from scipy.optimize import LinearConstraint >>> constraints = LinearConstraint(A, b_l, b_u) The non-negativity bounds on the decision variables are enforced by default, so we do not need to provide an argument for `bounds`. Finally, the problem states that both decision variables must be integers: >>> integrality = np.ones_like(c) We solve the problem like: >>> from scipy.optimize import milp >>> res = milp(c=c, constraints=constraints, integrality=integrality) >>> res.x [2.0, 2.0] Note that had we solved the relaxed problem (without integrality constraints): >>> res = milp(c=c, constraints=constraints) # OR: >>> # from scipy.optimize import linprog; res = linprog(c, A, b_u) >>> res.x [1.8, 2.8] we would not have obtained the correct solution by rounding to the nearest integers. Other examples are given :ref:`in the tutorial `. statusNr!rsuccessxfunmip_node_countmip_dual_boundmip_gap)rPrgetr rarrayr )rIrJrKr rLargs_ivrrr?r@rAr'r( highs_resres highs_status highs_messagerRr!rTs r)milpr`s4rq+v{GDGGNDA{BFGT3Wq&'4c!2{G=I C==40LMM)T2M4\5BDOFGCMC NkC N c4 Amrxx{CHud+CJ%MM*:DAC%MM*:DAC]]9d3C N # )rDnumpyrnumpy.exceptionsr scipy.sparserrr_highspy._highs_wrapperr _constraintsr r _optimizer _linprog_highsr r*rPr`rar)rjs?64432%:>BIOX $pra