
    khpT                        d dl mZ ddlmZmZmZmZmZmZ d dl	Z	d dl
Z
ddlmZ d dlmZ erddlmZ d dlZda G d	 d
e      Z G d de      Zy)    )annotations   )LpSolver_CMDLpSolver
subprocessPulpSolverErrorclocklogN   )	constants)TYPE_CHECKING)	LpProblemc                      e Zd ZdZd ZdZ	 ddla	 	 	 	 	 	 	 	 	 ddZd Z	d Z
d Zd Zd	 Zdd
Zd ZddZddZy#  d ZddZY yxY w)GUROBIz
    The Gurobi LP/MIP solver (via its python interface)

    The Gurobi variables are available (after a solve) in var.solverVar
    Constraints in constraint.solverConstraint
    and the Model is in prob.solverModel
    Nr   c
           	     B   || _         |r|ni | _        | j                   dn|	| _        |
| _        d| _        d| _        t        j                  | ||||||       | j                  s;| j                  rd| j                  d<   yd| j                  d<   d| j                  d<   yy)a  
            :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 bool warmStart: if True, the solver will use the current value of variables as a start
            :param str logPath: path to the log file
            :param gp.Env env: Gurobi environment to use. Default None.
            :param dict envOptions: environment options.
            :param bool manageEnv: if False, assume the environment is handled by the user.


            If ``manageEnv`` is set to True, the ``GUROBI`` object creates a
            local Gurobi environment and manages all associated Gurobi
            resources. Importantly, this enables Gurobi licenses to be freed
            and connections terminated when the ``.close()`` function is called
            (this function always disposes of the Gurobi model, and the
            environment)::

                solver = GUROBI(manageEnv=True)
                prob.solve(solver)
                solver.close() # Must be called to free Gurobi resources.
                # All Gurobi models and environments are freed

            ``manageEnv=True`` is required when setting license or connection
            parameters. The ``envOptions`` argument is used to pass parameters
            to the Gurobi environment. For example, to connect to a Gurobi
            Cluster Manager::

                options = {
                    "CSManager": "<url>",
                    "CSAPIAccessID": "<access-id>",
                    "CSAPISecret": "<api-key>",
                }
                solver = GUROBI(manageEnv=True, envOptions=options)
                solver.close()
                # Compute server connection terminated

            Alternatively, one can also pass a ``gp.Env`` object. In this case,
            to be safe, one should still call ``.close()`` to dispose of the
            model::

                with gp.Env(params=options) as env:
                    # Pass environment as a parameter
                    solver = GUROBI(env=env)
                    prob.solve(solver)
                    solver.close()
                    # Still call `close` as this disposes the model which is required to correctly free env

            If ``manageEnv`` is set to False (the default), the ``GUROBI``
            object uses the global default Gurobi environment which will be
            freed once the object is deleted. In this case, one can still call
            ``.close()`` to dispose of the model::

                solver = GUROBI()
                prob.solve(solver)
                # The global default environment and model remain active
                solver.close()
                # Only the global default environment remains active
            NF)mipmsg	timeLimitgapRellogPath	warmStartr   
OutputFlag)	envenv_options
manage_envsolver_paramsmodelinit_gurobir   __init__r   )selfr   r   r   r   r   r   r   
envOptions	manageEnvsolverParamss              z/var/www/html/SchoolMeal/SchoolMeal/pds_admin_SchoolMeal/Backend/venv/lib/python3.12/site-packages/pulp/apis/gurobi_api.pyr   zGUROBI.__init__F   s    R DH-7zRD'+xx';eDO!-DDJ$D## 88??56D$$\256D$$\278D&&|4     c                $    | j                          y N)closer    s    r$   __del__zGUROBI.__del__   s    JJLr%   c                    | j                   sy| j                  j                          | j                  r| j                  j                          yy)z
            Must be called when internal Gurobi model and/or environment
            requires disposing. The environment (default or otherwise) will be
            disposed only if ``manageEnv`` is set to True.
            N)r   r   disposer   r   r)   s    r$   r(   zGUROBI.close   s<     ##JJ   " r%   c                Z   |j                   }|j                  }t        j                  }|j                  t
        j                  |j                  t
        j                  |j                  t
        j                  |j                  t
        j                  |j                  t
        j                  |j                  t
        j                  |j                  t
        j                  |j                   t
        j                  |j"                  t
        j                  |j$                  t
        j                  i
}| j&                  rt)        d|       d|_        |j,                  D ]	  }d|_         |j1                  |t
        j2                        }|j5                  |       |j6                  dk\  rt9        |j,                  |j;                  |j<                  j>                  |jA                                     D ]  \  }}||_!         t9        |jD                  jG                         |j;                  |j<                  jH                  |jK                                     D ]  \  }	}||	_&         |jN                  st9        |j,                  |j;                  |j<                  jP                  |jA                                     D ]  \  }}||_)         t9        |jD                  jG                         |j;                  |j<                  jT                  |jK                                     D ]  \  }	}||	_+         |S )NzGurobi status=TFr   ),solverModelStatusgpGRBOPTIMALr   LpStatusOptimal
