
    kh-{                     r    d dl mZmZmZmZ ddlmZ ddlZddlZd Z	 G d de      Z
e
Zda G d	 d
e      Zy)   )LpSolverLpSolver_CMD
subprocessPulpSolverError   )	constants    Nc                 ~    | j                         xs, t        | j                        xs t        | j                        S )zyCheck whether lp is a MIP.

    From an XPRESS point of view, a problem is also a MIP if it contains
    SOS constraints.)isMIPlensos1sos2)lps    z/var/www/html/SchoolMeal/SchoolMeal/pds_admin_SchoolMeal/Backend/venv/lib/python3.12/site-packages/pulp/apis/xpress_api.py_ismipr   !   s*    
 88:5RWW5RWW5    c                   l    e Zd ZdZd Z	 	 	 	 	 	 	 	 	 	 	 	 d
dZd Zd Zd Ze	d        Z
d Ze	d	        Zy)XPRESSzOThe XPRESS LP solver that uses the XPRESS command line tool
    in a subprocessNc                 H    t        j                  | |||||||||	|
||       y)a  
        Initializes the Xpress solver.

        :param bool mip: if False, assume LP even if integer variables
        :param bool msg: if False, no log is shown
        :param float timeLimit: maximum time for solver (in seconds)
        :param float gapRel: relative gap tolerance for the solver to stop (in fraction)
        :param heurFreq: the frequency at which heuristics are used in the tree search
        :param heurStra: heuristic strategy
        :param coverCuts: the number of rounds of lifted cover inequalities at the top node
        :param preSolve: whether presolving should be performed before the main algorithm
        :param options: Adding more options, e.g. options = ["NODESELECTION=1", "HEURDEPTH=5"]
                        More about Xpress options and control parameters please see
                        https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/chapter7.html
        :param bool warmStart: if True, then use current variable values as start
        )gapRelmipmsg	timeLimitoptionspath	keepFilesheurFreqheurStra	coverCutspreSolve	warmStartN)r   __init__)selfr   r   r   r   r   r   r   r   r   r   r    r!   s                r   r"   zXPRESS.__init__/   s9    > 		
r   c                 $    | j                  d      S )N	optimizer)executableExtensionr#   s    r   defaultPathzXPRESS.defaultPath^   s    ''44r   c                 8    | j                  | j                        S )True if the solver is available)
executabler   r'   s    r   	availablezXPRESS.availablea   s    tyy))r   c           
         | j                  | j                        st        d| j                  z         | j                  |j                  ddddd      \  }}}}}|j                  |d| j                        }| j                  j                  d	d
      rL|D cg c]/  }|j                         |j                  |j                         f1 }	}| j                  ||	       g }
t        |      r| j                  r|
j                  g d       t        j                  t        j                  t        j                  t        j                  t        j                  t        j                  t        j                   t        j                  d}d}n|
j                  ddg       t        j"                  t        j                   t        j                  t        j                  t        j                  t        j$                  t        j                  t        j"                  t        j                  d	}d}t'        |d      5 }| j(                  s|j+                  d       |j+                  d| j-                  |      z   dz          | j.                  |j+                  d| j.                  z         | j                  j                  d      }||j+                  d|dd       | j                  j                  d      }||j+                  d|z         | j                  j                  d      }||j+                  d|z         | j                  j                  d      }||j+                  d|z         | j                  j                  d       }||j+                  d!|z         | j                  j                  d	d
      r&|j+                  d"| j-                  |      z   dz          | j0                  D ]  }|j+                  |dz           t        |      r| j                  r|j+                  d#       n|j+                  d$       |j+                  d%| j-                  |      z   dz          |j+                  d&| j-                  |       d'       |
