Ticket #7270: trac_7270.patch

File trac_7270.patch, 34.2 KB (added by ncohen, 11 years ago)
  • sage/numerical/all.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1255776303 -7200
    # Node ID 494f8a8c14f24bedd964f1ecf19e7f0fa9595dc0
    # Parent  14516cf5b0ccefed648d0043a7c9beb7121a5598
    Last "core" modifications of numerical.mip.
    
    diff -r 14516cf5b0cc -r 494f8a8c14f2 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)
    4 from sage.numerical.mip import *
     4from sage.numerical.mip import MixedIntegerLinearProgram
  • sage/numerical/mip.pyx

    diff -r 14516cf5b0cc -r 494f8a8c14f2 sage/numerical/mip.pyx
    a b  
    6161        """
    6262        try:
    6363            from sage.numerical.mipCoin import solveCoin
    64             self.default_solver = "Coin"
     64            self._default_solver = "Coin"
    6565        except:
    6666            try:
    67                 from sage.numerical.mipGlpk import solveGlpk
    68                 self.default_solver = "GLPK"
     67                from sage.numerical.mipGlpk import solve_glpk
     68                self._default_solver = "GLPK"
    6969            except:
    70                 self.default_solver = None
     70                self._default_solver = None
    7171
    7272        from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing
    7373        from sage.rings.real_double import RealDoubleField as RR
    7474        P = InfinitePolynomialRing(RR(), names=('x',))
    75         (self.x,) = P._first_ngens(1)
     75        (self._x,) = P._first_ngens(1)
    7676
    77         # number of variables
    78         self.count = 0
    79         self.maximization = maximization
    80         self.objective = None
     77        # List of all the MIPVariables linked to this instance of
     78        # MixedIntegerLinearProgram
     79        self._mipvariables = []
    8180
    82         self.variables = {}
    83         self.constraints = []
     81        # Associates an index to the variables from self._x
     82        self._variables = {}
    8483
    85         #constains the min and max bounds on the variables
    86         self.min = {}
    87         self.max = {}
    88 
    89         # constains the variables types
    90         self.types = {}
    91 
    92         #constains the variables' values when
     84        # contains the variables' values when
    9385        # solve(objective_only=False) is called
    94         self.values = {}
     86        self._values = {}
    9587
    9688        # Several constants
    9789        self.__BINARY = 1
    9890        self.__REAL = -1
    9991        self.__INTEGER = 0
    10092
     93        # ######################################################
     94        # The informations of a Linear Program
     95        #
     96        # - name
     97        # - maximization
     98        # - objective
     99        #    --> name
     100        #    --> i
     101        #    --> values
     102        # - variables
     103        #   --> names
     104        #   --> type
     105        #   --> bounds
     106        #       --> min
     107        #       --> max
     108        # - constraints
     109        #   --> names
     110        #   --> matrix
     111        #       --> i
     112        #       --> j
     113        #       --> values
     114        #   --> bounds
     115        #       --> min
     116        #       --> max
     117        #
     118        # The Constraint matrix being almost always sparse, it is stored
     119        # as a list of positions (i,j) in the matrix with an associated value.
     120        #
     121        # This is how matrices are exchanged in GLPK's or Cbc's libraries
     122        # By storing the data this way, we do no have to convert them
     123        # ( too often ) and this process is a bit faster.
     124        #
     125        # ######################################################
     126       
     127
     128        self._name = None
     129        self._maximization = maximization
     130        self._objective_i = None
     131        self._objective_values = None
     132        self._objective_name = None
     133        self._variables_name = []
     134        self._variables_type = []
     135        self._variables_bounds_min = []
     136        self._variables_bounds_max = []
     137        self._constraints_name = []
     138        self._constraints_matrix_i = []
     139        self._constraints_matrix_j = []
     140        self._constraints_matrix_values = []
     141        self._constraints_bounds_max = []
     142        self._constraints_bounds_min = []       
     143
     144
    101145    def __repr__(self):
    102146         r"""
    103147         Returns a short description of the ``MixedIntegerLinearProgram``.
     
    110154             sage: print p
    111155             Mixed Integer Program ( maximization, 2 variables, 1 constraints )
    112156         """
    113          return "Mixed Integer Program ( " + \
    114              ( "maximization" if self.maximization else "minimization" ) + \
    115              ", " + str(len(self.variables)) + " variables, " +  \
    116              str(len(self.constraints)) + " constraints )"
     157         return "Mixed Integer Program "+("\""+self._name+"\"" if self._name!=None else "")+" ( " + \
     158             ( "maximization" if self._maximization else "minimization" ) + \
     159             ", " + str(len(self._variables)) + " variables, " +  \
     160             str(len(self._constraints_bounds_min)) + " constraints )"
     161   
     162    def __eq__(self,p):
     163        r"""
     164        Test of equality.
    117165
    118     def new_variable(self, vtype=-1, dim=1):
     166        INPUT:
     167
     168        - ``p`` -- an instance of ``MixedIntegerLinearProgram`` to be tested
     169          against ``self``.
     170
     171        EXAMPLE::
     172
     173            sage: p = MixedIntegerLinearProgram()
     174            sage: v = p.new_variable()
     175            sage: p.add_constraint(v[1] + v[2], max=2)
     176            sage: p == loads(dumps(p))
     177            True
     178            sage: p2 = loads(dumps(p))
     179            sage: p2.add_constraint(2*v[1] + 3*v[2], max=1)
     180            sage: p == p2
     181            False
     182        """
     183
     184        return (
     185            self._name == p._name and
     186            self._maximization == p._maximization and
     187            self._objective_i == p._objective_i and
     188            self._objective_values == p._objective_values and
     189            self._objective_name == p._objective_name and
     190            self._variables_name == p._variables_name and
     191            self._variables_type == p._variables_type and
     192            self._variables_bounds_min == p._variables_bounds_min and
     193            self._variables_bounds_max == p._variables_bounds_max and
     194            self._constraints_name == p._constraints_name and
     195            self._constraints_matrix_i == p._constraints_matrix_i and
     196            self._constraints_matrix_j == p._constraints_matrix_j and
     197            self._constraints_matrix_values == p._constraints_matrix_values and
     198            self._constraints_bounds_max == p._constraints_bounds_max
     199            )
     200
     201    def set_problem_name(self,name):
     202        r"""
     203        Sets the name of the ``MixedIntegerLinearProgram``.
     204
     205        INPUT:
     206
     207        - ``name`` -- A string representing the name of the
     208          ``MixedIntegerLinearProgram``.
     209         
     210        EXAMPLE::
     211
     212            sage: p=MixedIntegerLinearProgram()
     213            sage: p.set_problem_name("Test program")
     214            sage: p
     215            Mixed Integer Program "Test program" ( maximization, 0 variables, 0 constraints )
     216        """
     217
     218        self._name=name       
     219
     220    def set_objective_name(self,name):
     221        r"""
     222        Sets the name of the objective function.
     223
     224        INPUT:
     225
     226        - ``name`` -- A string representing the name of the
     227          objective function.
     228         
     229        EXAMPLE::
     230
     231            sage: p=MixedIntegerLinearProgram()
     232            sage: p.set_objective_name("Objective function")
     233        """
     234
     235        self._objective_name=name       
     236
     237    def _update_variables_name(self):
     238        r"""
     239        Updates the names of the variables.
     240
     241        Only called before writing the Problem to a MPS or LP file.
     242       
     243        EXAMPLE::
     244
     245            sage: p=MixedIntegerLinearProgram()
     246            sage: v=p.new_variable(name="Test")
     247            sage: v[5]+v[99]
     248            x1 + x0
     249            sage: p._update_variables_name()
     250        """
     251
     252        self._variables_name=['']*len(self._variables)
     253        for v in self._mipvariables:
     254            v._update_variables_name()
     255
     256
     257    def new_variable(self, vtype=-1, dim=1,name=None):
    119258        r"""
    120259        Returns an instance of ``MIPVariable`` associated
    121260        to the current instance of ``MixedIntegerLinearProgram``.
     
    138277          ``x[key1][key2]``.
    139278        - ``vtype`` (integer) -- Defines the type of the variables
    140279          (default is ``REAL``).
     280        - ``name`` (string) -- A name for the variable
     281          ( default is V+number )
    141282
    142283        EXAMPLE::
    143284
     
    147288            sage: y = p.new_variable(dim=2)
    148289            sage: p.add_constraint(x[2] + y[3][5], max=2)
    149290        """
    150         return MIPVariable(self, vtype, dim=dim)
     291        if name==None:
     292            name="V"+str(len(self._mipvariables))
     293        v=MIPVariable(self, vtype, dim=dim,name=name)
     294        self._mipvariables.append(v)
     295        return v
    151296
    152     def export(self, format="text"):
     297    def constraints(self):
    153298        r"""
    154         Exports the ``MixedIntegerLinearProgram`` to a string in
    155         different formats.
     299        Returns the list of constraints.
    156300
    157         INPUT:
     301        This functions returns the constraints as a list
     302        of tuples ``(linear_function,min_bound,max_bound)``, representing
     303        the constraint :
     304       
     305        `\mbox{min_bound} \leq \mbox{linear_function} \leq \mbox{max_bound}`
     306       
     307        Variables ``min_bound`` (respectively ``max_bound``) is set
     308        to ``None`` when the function has no lower ( respectively upper )
     309        bound.
     310       
     311        EXAMPLE::
     312            sage: p = MixedIntegerLinearProgram(maximization=True)
     313            sage: x = p.new_variable()
     314            sage: p.set_objective(x[1] + 5*x[2])
     315            sage: p.add_constraint(x[1] + 0.2*x[2], max=4)
     316            sage: p.add_constraint(1.5*x[1]+3*x[2], max=4)
     317            sage: p.constraints()
     318            [(3.0*x1 + 1.5*x0, None, 4.0), (0.2*x1 + x0, None, 4.0)]
     319        """
     320       
     321        constraints=[0]*len(self._constraints_bounds_min)
     322        for (i,j,value) in zip(self._constraints_matrix_i,self._constraints_matrix_j,self._constraints_matrix_values):
     323            constraints[i-1]+=value*self._x[j]
     324        return zip(constraints,self._constraints_bounds_min,self._constraints_bounds_max)
    158325
    159         - ``format``
    160326
    161           - ``"text"`` -- (default) human-readable format
     327    def show(self):
     328        r"""
     329        Displays the ``MixedIntegerLinearProgram`` in a human-readable
     330        way.
    162331
    163332        EXAMPLES::
    164333
     
    166335            sage: x = p.new_variable()
    167336            sage: p.set_objective(x[1] + x[2])
    168337            sage: p.add_constraint(-3*x[1] + 2*x[2], max=2)
    169             sage: print p.export(format="text")
     338            sage: p.show()
    170339            Maximization:
    171               x2 + x1
     340              +1.0 x_0 +1.0 x_1
    172341            Constraints:
    173               2.0*x2 - 3.0*x1
     342              2.0*x1 - 3.0*x0 <= 2.0
    174343            Variables:
    175               x2 is a real variable (min=0.0, max=+oo)
    176344              x1 is a real variable (min=0.0, max=+oo)
     345              x0 is a real variable (min=0.0, max=+oo)
    177346        """
    178         if format == "text":
    179             value = ( "Maximization:\n"
    180                       if self.maximization
    181                       else "Minimization:\n" )
    182             value += "  " + ( str(self.objective)
    183                               if self.objective != None
    184                               else "Undefined" )
    185             value += "\nConstraints:"
    186             for c in self.constraints:
    187                 value += "\n  " + str(c["function"])
    188             value += "\nVariables:"
    189             for v in self.variables.keys():
    190                 value += "\n  " + str(v) + " is"
    191                 if self.is_integer(v):
    192                     value += " an integer variable"
    193                 elif self.is_binary(v):
    194                     value += " an boolean variable"
    195                 else:
    196                     value += " a real variable"
    197                 value += " (min=" + \
    198                     ( str(self.get_min(v))
    199                       if self.get_min(v) != None
    200                       else "-oo" ) + \
    201                     ", max=" + \
    202                     ( str(self.get_max(v))
    203                       if self.get_max(v) != None
    204                       else "+oo" ) + \
    205                     ")"
    206             return value
     347        value = ( "Maximization:\n"
     348                  if self._maximization
     349                  else "Minimization:\n" )
     350        value+="  "
     351        if self._objective_i==None:
     352            value+="Undefined"
    207353        else:
    208             raise ValueError("Only human-readable format is currently defined.")
     354            for (i,c) in zip(self._objective_i, self._objective_values):
     355                value+=("+"+str(c) if c>0 else str(c))+" x_"+str(i)+" "
    209356
     357        value += "\nConstraints:"
     358        for (c,min,max) in self.constraints():
     359            value += "\n  " + (str(min)+" <= " if min!=None else "")+str(c)+(" <= "+str(max) if max!=None else "")
     360        value += "\nVariables:"
     361        for v in self._variables.keys():
     362            value += "\n  " + str(v) + " is"
     363            if self.is_integer(v):
     364                value += " an integer variable"
     365            elif self.is_binary(v):
     366                value += " an boolean variable"
     367            else:
     368                value += " a real variable"
     369            value += " (min=" + \
     370                ( str(self.get_min(v))
     371                  if self.get_min(v) != None
     372                  else "-oo" ) + \
     373                ", max=" + \
     374                ( str(self.get_max(v))
     375                  if self.get_max(v) != None
     376                  else "+oo" ) + \
     377                ")"
     378        print value
     379
     380    def write_mps(self,filename,modern=True):
     381        r"""
     382        Write the linear program as a MPS file.
     383
     384        This function export the problem as a MPS file.
     385
     386        INPUT:
     387
     388        - ``filename`` -- The file in which you want the problem
     389          to be written.
     390
     391        - ``modern`` -- Lets you choose between Fixed MPS and Free MPS
     392
     393            - ``True`` -- Outputs the problem in Free MPS
     394            - ``False`` -- Outputs the problem in Fixed MPS
     395
     396        EXAMPLE::
     397
     398            sage: p = MixedIntegerLinearProgram()
     399            sage: x = p.new_variable()
     400            sage: p.set_objective(x[1] + x[2])
     401            sage: p.add_constraint(-3*x[1] + 2*x[2], max=2,name="OneConstraint")
     402            sage: p.write_mps(SAGE_TMP+"/lp_problem.mps") # optional - requires GLPK
     403
     404        For information about the MPS file format :
     405        http://en.wikipedia.org/wiki/MPS_%28format%29
     406        """
     407       
     408        try:
     409            from sage.numerical.mipGlpk import write_mps
     410        except:
     411            raise NotImplementedError("You need GLPK installed to use this function. To install it, you can type in Sage: install_package('glpk')")
     412
     413        self._update_variables_name()
     414        write_mps(self, filename, modern)
     415       
     416
     417    def write_lp(self,filename):
     418        r"""
     419        Write the linear program as a LP file.
     420
     421        This function export the problem as a LP file.
     422
     423        INPUT:
     424
     425        - ``filename`` -- The file in which you want the problem
     426          to be written.
     427
     428        EXAMPLE::
     429       
     430            sage: p = MixedIntegerLinearProgram()
     431            sage: x = p.new_variable()
     432            sage: p.set_objective(x[1] + x[2])
     433            sage: p.add_constraint(-3*x[1] + 2*x[2], max=2)
     434            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp") # optional - requires GLPK
     435
     436        For more information about the LP file format :
     437        http://lpsolve.sourceforge.net/5.5/lp-format.htm
     438        """
     439        try:
     440            from sage.numerical.mipGlpk import write_lp
     441        except:
     442            raise NotImplementedError("You need GLPK installed to use this function. To install it, you can type in Sage: install_package('glpk')")
     443
     444        self._update_variables_name()
     445        write_lp(self, filename)
     446
     447       
    210448    def get_values(self, *lists):
    211449        r"""
    212450        Return values found by the previous call to ``solve()``.
     
    260498                if l.depth() == 1:
    261499                    c = {}
    262500                    for (k,v) in l.items():
    263                         c[k] = self.values[v] if self.values.has_key(v) else None
     501                        c[k] = self._values[v] if self._values.has_key(v) else None
    264502                    val.append(c)
    265503                else:
    266504                    c = {}
     
    274512                    c = []
    275513                    [c.append(self.get_values(ll)) for ll in l]
    276514                    val.append(c)
    277             elif self.variables.has_key(l):
    278                 val.append(self.values[l])
     515            elif self._variables.has_key(l):
     516                val.append(self._values[l])
    279517        if len(lists) == 1:
    280518            return val[0]
    281519        else:
    282520            return val
    283521
    284     def show(self):
    285         r"""
    286         Prints the ``MixedIntegerLinearProgram`` in a human-readable format.
    287 
    288         EXAMPLE::
    289 
    290             sage: p = MixedIntegerLinearProgram()
    291             sage: x = p.new_variable()
    292             sage: p.set_objective(x[1] + x[2])
    293             sage: p.add_constraint(-3*x[1] + 2*x[2], max=2)
    294             sage: p.show()
    295             Maximization:
    296               x2 + x1
    297             Constraints:
    298               2.0*x2 - 3.0*x1
    299             Variables:
    300               x2 is a real variable (min=0.0, max=+oo)
    301               x1 is a real variable (min=0.0, max=+oo)
    302         """
    303         print self.export(format="text")
    304 
    305522    def set_objective(self,obj):
    306523        r"""
    307524        Sets the objective of the ``MixedIntegerLinearProgram``.
    308525
    309526        INPUT:
    310527
    311         - ``obj`` -- A linear function to be optimized.
     528        - ``obj`` -- A linear function to be optimized.
     529          ( can also be set to ``None`` or ``0`` when just
     530          looking for a feasible solution )
    312531
    313532        EXAMPLE:
    314533
     
    331550            sage: p.add_constraint(x[1] + 0.2*x[2], max=4)
    332551            sage: p.add_constraint(1.5*x[1]+3*x[2], max=4)
    333552            sage: p.solve()     # optional - requires Glpk or COIN-OR/CBC
    334             6.6666666666666661
     553            6.6666666666666661           
     554            sage: p.set_objective(None)
     555            sage: p.solve()
     556            0.0
    335557        """
    336         self.objective=obj
    337558
    338     def add_constraint(self, linear_function, max=None, min=None):
     559
     560        self._objective_i = []
     561        self._objective_values = []
     562
     563
     564        # If the objective is None, or a constant, we want to remember
     565        # that the objective function has been defined ( the user did not
     566        # forget it ). In some LP problems, you just want a feasible solution
     567        # and do not care about any function being optimal.
     568        try:
     569            obj.constant_coefficient()
     570        except:
     571            return None
     572
     573        for (id, coeff) in [(id, coeff) for (id, coeff) in self._NormalForm(obj).items() if id != -1]:
     574            self._objective_i.append(id)
     575            self._objective_values.append(coeff)
     576
     577    def add_constraint(self, linear_function, max=None, min=None, name=None):
    339578        r"""
    340579        Adds a constraint to the ``MixedIntegerLinearProgram``.
    341580
     
    345584        - ``max`` -- An upper bound on the constraint (set to ``None``
    346585          by default).
    347586        - ``min`` -- A lower bound on the constraint.
     587        - ``name`` -- A name for the constraint.
    348588
    349589        EXAMPLE:
    350590
     
    368608            sage: p.add_constraint(1.5*x[1] + 3*x[2], max=4)
    369609            sage: p.solve()     # optional - requires Glpk or COIN-OR/CBC
    370610            6.6666666666666661
     611
     612        TESTS::
     613
     614            sage: p=MixedIntegerLinearProgram()
     615            sage: p.add_constraint(sum([]),min=2)
    371616        """
    372         max = float(max) if max != None else None
    373         min = float(min) if min != None else None
    374         self.constraints.append({
    375                 "function": linear_function,
    376                 "min": min,
    377                 "max": max,
    378                 "card": len(linear_function.variables()) })
     617
     618
     619        # In case a null constraint is given ( see tests )
     620        try:
     621            linear_function.constant_coefficient()
     622        except:
     623            return None
     624
     625        if linear_function==0:
     626            return None
     627
     628        self._constraints_name.append(name)
     629
     630        # We do not want to ignore the constant coefficient
     631        max = float(max-linear_function.constant_coefficient()) if max != None else None
     632        min = float(min-linear_function.constant_coefficient()) if min != None else None
     633
     634        linear_function-=linear_function.constant_coefficient()
     635        c=len(self._constraints_bounds_min)
     636
     637        self._constraints_bounds_max.append(max)
     638        self._constraints_bounds_min.append(min)
     639
     640
     641        for (id,value) in zip([self._variables[var] for var in linear_function.variables()], linear_function.coefficients()):
     642            self._constraints_matrix_i.append(c)
     643            self._constraints_matrix_j.append(id)
     644            self._constraints_matrix_values.append(value)
    379645
    380646    def set_binary(self, e):
    381647        r"""
     
    404670            e.vtype = self.__BINARY
    405671            if e.depth() == 1:
    406672                for v in e.values():
    407                     self.types[v] = self.__BINARY
     673                    self._variables_type[self._variables[v]] = self.__BINARY
    408674            else:
    409675                for v in e.keys():
    410676                    self.set_binary(e[v])
    411         elif self.variables.has_key(e):
    412             self.types[e] = self.__BINARY
     677        elif self._variables.has_key(e):
     678            self._variables_type[self._variables[e]] = self.__BINARY
    413679        else:
    414680            raise ValueError("e must be an instance of MIPVariable or one of its elements.")
    415681
     
    437703            sage: p.is_binary(v[1])
    438704            True
    439705        """
    440         # Returns an exception if the variable does not exist.
    441         # For example if the user tries to find out the type of
    442         # a MIPVariable or anything else.
    443         self.variables[e]
    444         if self.types.has_key(e) and self.types[e] == self.__BINARY:
     706
     707        if self._variables_type[self._variables[e]] == self.__BINARY:
    445708            return True
    446709        return False
    447710
     
    472735            e.vtype = self.__INTEGER
    473736            if e.depth() == 1:
    474737                for v in e.values():
    475                     self.types[v] = self.__INTEGER
     738                    self._variables_type[self._variables[v]] = self.__INTEGER
    476739            else:
    477740                for v in e.keys():
    478741                    self.set_integer(e[v])
    479         elif self.variables.has_key(e):
    480             self.types[e] = self.__INTEGER
     742        elif self._variables.has_key(e):
     743            self._variables_type[self._variables[e]] = self.__INTEGER
    481744        else:
    482745            raise ValueError("e must be an instance of MIPVariable or one of its elements.")
    483746
     
    505768            sage: p.is_integer(v[1])
    506769            True
    507770        """
    508         # Returns an exception if the variable does not exist.
    509         # For example if the user tries to find out the type of
    510         # a MIPVariable or anything else.
    511         self.variables[e]
    512         if self.types.has_key(e) and self.types[e] == self.__INTEGER:
     771
     772        if self._variables_type[self._variables[e]] == self.__INTEGER:
    513773            return True
    514774        return False
    515775
     
    540800            e.vtype = self.__REAL
    541801            if e.depth() == 1:
    542802                for v in e.values():
    543                     self.types[v] = self.__REAL
     803                    self._variables_type[self._variables[v]] = self.__REAL
    544804            else:
    545805                for v in e.keys():
    546806                    self.set_real(e[v])
    547         elif self.variables.has_key(e):
    548             self.types[e] = self.__REAL
     807        elif self._variables.has_key(e):
     808            self._variables_type[self._variables[e]] = self.__REAL
    549809        else:
    550810            raise ValueError("e must be an instance of MIPVariable or one of its elements.")
    551811
     
    575835            sage: p.is_real(v[1])
    576836            True
    577837        """
    578         # Returns an exception if the variable does not exist.
    579         # For example if the user tries to find out the type of
    580         # a MIPVariable or anything else.
    581         self.variables[e]
    582         if (not self.types.has_key(e)) or self.types[e] == self.__REAL:
     838
     839        if self._variables_type[self._variables[e]] == self.__REAL:
    583840            return True
    584841        return False
    585842
     
    641898            sage: p.solve()           # optional - requires Glpk or COIN-OR/CBC
    642899            6.6666666666666661
    643900            sage: p.get_values(x)     # optional random - requires Glpk or COIN-OR/CBC
    644             {1: 0.0, 2: 1.3333333333333333}
     901            {0: 0.0, 1: 1.3333333333333333}
    645902
    646903            sage: ### Computation of a maximum stable set in Petersen's graph
    647904            sage: g = graphs.PetersenGraph()
     
    654911            sage: p.solve(objective_only=True)     # optional - requires Glpk or COIN-OR/CBC
    655912            4.0
    656913        """
    657         if self.objective == None:
     914        if self._objective_i == None:
    658915            raise ValueError("No objective function has been defined.")
    659916
    660917        if solver == None:
    661             solver = self.default_solver
     918            solver = self._default_solver
    662919
    663920        if solver == None:
    664921            raise ValueError("There does not seem to be any solver installed. Please visit http://www.sagemath.org/doc/tutorial/tour_LP.html for more informations.")
     
    670927            return solveCoin(self, log=log, objective_only=objective_only)
    671928        elif solver == "GLPK":
    672929            try:
    673                 from sage.numerical.mipGlpk import solveGlpk
     930                from sage.numerical.mipGlpk import solve_glpk
    674931            except:
    675932                raise NotImplementedError("GLPK is not installed and cannot be used to solve this MixedIntegerLinearProgram. To install it, you can type in Sage: install_package('glpk')")
    676             return solveGlpk(self, log=log, objective_only=objective_only)
     933            return solve_glpk(self, log=log, objective_only=objective_only)
    677934        elif solver == "CPLEX":
    678935            raise NotImplementedError("The support for CPLEX is not implemented yet.")
    679936        else:
     
    698955            sage: p = MixedIntegerLinearProgram()
    699956            sage: v = p.new_variable()
    700957            sage: p._NormalForm(v[0] + v[1])
    701             {1: 1.0, 2: 1.0, -1: 0.0}
     958            {0: 1.0, 1: 1.0, -1: 0.0}
    702959        """
    703         d = dict( zip([self.variables[v] for v in exp.variables()],
     960        d = dict( zip([self._variables[v] for v in exp.variables()],
    704961                      exp.coefficients()) )
    705962        d[-1] = exp.constant_coefficient()
    706963        return d
     
    722979
    723980            sage: p = MixedIntegerLinearProgram()
    724981            sage: v = p.new_variable()
    725             sage: p.count
     982            sage: len(p._variables_type)
    726983            0
    727984            sage: p._add_element_to_ring(p.__REAL)
    728             x1
    729             sage: p.count
     985            x0
     986            sage: len(p._variables_type)
    730987            1
    731988        """
    732         self.count += 1
    733         v = self.x[self.count]
    734         self.variables[v] = self.count
    735         self.types[v] = vtype
    736         self.min[v] = 0.0
     989
     990        v = self._x[len(self._variables_type)]
     991        self._variables[v] = len(self._variables_type)
     992        self._variables_type.append(vtype)
     993        self._variables_bounds_min.append(0)
     994        self._variables_bounds_max.append(None)
    737995        return v
    738996
    739997    def set_min(self, v, min):
     
    7581016            sage: p.get_min(v[1])
    7591017            6.0
    7601018        """
    761         self.min[v] = min
     1019        self._variables_bounds_min[self._variables[v]] = min
    7621020
    7631021    def set_max(self, v, max):
    7641022        r"""
     
    7811039            sage: p.get_max(v[1])
    7821040            6.0
    7831041        """
    784         self.max[v] = max
     1042
     1043        self._variables_bounds_max[self._variables[v]] = max
    7851044
    7861045    def get_min(self, v):
    7871046        r"""
     
    8071066            sage: p.get_min(v[1])
    8081067            6.0
    8091068        """
    810         return float(self.min[v]) if self.min.has_key(v) else None
     1069        return float(self._variables_bounds_min[self._variables[v]]) if self._variables_bounds_min[self._variables[v]] != None else None
    8111070
    8121071    def get_max(self, v):
    8131072        r"""
     
    8321091            sage: p.get_max(v[1])
    8331092            6.0
    8341093        """
    835         return float(self.max[v]) if self.max.has_key(v) else None
     1094        return float(self._variables_bounds_max[self._variables[v]])  if self._variables_bounds_max[self._variables[v]] != None else None
    8361095
    8371096class MIPSolverException(Exception):
    8381097    r"""
     
    8471106
    8481107        EXAMPLE::
    8491108
     1109            sage: from sage.numerical.mip import MIPSolverException
    8501110            sage: MIPSolverException("Error")
    8511111            MIPSolverException()
     1112
     1113        TESTS::
     1114
     1115            sage: # No continuous solution
     1116            sage: #
     1117            sage: p=MixedIntegerLinearProgram()
     1118            sage: v=p.new_variable()
     1119            sage: p.add_constraint(v[0],max=5.5)
     1120            sage: p.add_constraint(v[0],min=7.6)
     1121            sage: p.set_objective(v[0])
     1122            sage: #
     1123            sage: # Tests of GLPK's Exceptions
     1124            sage: #
     1125            sage: p.solve(solver="GLPK") # optional - requires GLPK
     1126            Traceback (most recent call last):
     1127            ...
     1128            MIPSolverException: 'GLPK : Solution is undefined'
     1129            sage: #
     1130            sage: #
     1131            sage: # No integer solution
     1132            sage: #
     1133            sage: p=MixedIntegerLinearProgram()
     1134            sage: v=p.new_variable()
     1135            sage: p.add_constraint(v[0],max=5.6)
     1136            sage: p.add_constraint(v[0],min=5.2)
     1137            sage: p.set_objective(v[0])
     1138            sage: p.set_integer(v)
     1139            sage: #
     1140            sage: # Tests of GLPK's Exceptions
     1141            sage: #
     1142            sage: p.solve(solver="GLPK") # optional - requires GLPK
     1143            Traceback (most recent call last):
     1144            ...
     1145            MIPSolverException: 'GLPK : Solution is undefined'
     1146
     1147
    8521148        """
    8531149        self.value = value
    8541150
     
    8581154
    8591155        EXAMPLE::
    8601156
     1157            sage: from sage.numerical.mip import MIPSolverException
    8611158            sage: e = MIPSolverException("Error")
    8621159            sage: print e
    8631160            'Error'
     
    8701167    ``MixedIntegerLinearProgram``.
    8711168    """
    8721169
    873     def __init__(self, p, vtype, dim=1):
     1170    def __init__(self, p, vtype, dim=1, name=None):
    8741171        r"""
    8751172        Constructor for ``MIPVariable``.
    8761173
     
    8811178        - ``vtype`` (integer) -- Defines the type of the variables
    8821179          (default is ``REAL``).
    8831180        - ``dim`` -- the integer defining the definition of the variable.
     1181        - ``name`` -- A name for the ``MIPVariable``.
    8841182
    8851183        For more informations, see the method
    8861184        ``MixedIntegerLinearProgram.new_variable``.
     
    8901188            sage: p=MixedIntegerLinearProgram()
    8911189            sage: v=p.new_variable()
    8921190        """
    893         self.dim = dim
    894         self.dict = {}
    895         self.p = p
    896         self.vtype = vtype
     1191        self._dim = dim
     1192        self._dict = {}
     1193        self._p = p
     1194        self._vtype = vtype
     1195        self._name=name
     1196
    8971197
    8981198    def __getitem__(self, i):
    8991199        r"""
     
    9081208            sage: v = p.new_variable()
    9091209            sage: p.set_objective(v[0] + v[1])
    9101210            sage: v[0]
    911             x1
     1211            x0
    9121212        """
    913         if self.dict.has_key(i):
    914             return self.dict[i]
    915         elif self.dim == 1:
    916             self.dict[i] = self.p._add_element_to_ring(self.vtype)
    917             return self.dict[i]
     1213        if self._dict.has_key(i):
     1214            return self._dict[i]
     1215        elif self._dim == 1:
     1216            self._dict[i] = self._p._add_element_to_ring(self._vtype)
     1217            return self._dict[i]
    9181218        else:
    919             self.dict[i] = MIPVariable(self.p, self.vtype, dim=self.dim-1)
    920             return self.dict[i]
     1219            self._dict[i] = MIPVariable(self._p, self._vtype, dim=self._dim-1)
     1220            return self._dict[i]
     1221
     1222    def _update_variables_name(self, prefix=None):
     1223        r"""
     1224        Updates the names of the variables in the parent instant of ``MixedIntegerLinearProgram``.
     1225
     1226        Only called before writing the Problem to a MPS or LP file.
     1227       
     1228        EXAMPLE::
     1229
     1230            sage: p=MixedIntegerLinearProgram()
     1231            sage: v=p.new_variable(name="Test")
     1232            sage: v[5]+v[99]
     1233            x1 + x0
     1234            sage: p._variables_name=['']*2
     1235            sage: v._update_variables_name()
     1236        """
     1237
     1238        if prefix==None:
     1239            prefix=self._name
     1240
     1241        if self._dim==1:
     1242            for (k,v) in self._dict.iteritems():
     1243                self._p._variables_name[int(str(v)[1:])]=prefix+"["+str(k)+"]"
     1244        else:
     1245            for v in self._dict.itervalues():
     1246                v._update_variables_name(prefix=prefix+"["+str(k)+"]")
     1247               
     1248               
     1249
     1250    def __repr__(self):
     1251        r"""
     1252        Returns a representation of self.
     1253
     1254        EXAMPLE::
     1255
     1256            sage: p=MixedIntegerLinearProgram()
     1257            sage: v=p.new_variable(dim=3)
     1258            sage: v
     1259            MIPVariable of dimension 3.
     1260            sage: v[2][5][9]
     1261            x0
     1262            sage: v
     1263            MIPVariable of dimension 3.
     1264        """
     1265        return "MIPVariable of dimension "+str(self._dim)+"."
    9211266
    9221267    def keys(self):
    9231268        r"""
     
    9311276            sage: v.keys()
    9321277            [0, 1]
    9331278        """
    934         return self.dict.keys()
     1279        return self._dict.keys()
    9351280
    9361281    def items(self):
    9371282        r"""
     
    9431288            sage: v = p.new_variable()
    9441289            sage: p.set_objective(v[0] + v[1])
    9451290            sage: v.items()
    946             [(0, x1), (1, x2)]
     1291            [(0, x0), (1, x1)]
    9471292        """
    948         return self.dict.items()
     1293        return self._dict.items()
    9491294
    9501295    def depth(self):
    9511296        r"""
     
    9591304            sage: v.depth()
    9601305            1
    9611306        """
    962         return self.dim
     1307        return self._dim
    9631308
    9641309    def values(self):
    9651310        r"""
     
    9711316            sage: v = p.new_variable()
    9721317            sage: p.set_objective(v[0] + v[1])
    9731318            sage: v.values()
    974             [x1, x2]
     1319            [x0, x1]
    9751320        """
    976         return self.dict.values()
     1321        return self._dict.values()