INFEASIBLELpStatusInfeasibleINF_OR_UNBD	UNBOUNDEDLpStatusUnboundedITERATION_LIMITLpStatusNotSolved
NODE_LIMIT
TIME_LIMITSOLUTION_LIMITINTERRUPTEDNUMERICr   print	resolveOK
_variables
isModifiedgetLpStatusUndefinedassignStatusSolCountzipgetAttrAttrXgetVarsvarValueconstraintsvaluesSlack
getConstrsslackIsMIPRCdjPipi)
r    lpr   solutionStatusr1   gurobiLpStatusvarstatusvalueconstrs
             r$   findSolutionValueszGUROBI.findSolutionValues   s_   NNE"\\N&&C Y66	 < <!=!=y::##Y%@%@	 ; ;	 ; ;""I$?$?!<!<Y88N xx&7BL}} '!&'#''	8S8STFOOF#~~""%MM5==U]]_#M# )JC $)CL)
 &)NN))+MM#((..%2B2B2DE& )MFE $)FL	) {{&)u}}SXX[[%--/'R' '
U "''
 *---/chhkk53C3C3EF* * %*		*
 Mr%   c                    	 t         j                  | j                        5  	 ddd       y# 1 sw Y   yxY w# t         j                  $ r#}t	        j
                  d| d       Y d}~yd}~ww xY w)True if the solver is availableparamsNGUROBI error: .FT)r0   Envr   GurobiErrorwarningswarn)r    es     r$   	availablezGUROBI.available   se    VV4#3#3V4 
 
  >> qc34s)    9 -9 69 9 A/A**A/c                   | j                   ry d| _         	 | j                  rKt        j                  | j                        | _        t        j                  | j
                        | _        n%t        j                  | j
                        | _        | j                  j                         D ]!  \  }}| j                  j                  ||       # y # t        j                  $ r}|d }~ww xY w)NTrb   )r   )r   r   r0   rf   r   r   Modelr   r   itemssetParamrg   )r    paramr]   rj   s       r$   