D ]  }|j+                  d(| d)| d*        |j+                  d+       |j+                  d,       ddd       t'        |      5 }d
}d}d}| j(                  sVt2        j4                  d-k\  r!t6        j8                  }t6        j8                  }n"t6        j:                  }t6        j<                  }d.}t7        j>                  | j                  |j                  gd.|||d./      }|r|j@                  D ]  } |jC                         d0k7  rt        d1| j                  z         	 ddd       | jE                  ||      \  }}}}}| jG                  ||||       |j                  |j                  |d2      t        j                        }|jI                  |       |jK                  |       |jM                  |       |jO                  |       |jQ                  |       |S c c}w # 1 sw Y   xY w# 1 sw Y   xY w)3"Solve a well formulated lp problemzPuLP: cannot execute r   prtcmdattrslxr   )writeSOSr   r!   FN)	mipobjval	bestbound	mipstatusr	   r   r                  r6   lpobjvallpstatus	r	   r   r   r8   r9   r:   r;   r<      wzOUTPUTLOG=0
z	readprob 
zMAXTIME=%d
r   zMIPRELSTOP=fr   zHEURFREQ=%d
r   zHEURSTRATEGY=%d
r   zCOVERCUTS=%d
r    zPRESOLVE=%d
zreadslxsol zmipoptimize
zlpoptimize
zwriteprtsol zset fh [open z
 w]; list
z
puts $fh "z=$z"
z
close $fh
zQUIT
i  T)shellstdinstdoutstderruniversal_newlinesr	   zPuLP: Error while executing ))r+   r   r   create_tmp_filesnamewriteLPr   optionsDictgetvaluewriteslxsolr   extendr   LpStatusUndefinedLpStatusInfeasibleLpStatusOptimalLpStatusNotSolvedLpStatusUnboundedopenr   write
quote_pathr   r   sys
hexversionr   DEVNULLPIPESTDOUTPopenrF   waitreadsoldelete_tmp_filesassignVarsValsassignVarsDjassignConsSlackassignConsPiassignStatus) r#   r   tmpLptmpSoltmpCmdtmpAttrtmpStart	variablesvstart	attrNames	statusmap	statuskeyr0   	targetGapr   r   r   r    optionr1   consumesuboutsuberrxpress_valuesredcostslacksdualsattrsstatuss                                    r   actualSolvezXPRESS.actualSolvee   s   tyy)!"9DII"EFF373H3HGGT5%4
0vvw JJuqdhhJ?	U32;UQqwwy?Taffaggi(UEUXu- 	":$((DE..........//,,..	I $Ij*56..,,//............
I #I&# '	 #88		/*IIkDOOE$::TAB~~)		.4>>9:((,,X6I$		K	!}B78''++J7H#		/H45''++J7H#		-89((,,[9I$		*Y67''++J7H#		/H45##K7		-$//(*CCdJK,, )		&4-()bzdhh		/*		.)IIntv'>>EFII 89E " :		JtfBtfC89:IIm$IIhO'	 P &\ 	RSGFF88 >>Z/'//F'//F (__F'..F"G%%BGG$#'F    A {{}!%&Dtyy&PQQ "=	R@ 15VW0M-eVVW=uyyB79T9TU
&!
 
6"

a V@'	  '	 P	R 	Rs&   Y-.Y-5JY2CY?2Y<?Zc                 (   i }i }i }i }t        |       5 }t        |      D ]  \  }}|dk  r|dk(  r-|j                         }t        |d         }	t        |d         }
>|dk  rD|dk(  rJ|j                         }t	        |      dkD  si|d   dk(  r(|d   }t        |d         ||<   t        |d         ||<   t	        |d         dk(  s|d   d	v s|d   }t        |d         ||<   t        |d         ||<    	 d
d
d
       t               }t        |      5 }|D ]  }|j                         j                  d      }t	        |      dk(  s1|d   j                         |d   k(  sK|d   j                         }	 t        |d   j                               }|||d   j                         <    	 d
d
d
       |||||fS # 1 sw Y   xY w# t        $ r0 	 t        |d   j                               }n# t        $ r Y nw xY wY lw xY w# 1 sw Y   XxY w)zRead an XPRESS solution filer;   r   r:   
   r   r	   Cr9   LGREN=)
