Ticket #6869: MIP-now-symbolic.patch

File MIP-now-symbolic.patch, 31.9 KB (added by ncohen, 11 years ago)
  • module_list.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1251911520 -7200
    # Node ID be8e3da6ae8b19599dfe798c71218ea899ac1d9d
    # Parent  331c64c92f35d0a430f4f212fbbcfaab4a87b31e
    Brand new version of the MIP class, using algebra istead of dictionaries.
    
    Let's say it is the first version that ever existed :-)
    
     ( Now with coverage = 100 % )
    
    diff -r 331c64c92f35 -r be8e3da6ae8b module_list.py
    a b  
    873873    #           sources = ['sage/modules/vector_rational_sparse.pyx'],
    874874    #           libraries = ['gmp']),
    875875
     876    ################################
     877    ##
     878    ## sage.numerical
     879    ##
     880    ################################
     881
     882
     883    Extension("sage.numerical.mip",
     884              ["sage/numerical/mip.pyx"],
     885            include_dirs=["local/include/"],
     886            libraries=["csage","stdc++"]),
     887
    876888
    877889    ################################
    878890    ##
  • sage/numerical/all.py

    diff -r 331c64c92f35 -r be8e3da6ae8b sage/numerical/all.py
    a b  
    11from optimize import (find_root, find_maximum_on_interval,
    22                      find_minimum_on_interval,minimize,minimize_constrained,
    33                      linear_program, find_fit)
     4from sage.numerical.mip import *
  • new file sage/numerical/mip.pxd

    diff -r 331c64c92f35 -r be8e3da6ae8b sage/numerical/mip.pxd
    - +  
     1cdef extern from *:
     2    ctypedef double* const_double_ptr "const double*"
     3 No newline at end of file
  • new file sage/numerical/mip.pyx

    diff -r 331c64c92f35 -r be8e3da6ae8b sage/numerical/mip.pyx
    - +  
     1include '../ext/stdsage.pxi'
     2
     3class MIP:
     4    r"""
     5    The MIP class is the link between SAGE and LP ( Linear Program ) and
     6    MIP ( Mixed Integer Program ) Solvers. Cf : http://en.wikipedia.org/wiki/Linear_programming
     7
     8    It consists of variables, linear constraints on these variables, and an objective
     9    function which is to be maximised or minimised under these constraints.
     10
     11    An instance of ``MIP`` also requires the information
     12    on the direction of the optimization :
     13   
     14    A ``MIP`` ( or ``LP`` ) is defined as a maximization
     15    if ``sense=1``, and is a minimization if ``sense=-1``
     16
     17    INPUT:
     18       
     19        - ``sense'' :
     20                 * When set to `1` (default), the ``MIP`` is defined as a Maximization
     21                 * When set to `-1`, the ``MIP`` is defined as a Minimization
     22   
     23    EXAMPLES::
     24
     25         sage: ### Computation of a maximum stable set in Petersen's graph ###
     26         sage: g=graphs.PetersenGraph()
     27         sage: p=MIP(sense=1)
     28         sage: b=p.newvar()
     29         sage: p.setobj(sum([b[v] for v in g]))
     30         sage: for (u,v) in g.edges(labels=None):
     31         ...       p.addconstraint(b[u]+b[v],max=1)
     32         sage: p.setbinary(b)
     33         sage: p.solve(objective_only=True)     # optional - requires Glpk or COIN-OR/CBC
     34         4.0
     35    """       
     36
     37    def __init__(self,sense=1):
     38        r"""
     39        Constructor for the MIP class
     40
     41        INPUT:
     42       
     43        - ``sense'' :
     44                 When set to 1, the MIP is defined as a Maximization
     45                 When set to -1, the MIP is defined as a Minimization
     46
     47        EXAMPLE:
     48
     49            sage: p=MIP(sense=1)
     50        """
     51
     52        try:
     53             from sage.numerical.mipCoin import solveCoin
     54             self.default_solver="Coin"
     55        except:
     56             try:
     57                  from sage.numerical.mipGlpk import solveGlpk
     58                  self.default_solver="GLPK"
     59             except:
     60                  self.default_solver=None
     61       
     62
     63        from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing
     64        from sage.rings.real_double import RealDoubleField as RR
     65        P = InfinitePolynomialRing(RR(), names=('x',));
     66        (self.x,) = P._first_ngens(1)
     67
     68        self.count=[0]
     69        self.sense=sense
     70        self.objective=None
     71        self.variables={}
     72        self.constraints=[]
     73        self.min={}
     74        self.max={}
     75        self.types={}
     76        self.values={}
     77        self.__BINARY=1
     78        self.__REAL=-1
     79        self.__INTEGER=0
     80
     81    def __repr__(self):
     82         r"""
     83         Returns a short description of the MIP
     84         
     85         EXAMPLE:
     86         
     87         sage: p=MIP()
     88         sage: v=p.newvar()
     89         sage: p.addconstraint(v[1]+v[2],max=2)
     90         sage: print p
     91         Mixed Integer Program ( maximization, 2 variables, 1 constraints )
     92         """
     93         return "Mixed Integer Program ( "+("maximization" if self.sense==1 else "minimization")+", "+str(len(self.variables))+" variables, "+str(len(self.constraints))+" constraints )"
     94
     95    def newvar(self,dim=1):
     96        r"""
     97        Returns an instance of ``MIPVariable`` associated
     98        to the current instance of ``MIP``.
     99       
     100        A new ``MIP`` variable ``x`` defined by :::
     101
     102            sage: p=MIP()
     103            sage: x=p.newvar()
     104
     105        It behaves exactly as an usual dictionary would. It can use any key
     106        argument you may like, as ``x[5]`` or ``x["b"]``, and has methods
     107        ``items()`` and ``keys()``
     108       
     109        Any of its fields exists, and is uniquely defined.
     110
     111        INPUT:
     112
     113        - ``dim`` ( integer ) : Defines the dimension of the dictionary
     114                      If ``x`` has dimension `2`, its fields will
     115                      be of the form ``x[key1][key2]``
     116
     117        EXAMPLE::
     118
     119            sage: p=MIP()
     120            sage: x=p.newvar()
     121            sage: y=p.newvar(dim=2)
     122            sage: p.addconstraint(x[2]+y[3][5],max=2)
     123        """
     124        return MIPVariable(self.x,self._addElementToRing,dim=dim)
     125         
     126
     127    def export(self,format="text"):
     128         r"""
     129         Exports the MIP to a string in different formats.
     130         
     131         INPUT:
     132         
     133         - ``format'' :
     134                   "text" : human-readable format
     135
     136         sage: p=MIP()
     137         sage: x=p.newvar()
     138         sage: p.setobj(x[1]+x[2])
     139         sage: p.addconstraint(-3*x[1]+2*x[2],max=2)
     140         sage: print p.export(format="text")
     141         Maximization :
     142           x2 + x1
     143         Constraints :
     144           2.0*x2 - 3.0*x1
     145         Variables :
     146           x2 is a real variable (min=0.0,max=+oo)
     147           x1 is a real variable (min=0.0,max=+oo)
     148         """
     149         if format=="text":
     150              value=("Maximization :\n" if self.sense==1 else "Minimization :\n")
     151              value=value+"  "+(str(self.objective) if self.objective!=None else "Undefined")
     152              value=value+"\nConstraints :"
     153              for c in self.constraints:
     154                   value=value+"\n  "+str(c["function"])
     155              value=value+"\nVariables :"
     156              for v in self.variables.keys():
     157                   value=value+"\n  "+str(v)+" is"
     158                   if self.isinteger(v):
     159                       value=value+" an integer variable"
     160                   elif self.isbinary(v):
     161                       value=value+" an boolean variable"                       
     162                   else:
     163                       value=value+" a real variable"
     164                   value+=" (min="+(str(self.getmin(v)) if self.getmin(v)!= None else "-oo")+",max="+(str(self.getmax(v)) if self.getmax(v)!= None else "+oo")+")"
     165              return value
     166
     167    def get_values(self,*lists):
     168        r"""
     169        Return values found by the previous call to ``solve()``
     170
     171        INPUT:
     172       
     173        - Any instance of ``MIPVariable`` ( or one of its elements ),
     174          or lists of them.
     175
     176        OUTPUT:
     177
     178        - Each instance of ``MIPVariable`` is replaced by a dictionary
     179           containing the numerical values found for each
     180           corresponding variable in the instance
     181        - Each element of an instance of a ``MIPVariable`` is replaced
     182           by its corresponding numerical value.
     183
     184        EXAMPLE::
     185
     186            sage: p=MIP()
     187            sage: x=p.newvar()
     188            sage: y=p.newvar(dim=2)
     189            sage: p.setobj(x[3]+y[2][9]+x[5])
     190            sage: p.addconstraint(x[3]+y[2][9]+2*x[5],max=2)
     191            sage: p.solve() # optional - requires Glpk or COIN-OR/CBC
     192            2.0
     193            sage: #
     194            sage: # Returns the optimal value of x[3]
     195            sage: p.get_values(x[3]) # optional - requires Glpk or COIN-OR/CBC
     196            0.0
     197            sage: #
     198            sage: # Returns a dictionary identical to x
     199            sage: # containing values for the corresponding
     200            sage: # variables
     201            sage: x_sol=p.get_values(x)
     202            sage: x_sol.keys()
     203            [3, 5]
     204            sage: #
     205            sage: # Obviously, it also works with
     206            sage: # variables of higher dimension
     207            sage: y_sol=p.get_values(y)
     208            sage: #
     209            sage: # We could also have tried :
     210            sage: [x_sol,y_sol]=p.get_values(x,y)
     211            sage: # Or
     212            sage: [x_sol,y_sol]=p.get_values([x,y])
     213        """
     214
     215        val=[]
     216        for l in lists:
     217            if isinstance(l,MIPVariable):
     218                if l.depth()==1:
     219                    c={}
     220                    for (k,v) in l.items():
     221                        c[k]=self.values[v] if self.values.has_key(v) else None
     222                    val.append(c)
     223                else:
     224                    c={}
     225                    for (k,v) in l.items():
     226                        c[k]=self.get_values(v)
     227                    val.append(c)                   
     228            elif isinstance(l,list):
     229                if len(l)==1:
     230                    val.append([self.get_values(l[0])])
     231                else:
     232                    c=[]
     233                    [c.append(self.get_values(ll)) for ll in l]
     234                    val.append(c)
     235            elif self.variables.has_key(l):
     236                val.append(self.values[l])
     237        if len(lists)==1:
     238            return val[0]
     239        else:
     240            return val
     241               
     242           
     243
     244    def show(self):
     245        r"""
     246        Prints the MIP in a human-readable way
     247
     248        EXAMPLE:
     249
     250        sage: p=MIP()
     251        sage: x=p.newvar()
     252        sage: p.setobj(x[1]+x[2])
     253        sage: p.addconstraint(-3*x[1]+2*x[2],max=2)
     254        sage: p.show()
     255        Maximization :
     256          x2 + x1
     257        Constraints :
     258          2.0*x2 - 3.0*x1
     259        Variables :
     260          x2 is a real variable (min=0.0,max=+oo)
     261          x1 is a real variable (min=0.0,max=+oo)
     262        """
     263        print self.export(format="text")
     264       
     265    #Ok
     266    def setobj(self,obj):
     267        r"""
     268        Sets the objective of the ``MIP``.
     269
     270        INPUT:
     271       
     272        - ``obj`` : A linear function to be optimized
     273
     274        EXAMPLE::
     275       
     276           This code solves the following Linear Program :
     277           
     278           Maximize:
     279              x + 5 * y
     280           Constraints:
     281              x + 0.2 y       <= 4
     282              1.5 * x + 3 * y   <=4
     283           Variables:
     284              x is Real ( min = 0, max = None )
     285              y is Real ( min = 0, max = None )
     286
     287           sage: p=MIP(sense=1)
     288           sage: x=p.newvar()
     289           sage: p.setobj(x[1]+5*x[2])
     290           sage: p.addconstraint(x[1]+0.2*x[2],max=4)
     291           sage: p.addconstraint(1.5*x[1]+3*x[2],max=4)
     292           sage: p.solve()     # optional - requires Glpk or COIN-OR/CBC
     293           6.6666666666666661
     294           
     295        """
     296        self.objective=obj
     297
     298    def addconstraint(self,linear_function,max=None,min=None):
     299        r"""
     300        Adds a constraint to the MIP
     301       
     302        INPUT :
     303
     304        - ``consraint`` : : A linear function
     305        - ``max``  : An upper bound on the constraint ( set to ``None`` by default )
     306        - ``min``  : A lower bound on the constraint
     307
     308        EXAMPLE::
     309       
     310           This code solves the following Linear Program :
     311           
     312           Maximize:
     313              x + 5 * y
     314           Constraints:
     315              x + 0.2 y       <= 4
     316              1.5 * x + 3 * y   <=4
     317           Variables:
     318              x is Real ( min = 0, max = None )
     319              y is Real ( min = 0, max = None )
     320
     321           sage: p=MIP(sense=1)
     322           sage: x=p.newvar()
     323           sage: p.setobj(x[1]+5*x[2])
     324           sage: p.addconstraint(x[1]+0.2*x[2],max=4)
     325           sage: p.addconstraint(1.5*x[1]+3*x[2],max=4)
     326           sage: p.solve()     # optional - requires Glpk or COIN-OR/CBC
     327           6.6666666666666661
     328        """
     329
     330        max=float(max) if max!=None else None
     331        min=float(min) if min!=None else None
     332        self.constraints.append({"function":linear_function,"min":min, "max":max,"card":len(linear_function.variables())})
     333
     334    def setbinary(self,e):
     335        r"""
     336        Sets a variable or a ``MIPVariable`` as binary
     337
     338        INPUT:
     339
     340        - ``e`` : An instance of ``MIPVariable`` or one of
     341                  its elements
     342
     343        NOTE:
     344
     345        We recommend you to define the types of your variables after
     346        your problem has been completely defined ( see example )
     347
     348        EXAMPLE:
     349
     350          sage: p=MIP()
     351          sage: x=p.newvar()
     352          sage: #
     353          sage: # The following instruction does absolutely nothing
     354          sage: # as none of the variables of x have been used yet
     355          sage: p.setbinary(x)
     356          sage: p.setobj(x[0]+x[1])
     357          sage: p.addconstraint(-3*x[0]+2*x[1],max=2)
     358          sage: #
     359          sage: # This instructions sets x[0] and x[1]
     360          sage: # as binary variables
     361          sage: p.setbinary(x)
     362          sage: p.addconstraint(x[3]+x[2],max=2)
     363          sage: #
     364          sage: # x[3] is not set as binary
     365          sage: # as no setbinary(x) has been called
     366          sage: # after its first definition
     367          sage: #
     368          sage: # Now it is done
     369          sage: p.setbinary(x[3])
     370        """
     371        if isinstance(e,MIPVariable):
     372            if e.depth()==1:
     373                for v in e.values():
     374                    self.types[v]=self.__BINARY               
     375            else:
     376                for v in e.keys():
     377                    self.setbinary(e[v])
     378        elif self.variables.has_key(e):       
     379            self.types[e]=self.__BINARY
     380        else:
     381            raise Exception("Wrong kind of variable..")
     382
     383    def isbinary(self,e):
     384        r"""
     385        Tests whether the variable is binary.
     386
     387        ( Variables are real by default )
     388
     389        INPUT:
     390
     391        - ``e`` : a variable ( not a ``MIPVariable``, but one of its elements ! )
     392
     393        OUTPUT:
     394
     395        ``True`` if the variable is binary, ``False`` otherwise
     396
     397        EXAMPLE:
     398
     399            sage: p=MIP()
     400            sage: v=p.newvar()
     401            sage: p.setobj(v[1])
     402            sage: p.isbinary(v[1])
     403            False
     404            sage: p.setbinary(v[1])           
     405            sage: p.isbinary(v[1])
     406            True
     407        """
     408        # Returns an exception if the variable does not exist..
     409        # For exemple if the users tries to find out the type of
     410        # a MIPVariable or anything else
     411        self.variables[e]
     412
     413        if self.types.has_key(e) and self.types[e]==self.__BINARY:
     414            return True
     415        return False
     416
     417    def setinteger(self,e):
     418        r"""
     419        Sets a variable or a ``MIPVariable`` as integer
     420
     421        INPUT:
     422
     423        - ``e`` : An instance of ``MIPVariable`` or one of
     424                  its elements
     425
     426        NOTE:
     427
     428        We recommend you to define the types of your variables after
     429        your problem has been completely defined ( see example )
     430
     431        EXAMPLE:
     432
     433          sage: p=MIP()
     434          sage: x=p.newvar()
     435          sage: #
     436          sage: # The following instruction does absolutely nothing
     437          sage: # as none of the variables of x have been used yet
     438          sage: p.setinteger(x)
     439          sage: p.setobj(x[0]+x[1])
     440          sage: p.addconstraint(-3*x[0]+2*x[1],max=2)
     441          sage: #
     442          sage: # This instructions sets x[0] and x[1]
     443          sage: # as integer variables
     444          sage: p.setinteger(x)
     445          sage: p.addconstraint(x[3]+x[2],max=2)
     446          sage: #
     447          sage: # x[3] is not set as integer
     448          sage: # as no setinteger(x) has been called
     449          sage: # after its first definition
     450          sage: #
     451          sage: # Now it is done
     452          sage: p.setinteger(x[3])
     453        """
     454        if isinstance(e,MIPVariable):
     455            if e.depth()==1:
     456                for v in e.values():
     457                    self.types[v]=self.__INTEGER               
     458            else:
     459                for v in e.keys():
     460                    self.setbinary(e[v])
     461        elif self.variables.has_key(e):       
     462            self.types[e]=self.__INTEGER
     463        else:
     464            raise Exception("Wrong kind of variable..")
     465
     466    def isinteger(self,e):
     467        r"""
     468        Tests whether the variable is integer.
     469
     470        ( Variables are real by default )
     471
     472        INPUT:
     473
     474        - ``e`` : a variable ( not a ``MIPVariable``, but one of its elements ! )
     475
     476        OUTPUT:
     477
     478        ``True`` if the variable is integer, ``False`` otherwise
     479
     480        EXAMPLE:
     481
     482            sage: p=MIP()
     483            sage: v=p.newvar()
     484            sage: p.setobj(v[1])
     485            sage: p.isinteger(v[1])
     486            False
     487            sage: p.setinteger(v[1])           
     488            sage: p.isinteger(v[1])
     489            True
     490        """
     491        # Returns an exception if the variable does not exist..
     492        # For exemple if the users tries to find out the type of
     493        # a MIPVariable or anything else
     494        self.variables[e]
     495
     496        if self.types.has_key(e) and self.types[e]==self.__INTEGER:
     497            return True
     498        return False
     499
     500    def setreal(self,e):
     501        r"""
     502        Sets a variable or a ``MIPVariable`` as real
     503
     504        INPUT:
     505
     506        - ``e`` : An instance of ``MIPVariable`` or one of
     507                  its elements
     508
     509        NOTE:
     510
     511        We recommend you to define the types of your variables after
     512        your problem has been completely defined ( see example )
     513
     514        EXAMPLE:
     515
     516          sage: p=MIP()
     517          sage: x=p.newvar()
     518          sage: #
     519          sage: # The following instruction does absolutely nothing
     520          sage: # as none of the variables of x have been used yet
     521          sage: p.setreal(x)
     522          sage: p.setobj(x[0]+x[1])
     523          sage: p.addconstraint(-3*x[0]+2*x[1],max=2)
     524          sage: #
     525          sage: # This instructions sets x[0] and x[1]
     526          sage: # as real variables
     527          sage: p.setreal(x)
     528          sage: p.addconstraint(x[3]+x[2],max=2)
     529          sage: #
     530          sage: # x[3] is not set as real
     531          sage: # as no setreal(x) has been called
     532          sage: # after its first definition
     533          sage: # ( even if actually, it is as variables
     534          sage: # are real by default ... )
     535          sage: #
     536          sage: # Now it is done
     537          sage: p.setreal(x[3])
     538        """
     539        if isinstance(e,MIPVariable):
     540            if e.depth()==1:
     541                for v in e.values():
     542                    self.types[v]=self.__REAL               
     543            else:
     544                for v in e.keys():
     545                    self.setbinary(e[v])
     546        elif self.variables.has_key(e):       
     547            self.types[e]=self.__REAL
     548        else:
     549            raise Exception("Wrong kind of variable..")
     550
     551
     552    def isreal(self,e):
     553        r"""
     554        Tests whether the variable is real.
     555
     556        ( Variables are real by default )
     557
     558        INPUT:
     559
     560        - ``e`` : a variable ( not a ``MIPVariable``, but one of its elements ! )
     561
     562        OUTPUT:
     563
     564        ``True`` if the variable is real, ``False`` otherwise
     565
     566        EXAMPLE:
     567
     568            sage: p=MIP()
     569            sage: v=p.newvar()
     570            sage: p.setobj(v[1])
     571            sage: p.isreal(v[1])
     572            True
     573            sage: p.setbinary(v[1])
     574            sage: p.isreal(v[1])
     575            False
     576            sage: p.setreal(v[1])           
     577            sage: p.isreal(v[1])
     578            True
     579        """
     580       
     581        # Returns an exception if the variable does not exist..
     582        # For exemple if the users tries to find out the type of
     583        # a MIPVariable or anything else
     584        self.variables[e]
     585
     586        if (not self.types.has_key(e)) or self.types[e]==self.__REAL:
     587            return True
     588        return False
     589
     590
     591    def solve(self,solver=None,log=False,objective_only=False):
     592        r"""
     593        Solves the MIP.
     594
     595        INPUT :
     596        - ``solver'' :
     597                 3 solvers should be available through this class :
     598                     - GLPK ( ``solver="GLPK"`` )
     599                     http://www.gnu.org/software/glpk/
     600                     
     601                     - COIN Branch and Cut  ( ``solver="Coin"`` )
     602                     COIN-OR http://www.coin-or.org/
     603                     If the spkg is installed
     604                     
     605                     - CPLEX  ( ``solver="CPLEX"`` )
     606                     http://www.ilog.com/products/cplex/
     607                     Not Implemented Yet
     608                     
     609                     ``solver`` should then be equal to one of ``"GLPK"``,
     610                     ``"Coin"``, ``"CPLEX"``, or ``None``.
     611                     If ``solver=None`` ( default ), the default solver is used
     612                     ( Coin if available, GLPK otherwise )
     613                     
     614        - ``log`` : This boolean variable indicates whether progress should be printed
     615                    during the computations.
     616       
     617        - ``objective_only`` : Boolean variable
     618                          * When set to ``True``, only the objective function is returned
     619                          * When set to ``False`` (default), the optimal
     620                            numerical values are stored ( takes computational
     621                            time )
     622
     623        OUTPUT :
     624       
     625        The optimal value taken by the objective function
     626       
     627        EXAMPLE :
     628       
     629        This code solves the following Linear Program :
     630
     631           Maximize:
     632              x + 5 * y
     633           Constraints:
     634              x + 0.2 y       <= 4
     635              1.5 * x + 3 * y   <=4
     636           Variables:
     637              x is Real ( min = 0, max = None )
     638              y is Real ( min = 0, max = None )
     639
     640
     641           sage: p=MIP(sense=1)
     642           sage: x=p.newvar()
     643           sage: p.setobj(x[1]+5*x[2])
     644           sage: p.addconstraint(x[1]+0.2*x[2],max=4)
     645           sage: p.addconstraint(1.5*x[1]+3*x[2],max=4)
     646           sage: p.solve()           # optional - requires Glpk or COIN-OR/CBC
     647           6.6666666666666661
     648           sage: p.get_values(x)     # optional - requires Glpk or COIN-OR/CBC
     649           {1: 0.0, 2: 1.3333333333333333}
     650
     651           sage: ### Computation of a maximum stable set in Petersen's graph ###
     652           sage: g=graphs.PetersenGraph()
     653           sage: p=MIP(sense=1)
     654           sage: b=p.newvar()
     655           sage: p.setobj(sum([b[v] for v in g]))
     656           sage: for (u,v) in g.edges(labels=None):
     657           ...       p.addconstraint(b[u]+b[v],max=1)
     658           sage: p.setbinary(b)
     659           sage: p.solve(objective_only=True)     # optional - requires Glpk or COIN-OR/CBC
     660           4.0
     661
     662
     663        """       
     664
     665        if self.objective==None:
     666            raise Exception("No objective function has been defined !")
     667
     668        if solver==None:
     669            solver=self.default_solver
     670
     671        if solver==None:
     672             raise Exception("There does not seem to be any solver installed...\n Please visit http://www.sagemath.org/doc/tutorial/tour_LP.html for more informations")
     673        elif solver=="Coin":
     674             try:
     675                  from sage.numerical.mipCoin import solveCoin
     676             except:
     677                raise NotImplementedError("Coin/CBC is not installed and cannot be used to solve this MIP\n To install it, you can type in Sage : sage: install_package('cbc')")               
     678             return solveCoin(self,log=log,objective_only=objective_only)
     679
     680        elif solver=="GLPK":
     681             try:
     682                  from sage.numerical.mipGlpk import solveGlpk
     683             except:
     684                raise NotImplementedError("GLPK is not installed and cannot be used to solve this MIP\n To install it, you can type in Sage : sage: install_package('glpk')")               
     685             return solveGlpk(self,log=log,objective_only=objective_only)
     686        elif solver=="CPLEX":
     687             raise NotImplementedError("The support for CPLEX is not written yet... We're seriously thinking about it, though ;-)")
     688        else:
     689            raise NotImplementedError("solver should be set to 'GLPK', 'Coin', 'CPLEX' or None (in which case the default one is used).")
     690
     691
     692    def _NormalForm(self,exp):
     693        r"""
     694        Returns a dictionary built from the linear function
     695
     696        INPUT:
     697
     698        - ``exp`` : The expression representing a linear function
     699
     700        OUTPUT:
     701
     702        A dictionary whose keys are the id of the variables, and whose
     703        values are their coefficients.
     704        The value corresponding to key `-1` is the constant coefficient
     705
     706        EXAMPLE:
     707
     708            sage: p=MIP()
     709            sage: v=p.newvar()
     710            sage: p._NormalForm(v[0]+v[1])
     711            {1: 1.0, 2: 1.0, -1: 0.0}
     712        """
     713        d=dict(zip([self.variables[v] for v in exp.variables()],exp.coefficients()))
     714        d[-1]=exp.constant_coefficient()
     715        return d
     716
     717    def _addElementToRing(self):
     718        r"""
     719        Creates a new variable from the main ``InfinitePolynomialRing``
     720
     721        OUTPUT:
     722
     723        - The newly created variable
     724
     725        EXAMPLE:
     726
     727            sage: p=MIP()
     728            sage: v=p.newvar()
     729            sage: p.count[0]
     730            0
     731            sage: p._addElementToRing()
     732            x1
     733            sage: p.count[0]
     734            1
     735        """
     736        self.count[0]+=1
     737        v=self.x[self.count[0]]
     738        self.variables[v]=self.count[0]
     739        self.types[v]=self.__REAL
     740        self.min[v]=0.0
     741        return v
     742
     743    def setmin(self,v,min):
     744        r"""
     745        Sets the minimum value of a variable
     746
     747        INPUT
     748
     749        - ``v`` : a variable ( not a ``MIPVariable``, but one of its elements ! )
     750        - ``min`` : the minimum value the variable can take
     751                    when ``min=None``, the variable has no lower bound
     752
     753        EXAMPLE::
     754
     755            sage: p=MIP()
     756            sage: v=p.newvar()
     757            sage: p.setobj(v[1])
     758            sage: p.getmin(v[1])
     759            0.0
     760            sage: p.setmin(v[1],6)
     761            sage: p.getmin(v[1])
     762            6.0
     763        """
     764        self.min[v]=min
     765
     766    def setmax(self,v,max):
     767        r"""
     768        Sets the maximum value of a variable
     769
     770        INPUT
     771
     772        - ``v`` : a variable ( not a ``MIPVariable``, but one of its elements ! )
     773        - ``max`` : the maximum value the variable can take
     774                    when ``max=None``, the variable has no upper bound
     775
     776        EXAMPLE::
     777
     778            sage: p=MIP()
     779            sage: v=p.newvar()
     780            sage: p.setobj(v[1])
     781            sage: p.getmax(v[1])
     782            sage: p.setmax(v[1],6)
     783            sage: p.getmax(v[1])
     784            6.0
     785        """
     786        self.max[v]=max
     787
     788
     789    def getmin(self,v):
     790        r"""
     791        Returns the minimum value of a variable
     792
     793        INPUT
     794
     795        - ``v`` a variable ( not a ``MIPVariable``, but one of its elements ! )
     796
     797        OUTPUT
     798
     799        Minimum value of the variable, or ``None`` is
     800        the variable has no lower bound
     801
     802        EXAMPLE::
     803
     804            sage: p=MIP()
     805            sage: v=p.newvar()
     806            sage: p.setobj(v[1])
     807            sage: p.getmin(v[1])
     808            0.0
     809            sage: p.setmin(v[1],6)
     810            sage: p.getmin(v[1])
     811            6.0
     812        """
     813        return float(self.min[v]) if self.min.has_key(v) else 0.0
     814    def getmax(self,v):
     815        r"""
     816        Returns the maximum value of a variable
     817
     818        INPUT
     819
     820        - ``v`` a variable ( not a ``MIPVariable``, but one of its elements ! )
     821
     822        OUTPUT
     823
     824        Maximum value of the variable, or ``None`` is
     825        the variable has no upper bound
     826
     827        EXAMPLE::
     828
     829            sage: p=MIP()
     830            sage: v=p.newvar()
     831            sage: p.setobj(v[1])
     832            sage: p.getmax(v[1])
     833            sage: p.setmax(v[1],6)
     834            sage: p.getmax(v[1])
     835            6.0
     836        """
     837        return float(self.max[v]) if self.max.has_key(v) else None
     838
     839class MIPSolverException(Exception):
     840    r"""
     841    Exception raised when the solver fails
     842    """
     843    def __init__(self, value):
     844        r"""
     845        Constructor for ``MIPSolverException``
     846
     847        ``MIPSolverException`` is the exception raised when the solver fails
     848
     849        EXAMPLE:
     850
     851            sage: MIPSolverException("Error")
     852            MIPSolverException()
     853                   
     854        """
     855        self.value = value
     856    def __str__(self):
     857        r"""
     858        Returns the value of the instance of ``MIPSolverException` `
     859
     860        EXAMPLE:
     861
     862            sage: e=MIPSolverException("Error")
     863            sage: print e
     864            'Error'
     865        """
     866        return repr(self.value)
     867
     868class MIPVariable:
     869     r"""
     870     ``MIPVariable`` is a variable used by the class ``MIP``
     871     """
     872     def __init__(self,x,f,dim=1):
     873         r"""
     874         Constructor for ``MIPVariable``
     875
     876         INPUT:
     877
     878         - ``x`` is the generator element of an ``InfinitePolynomialRing``
     879         - ``f`` is a function returning a new variable from the parent class
     880         - ``dim`` is the integer defining the definition of the variable
     881
     882         For more informations, see method ``MIP.newvar``
     883
     884         EXAMPLE:
     885
     886            sage: p=MIP()
     887            sage: v=p.newvar()
     888           
     889           
     890         """
     891         self.dim=dim
     892         self.dict={}
     893         self.x=x
     894         self.f=f
     895
     896     def __getitem__(self,i):
     897          r"""
     898          Returns the symbolic variable corresponding to the key
     899
     900          Returns the element asked, otherwise creates it.
     901          ( When depth>1, recursively creates the variables )
     902
     903         EXAMPLE:
     904
     905             sage: p=MIP()
     906             sage: v=p.newvar()
     907             sage: p.setobj(v[0]+v[1])
     908             sage: v[0]
     909             x1
     910          """
     911          if self.dict.has_key(i):
     912               return self.dict[i]
     913          elif self.dim==1:
     914              self.dict[i]=self.f()
     915              return self.dict[i]
     916          else:
     917               self.dict[i]=MIPVariable(dim=self.dim-1,x=self.x, f=self.f)
     918               return self.dict[i]
     919     def keys(self):
     920         r"""
     921         Returns the keys already defined in the dictionary
     922
     923         EXAMPLE:
     924
     925             sage: p=MIP()
     926             sage: v=p.newvar()
     927             sage: p.setobj(v[0]+v[1])
     928             sage: v.keys()
     929             [0, 1]
     930         """
     931         return self.dict.keys()
     932     def items(self):
     933         r"""
     934         Returns the pairs (keys,value) contained in the dictionary
     935
     936         EXAMPLE:
     937
     938             sage: p=MIP()
     939             sage: v=p.newvar()
     940             sage: p.setobj(v[0]+v[1])
     941             sage: v.items()
     942             [(0, x1), (1, x2)]
     943         """
     944         return self.dict.items()
     945     def depth(self):
     946         r"""
     947         Returns the current variable's depth
     948
     949         EXAMPLE:
     950
     951             sage: p=MIP()
     952             sage: v=p.newvar()
     953             sage: p.setobj(v[0]+v[1])
     954             sage: v.depth()
     955             1
     956         """
     957         return self.dim
     958     def values(self):
     959         r"""
     960         Returns the symbolic variables associated to the current dictionary
     961
     962         EXAMPLE:
     963
     964             sage: p=MIP()
     965             sage: v=p.newvar()
     966             sage: p.setobj(v[0]+v[1])
     967             sage: v.values()
     968             [x1, x2]
     969         """
     970         return self.dict.values()
     971
     972