initGurobizGUROBI.initGurobi   s    #' ??!vvT-=-=v>DH!#dhh!7DJ "$dhh!7DJ$($6$6$<$<$> 6LE5JJ''u56>> s   B:C C+$C&&C+c                    t                | _        |j                  j                  |       | xj                  t               z  c_        y)zSolves the problem with gurobicallbackN)r	   	solveTimer.   optimizer    rX   rt   s      r$   
callSolverzGUROBI.callSolver  s4     $gXDNNN##X#6NNeg%Nr%   c                t	   t        j                  d       | j                          |j                  | j                  _        | j                  |_        t        j                  d       |j                  t        j                  k(  r|j                  j                  dd       | j                  r&|j                  j                  d| j                         | j                  j                  d      }| j                  j                  d      }|r|j                  j                  d|       |r|j                  j                  d	|       t        j                  d
       |j                  j                          |j                  j                   }|j#                         D ]  }|j$                  }|t&        j(                  j*                   }|j,                  }|t&        j(                  j*                  }|j.                  j                  |d      }t&        j(                  j0                  }	|j2                  t        j4                  k(  r&| j6                  rt&        j(                  j8                  }	t;        |d      r|dk(  s|j                  j=                  |||	||j                        |_         | j                  j                  dd      r9|j@                  D ]*  }|jB                  |jB                  |j>                  _"        , |j                  j                          t        j                  d       |jF                  jI                         D ]M  \  }
}t&        jK                  tM        |jO                               |jQ                         D cg c]  }|j>                   c}      }|j                  t        jR                  k(  r1|j                  jU                  ||jV                   k  |
      |_,        |j                  t        jZ                  k(  r1|j                  jU                  ||jV                   k\  |
      |_,        |j                  t        j\                  k(  r2|j                  jU                  ||jV                   k(  |
      |_,        Et_        d       |j                  j                          yc c}w )zW
            Takes the pulp lp model and translates it into a gurobi model
            zcreate the gurobi modelzset the sense of the problem
ModelSense	TimeLimitr   r   MIPGapLogFilez add the variables to the problemNg        	solverVarr   )vtypeobjnamer   Fz"add the Constraints to the problem)r   z#Detected an invalid constraint type)0r
   debugrq   r   r   	ModelNamer.   senser   
LpMaximizesetAttrr   ro   optionsDictrD   updateNumVars	variableslowBoundr0   r1   INFINITYupBound	objective
CONTINUOUScat	LpIntegerr   INTEGERhasattraddVarr   rB   rM   startrN   rn   LinExprlistrO   keysLpConstraintLE	addConstrconstantsolverConstraintLpConstraintGELpConstraintEQr   )r    rX   r   r   nvarsr[   r   r   r   varTyper   
constraintvexprs                 r$   buildSolverModelzGUROBI.buildSolverModel  s    II/0OO#%77DJJ !ZZBNII45xx9///&&|R8~~''T^^D%%))(3F&&**95G''&9''	7;II89NN!!#NN**E||~ <<# "/H++? ffooGll&&sC0&&++77i111dhh ffnnGsK0EQJ$&NN$9$9 'c %: %CM  ##K7 == ;C||/.1ll+; NN!!#II:;$&NN$8$8$: Q jzz**,-Z__EV/W/W ##y'?'??24..2J2J!4!4 444 3K 3J/  %%)A)AA24..2J2J!4!4 444 3K 3J/  %%)A)AA24..2J2J!4!4 444 3K 3J/ **OPP%Q& NN!!#! 0Xs   	R5c                   | j                  |       t        j                  d       | j                  ||       | j	                  |      }|j
                  D ]	  }d|_         |j                  j                         D ]	  }d|_         |S )z
            Solve a well formulated lp problem

            creates a gurobi model, variables and constraints and attaches
            them to the lp model which it then solves
            zSolve the Model using gurobirs   F)	r   r
   r   rx   r_   rB   modifiedrN   rO   )r    rX   rt   rY   r[   r   s         r$   actualSolvezGUROBI.actualSolveR  s     !!"%II45OOBO2!44R8N}} %$% nn335 ,
&+
#,!!r%   c                   t        j                  d       |j                  j                         D ]X  }|j                  s|j
                  j                  t        j                  j                  j                  |j                          Z |j                  j                          | j                  ||       | j                  |      }|j                   D ]	  }d|_         |j                  j                         D ]	  }d|_         |S )z
            Solve a well formulated lp problem

            uses the old solver and modifies the rhs of the modified constraints
            zResolve the Model using gurobirs   F)r
   r   rN   rO   r   r   r   r0   r1   rJ   RHSr   r.   r   rx   r_   rB   )r    rX   rt   r   rY   r[   s         r$   actualResolvezGUROBI.actualResolvee  s     II67 nn335 
&&//77**=*=)=
 NN!!#OOBO2!44R8N}} %$% nn335 ,
&+
#,!!r%   c                     y)ra   F r)   s    r$   rk   zGUROBI.available<   s    r%   c                    t        d      )"Solve a well formulated lp problemzGUROBI: Not Available)r   rw   s      r$   r   zGUROBI.actualSolve@   s    !"9::r%   )	TTNNFNNNFr'   )__name__
__module____qualname____doc__r   r   gurobipyr0   r   r*   r(   r_   rk   rq   rx   r   r   r   r   r%   r$   r   r   *   s     D
CC" 	 a	9F	
	#0	d		$	&C	$J	"&	"W	;		;s	   < 	Ar   c                  X    e Zd ZdZd Z	 	 	 	 	 	 	 	 	 	 	 	 d
dZd Zd Zd Zd Z	d Z
d	 Zy)
GUROBI_CMDzThe GUROBI_CMD solverNc                F    t        j                  | |||||||	||
||       y)a.  
        :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 float gapAbs: absolute gap tolerance for the solver to stop
        :param int threads: sets the maximum number of threads
        :param list options: list of additional options to pass to solver
        :param bool warmStart: if True, the solver will use the current value of variables as a start
        :param bool keepFiles: if True, files are saved in the current directory and not deleted after solving
        :param str path: path to the solver binary
        :param str logPath: path to the log file
        )r   r   r   r   optionsr   path	keepFilesthreadsgapAbsr   N)r   r   )r    r   r   r   r   r   r   r   r   r   r   r   	mip_starts                r$   r   zGUROBI_CMD.__init__  s6    8 		
r%   c                $    | j                  d      S )N	gurobi_cl)executableExtensionr)   s    r$   defaultPathzGUROBI_CMD.defaultPath  s    ''44r%   c                ,   | j                  | j                        syt        j                  | j                  t        j                  d      }|j                         \  }}|j                  dk(  ry| j                  rt        j                  d| d       y)ra   FT)stdoutuniversal_newlinesr   rd   re   )