rW   	enumeratesplitintr   floatdictstriplower
ValueError)filenameattrfilerz   r{   r|   r}   rC   lineno_linerowscolslinerK   r~   fieldsrO   s                   r   ra   zXPRESS.readsol   s1    (^ "	9q!*1 !9A:q[!KKMEuQx=DuQx=Db[r\ !;;=D4y1}7c> $(7D+0a>F4L,1$q'NGDM a\Q.47f3D $(7D+0a>F4L*/Q.E$KC!9"	9H (^ 	5q 5++C0v;!#q	(9VAY(F"1IOO-E! #F1IOO$5 6 05E&)//+,5	5 wu44e"	9 "	9X & !!$)&)//*;$<E) ! !!	5 	5s   A4G 	AG G )G 3HH(H<GH G		HG32H3	G?	<H>G?	?HHHHHc           
          t        |d      5 }t        |      D ]<  \  }}|j                  d|z         |D ]  \  }}|j                  d| d|dd         > |j                  d       ddd       y# 1 sw Y   yxY w)	a  
        Write a solution file in SLX format.
        The function can write multiple solutions to the same file, each
        solution must be passed as a list of (name,value) pairs. Solutions
        are written in the order specified and are given names "solutionN"
        where N is the index of the solution in the list.

        :param string name: file name
        :param list values: list of lists of (name,value) pairs
        rA   zNAME solution%d
z C       z.16frB   zENDATA
N)rW   r   rX   )r#   rK   rz   r2   isolrO   s          r   rP   zXPRESS.writeslxsol  s     $_ 	"#F+ @3		-12#& @KD%IIad|2>?@@ IIj!	" 	" 	"s   AA22A;c                 <    dt        j                  dd|       z   dz   S )z
        Quotes a path for the Xpress optimizer console, by wrapping it in
        double quotes and escaping the following characters, which would
        otherwise be interpreted by the Tcl shell: \ $ " [
        "z	([\\$"[])z\\\1)resub)r   s    r   rY   zXPRESS.quote_path-  s!     RVVL'4883>>r   )TTNNNFNNNNNF)__name__
__module____qualname____doc__rK   r"   r(   r,   r   staticmethodra   rP   rY    r   r   r   r   )   sy     D -
^5*yv 85 85t"$ ? ?r   r   c                   x    e Zd ZdZd Z	 	 	 	 	 	 	 	 	 	 	 ddZd ZddZd ZddZ	d Z
dd	Zed
        Zd Zd Zy)	XPRESS_PYz0The XPRESS LP solver that uses XPRESS Python APINc                 |    |t        |       }t        j                  | ||||||||||	       d| _        |
| _        y)a  
        Initializes the Xpress solver.

        :param bool mip: if False, assume LP even if integer variables
        :param bool msg: if False, no log is shown
        :param float timeLimit: maximum time for solver (in seconds)
        :param float gapRel: relative gap tolerance for the solver to stop (in fraction)
        :param heurFreq: the frequency at which heuristics are used in the tree search
        :param heurStra: heuristic strategy
        :param coverCuts: the number of rounds of lifted cover inequalities at the top node
        :param preSolve: whether presolving should be performed before the main algorithm
        :param bool warmStart: if set then use current variable values as warm start
        :param string export: if set then the model will be exported to this file before solving
        :param options: Adding more options. This is a list the elements of which
                        are either (name,value) pairs or strings "name=value".
                        More about Xpress options and control parameters please see
                        https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/chapter7.html
        N)
r   r   r   r   r   r   r   r   r    r!   )absr   r"   
_available_export)r#   r   r   r   r   r   r   r   r    r!   exportr   s               r   r"   zXPRESS_PY.__init__A  sW    @   YI	
 r   c                     | j                   -	 ddlat        j                  d       d| _         | j                   S | j                   S #  d| _         Y | j                   S xY w)r*   Nr	   FT)r   rx   setOutputEnabledr'   s    r   r,   zXPRESS_PY.availablez  sX    ??"	( ''."& t("'s    A 	Ac                    	 |j                   }|j                         D ]	  }d|_         |j                  j	                         D ]	  }d|_         | j
                  a| j
                  j                         j                  d      r|j                  | j
                  d       n|j                  | j
                         | ||       t        |      r| j                  s|j                          y|j                          y# t        j                  t        j                  t        j                   f$ r}t#        t%        |            d}~ww xY w)a  Perform the actual solve from actualSolve() or actualResolve().

        :param prepare:  a function that is called with `lp` as argument
                         and allows final tweaks to `lp.solverModel` before
                         the low level solve is started.
        FNz.lpl)solverModelrm   modifiedconstraintsrz   r   r   endswithrX   r   r   
lpoptimizesolverx   
ModelErrorInterfaceErrorSolverErrorr   str)r#   r   preparemodelrn   cerrs          r   
callSolverzXPRESS_PY.callSolver  s   	,NNE \\^ #"
#^^**, #"
# ||'<<%%'007KKc2KK-"bz$((  " !!6#8#8&:L:LM 	,!#c(++	,s   C,D  /D   2E2EEc           
         	 |j                   }t        |      r| j                  rg g d d f\  }}}}	 |j                  ||       t        j
                  t        j
                  t        j
                  t        j
                  t        j
                  t        j                  t        j                  t        j
                  d}d}ng g g g f\  }}}}	 |j                  ||||       t        j                  t        j                  t        j                  t        j
                  t        j
                  t        j                  t        j
                  t        j                  t        j
                  d	}d}|H|j                  |j                         D 	ci c]  }	|	j                  ||	j                  d      ! c}	       |H|j                  |j                         D 	ci c]  }	|	j                  ||	j                  d      ! c}	       |M|j!                  |j"                  j%                         D 
ci c]  \  }
}|
||j                  d       c}}
       |M|j'                  |j"                  j%                         D 
ci c]  \  }
}|
||j                  d       c}}
       |j)                  |j+                  |      t        j
                        }|j-                  |       |S #  d\  }}Y xY w#  d\  }}}}Y xY wc c}	w c c}	w c c}}
w c c}}
w # t.        j0                  t.        j2                  t.        j4                  f$ r}t7        t9        |            d }~ww xY w)N)NNr7   r6   )NNNNr?   r>   r	   )r   r   r   	getmipsolr   rR   rS   rT   getlpsolrU   rV   rc   rm   rK   _xprsrd   rf   r   itemsre   rN   	getAttribrg   rx   r   r   r   r   r   )r#   r   r   xr|   r}   djsrq   rr   rn   nr   r   r   s                 r   findSolutionValueszXPRESS_PY.findSolutionValues  s   >	,NNEbzdhh(*Bd(:%65#+OOAv. !22 22 22 22 22 33 00 22		 (	 )+BB%65#CNN1feS9
 !22 00 33 22 22 22 22 22 22
	 '	}!!",,."QQ1661QWWQZ=#8"QR",,. QQQWWQZ!8 QR 8:8L8L8NOfq!Qaggaj))O !""9;9M9M9OPv1Qqwwqz**P ]]	*I,G,GF OOF#Mg+ *IAv"C,B)Avuc #R Q P Q !!6#8#8&:L:LM 	,!#c(++	,sy   .L K! B	L K. !B+L $K=0&L $L:1L +L
2L :L
A	L !K+(L .	K:7L 2MMMc                    | j                         sd}	 ddl}t	        |      | j                  |       | j                  ||       | j                  |      S # t        $ r}t        |      }Y d}~t	        |      d}~ww xY w)r.   zXPRESS Python API not availabler	   N)r,   rx   ImportErrorr   r   buildSolverModelr   r   )r#   r   r   messagerx   r   s         r   r   zXPRESS_PY.actualSolve  sy    ~~7G# "'**b!G$&&r**  #c(!'**#s   A 	A? A::A?c                    | j                  |       	 |j                  }dD ]6  \  }}| j                  j                  |d      }|%|j	                  ||       8 | j
                  D ]  }t        |t              r|d   }|d   }n]|j                  dd      }t        |      dk7  rt        dt        |      z         |d   j                         }|d   j                         }	 |j	                  |t        |              | j                  j                  dd	      rt!               }t!               }	t#        |j%                         d
       D ]P  }
|
j'                         |j)                  |
j'                                |	j)                  |
j*                  d          R t-        |      rT| j.                  rHt        |      |j0                  j2                  k(  r|j5                  |       n(|j7                  ||	d       n|j9                  |ddd       | j:                  rd }|j=                  |       yy# t        $ r Y nw xY w	 |j	                  |t        |             # t        $ r Y nw xY w|j	                  ||       # t>        j@                  t>        jB                  t>        jD                  f$ r}t        t        |            d}~ww xY w)zP
        Takes the pulp lp model and translates it into an xpress model
        ))r   