executabler   r   PopenPIPEcommunicate
returncoder   rh   ri   )r    resultouterrs       r$   rk   zGUROBI_CMD.available  sz    tyy) !!IIjoo$
 %%'S!88MMN3%q12r%   c                p   | j                  | j                        st        d| j                  z         | j                  |j                  ddd      \  }}}|j                  |d      }	 t        j                  |       | j                  }| j                  | j                         z   }| j                  |j                  d| j                  f       |d	d	j                  |D 	cg c]  \  }}	| d
|	  c}	}      z   z  }|d| z  }| j                  j                  dd      r| j                  ||       |d| z  }|j!                         r!| j"                  st%        j&                  d       |d	| z  }| j)                         }
t+        j,                  |j/                         |
|
      }|
|
j1                          |dk7  rt        d| j                  z         t        j                  j3                  |      st4        j6                  }dx}x}x}}n| j9                  |      \  }}}}}| j;                  |||d       |t4        j<                  k7  rD|j?                  |       |jA                  |       |jC                  |       |jE                  |       |jG                  |       |S #  Y 0xY wc c}	}w )r   zPuLP: cannot execute rX   solmstr   )writeSOSNr|    =z ResultFile=r   F)filenamevsz InputFile=z1GUROBI_CMD does not allow a problem to be relaxed)r   stderrr   z$PuLP: Error while trying to execute z
gurobi.log)$r   r   r   create_tmp_filesr   writeLPosremover   
getOptionsr   appendjoinr   rD   writesolisMIPr   rh   ri   get_piper   callsplitr(   existsr   r:   readsoldelete_tmp_filesr5   assignVarsValsassignVarsDjassignConsPiassignConsSlackrF   )r    rX   tmpLptmpSoltmpMstr   cmdr   keyr]   pipereturn_coder\   rO   reducedCostsshadowPricesslackss                    r$   r   zGUROBI_CMD.actualSolve  sg    tyy)!"9DII"EFF $ 5 5bggtUE RvvZZZ*	IIf ii,,!22>>%NNK89sSXX'JJC#aw/JKKKfX&&U3MM6bM1[))C88:88QR5'{}} oociik$tL JJL!!"H499"TUUww~~f%00F<@@F@\@L6 BFfAU>FFL,eVV\BY111f%OOL)OOL)v&
Q	
 Ks   *J* #J2*J/c                b   t        |      5 }	 t        |       t        j
                  }i }i }i }i }i }i }|D ],  }|d   dk7  s|j                         \  }	}
t        |
      ||	<   . 	 ddd       fS # t        $ r# t        j                  }|i i i i fcY cddd       S w xY w# 1 sw Y   ?xY w)zRead a Gurobi solution fileNr   #)opennextStopIterationr   r:   r3   r   float)r    r   my_filer\   r   r   rO   r   liner   r]   s              r$   r   zGUROBI_CMD.readsol  s    (^ 	0w.W ..FLFLFFL 07c>"&**,KD%#(<F4L0#	0* v|\6AA% ! ."44r2r2--	0 	0.	0 	0s3   B%A6)B%#B%6 B"B%!B""B%%B.c                H   |D cg c]/  }|j                         |j                  |j                         f1 }}g }|D ]  \  }}|j                  | d|         t        |d      5 }|j	                  dj                  |             ddd       yc c}w # 1 sw Y   yxY w)zWrites a GUROBI solution fileNr   w
T)r]   r   r   r   writer   )	r    r   r   r   rO   rowsr   r]   fs	            r$   r   zGUROBI_CMD.writesol  s     02K!QWWY5J1661779%KK! 	+KD%KK4&%)*	+(C  	%AGGDIIdO$	% L	%s   BB)!BB!c                    t        dddd      }|j                         D cg c]3  \  }}|| j                  v r | j                  |   || j                  |   f5 c}}S c c}}w )Nr~   r}   	MIPGapAbsThreads)r   r   r   r   )dictrn   r   )r    	params_eqkr   s       r$   r   zGUROBI_CMD.getOptions  ss    	
	 ")
1D$$$)9)9!)<)H   #$
 	
 
s   8A)TTNNNNFFNNNF)r   r   r   r   r   r   r   rk   r   r   r   r   r   r%   r$   r   r   |  sV    D )
V5$1fB2	
r%   r   )
__future__r   corer   r   r   r   r	   r
   r   sys r   typingr   r   rh   r0   r   r   r   r%   r$   <module>r     sI   6 # Q Q 	 
     
O"X O"d
h
 h
r%   