MIPRELSTOP)r   MAXTIME)r   HEURFREQ)r   HEURSTRATEGY)r   	COVERCUTS)r    PRESOLVENr	   r   r   r   zInvalid option r!   Fc                      | j                   d   S Nr	   r   r   s    r   <lambda>z,XPRESS_PY.buildSolverModel.<locals>.<lambda>2  s    aggaj r   key	warmstartc                 &    |dkD  rt        |       y y r   )print)probdatar   msgtypes       r   r   z+XPRESS_PY.buildSolverModel.<locals>.messageC  s    {c
 #r   )#_extractr   rM   rN   
setControlr   
isinstancetupler   r   r   r   r   r   r   r   listsortedrm   rO   appendr   r   r   
attributesr   
loadmipsol	addmipsol	loadlpsolr   addcbmessagerx   r   r   r   )r#   r   r   r   rK   rO   rt   r   solvalcolindrn   r   r   s                r   r   zXPRESS_PY.buildSolverModel  s    	bK	, NNE 
2	T ((,,S$7$$$T51
2 ,, .fe,!!9D"1IE#\\#q1F6{a'-.?#f+.MNN!!9??,D"1IOO-E$$T3u:6., ##K74HI 2Awwy,aggi0aggaj12 ":$(( 6{e&6&6&;&;;((0DOOFD$=xx# ""7+ 7 " $$T5<8!   u-6 !!6#8#8&:L:LM 	,!#c(++	,sn   2J BJ "H3=A!J CJ 3	H?<J >H??J I J  	I,)J +I,,J 2K5K		Kc                    	 t               }t               }t        |j                        D ]o  }|j                  |   }|j                  st	        |d      st        d      |j                  |j                  d          |j                  |j                          q t        |      dkD  r|j                  j                  ||       t               }t               }t               }	|j                         D ]  }
|
j                  st	        |
d      st        d      |j                  |
j                  d          |j                  d       |	j                  |
j                  t        j                   n|
j                         |j                  |
j                  d          |j                  d       |	j                  |
j                   t        j                  n|
j                           t        |      dkD  r|j                  j#                  |||	       | j%                  ||       | j'                  |      S # t        j(                  t        j*                  t        j,                  f$ r}t        t/        |            d}~ww xY w)z>Resolve a problem that was previously solved by actualSolve().r   zCannot add new constraintsr	   zCannot add new variablesLNG)r   r   r   r   hasattrr   r   r   constantr   r   chgrhsrm   lowBoundrx   infinityupBound	chgboundsr   r   r   r   r   r   )r#   r   r   rhsindrhsvalrK   conbndindbndtypebndvalrn   r   s               r   actualResolvezXPRESS_PY.actualResolveK  s   &	,VFVFr~~. 	-nnT*||sG,)*FGGciil+s||m,	- 6{Q%%ff5VFfGVF\\^ Szzq'*)*DEEaggaj)s#!**2Dv.!**Uaggaj)s#1Bfoo		RS 7|a((&AOOB(**2..!!6#8#8&:L:LM 	,!#c(++	,s   H6H9 92J+I??Jc                     t        | d      rt        | d       | j                         D ]  }t        |d      st        |d        | j                  j	                         D ]  }t        |d      st        |d        y)z,Reset any XPRESS specific information in lp.r   r   N)r   delattrrm   r   rz   )r   rn   r   s      r   _resetzXPRESS_PY._resetu  ss     2}%B& 	$Aq'"7#	$ &&( 	$Aq'"7#	$r   c           
      	   | j                  |       	 t        j                         }|j                  t        j
                  k(  r|j                  t        j                         t               }t               }t               }t               }t               }|j                         D ]'  }|j                  |j                  t        j                   n|j                         |j                  |j                  t        j                  n|j                         |j                  |j                  j                  |d             |j                   t        j"                  k(  r|j                  d       n@|j                   t        j$                  k(  r|j                  d       n|j                  d       |j                  |j&                         * |j)                  |dgt+        |      dz   z  g g ||||       t-        t/        |j                         |j1                                     D ]  \  }	\  }}
|	|
f|_         t               }t-        t5        |j6                              D ]  \  }}|j6                  |   }t        j9                  d t5        |j;                         d	 
      D              }|j<                   }|j                  t        j>                  k(  r't        jA                  |t        jB                  |      }n|j                  t        jD                  k(  r't        jA                  |t        jF                  |      }ne|j                  t        jH                  k(  r't        jA                  |t        jJ                  |      }n!tM        dtO        |j                        z         |j                  |||f       t+        |      dkD  sj|jQ                  |D cg c]  \  }}}|
 c}}       |D ]  \  }}}||f|_         t               } t+        |      dkD  r9|jQ                  |D cg c]  \  }}}|
 c}}       |D ]  \  }}}||f|_         d } |||jR                  d        |||jT                  d       ||_+        yc c}}w c c}}w # t        jX                  t        jZ                  t        j\                  f$ r*}| j                  |       tM        tO        |            d}~ww xY w)a  Extract a given model to an XPRESS Python API instance.

        The function stores XPRESS specific information in the `solverModel` property
        of `lp` and each variable and constraint. These information can be
        removed by calling `_reset`.
        Ng        IBr   r	   r   c              3   F   K   | ]  \  }}||j                   d    z    yw)r   Nr   ).0r   as      r   	<genexpr>z%XPRESS_PY._extract.<locals>.<genexpr>  s(      !1 
N!s   !c                 &    | d   j                   d   S r   r   r   s    r   r   z$XPRESS_PY._extract.<locals>.<lambda>  s    !A$**Q- r   r   )bodysenserhszUnsupprted constraint type d   c                 ^   g }t        |      D ]  }g }g }||   j                         D ]4  \  }}|j                  |j                  d          |j                  |       6 |j                  t        j                  |||t        |                    t        |      r| j                  |       yy)z"Extract sos constraints from PuLP.r	   N)	r   r   r   r   rx   sosr   r   addSOS)	msosdictsostypesoslistrK   indicesweightsrn   vals	            r   addsosz"XPRESS_PY._extract.<locals>.addsos  s     #7O UD G G")$-"5"5"7 ,3qwwqz2s+, NN6::gwT#STU w<HHW%  r   r   )/r  rx   problemr  r   
LpMaximizechgobjsensemaximizer   rm   r   r   r   r   	objectiverN   cat	LpIntegerLpBinaryrK   addcolsr   r   zipgetVariabler   r   r   Sumr   r   LpConstraintLE
constraintleqLpConstraintGEgeqLpConstraintEQeqr   r   addConstraintr   r   r   r   r   r   )r#   r   r   objlbubctypenamesrn   jr   consr   rK   r   lhsr  r   ry   r  r   s                        r   r   zXPRESS_PY._extract  s    	BW	,NN$Exx9///!!&//2
 &CBBFEFE\\^ 
%		ajj.@6??*ajjQ		QYY->&//AIIN

2<<++As3455I///LL%UUi000LL%LL%QVV$
% MM#sc#hl3RRUER&s2<<>5;L;L;N'OP !	6Aqa&! 6D$VBNN%;< "4nnT* jj ! &syy{8O P!  ||m99	 8 88))s&**#)NAYY)":"::))s&**#)NAYY)":"::))s&)))MA)5CIIF  Q3K(t9s?''$(?wq!Q(?@%) +	1c%&F	+6D1"2 4y1}##d$;71aQ$;<!% 'IAq#!"ACI'&  5"''1%5"''1%"BN; )@
 %<2 !!6#8#8&:L:LM 	,KKO!#c(++	,s>   N:R R R,AR 3R
 AR R 2S7%S22S7c                 8    |j                   j                  |      S )z`Get an arbitrary attribute for the model that was previously
        solved using actualSolve().)r   r   )r#   r   whichs      r   getAttributezXPRESS_PY.getAttribute  s     ~~''..r   )TTNNNNNNNNN)N)r   r   r   r   rK   r"   r,   r   r   r   r   r   r   r  r   r7  r   r   r   r   r   <  sv    :D 7r,@?,B+P,d(,T 	$ 	$_,B/r   r   )corer   r   r   r    r   rZ   r   r   r   
XPRESS_CMDrx   r   r   r   r   <module>r;     sE   6 F E  
 	6K?\ K?\ 
	i/ i/r   