Ticket #10341: trac_10431-part5.patch

File trac_10431-part5.patch, 14.5 KB (added by ncohen, 11 years ago)
  • sage/numerical/backends/cplex_backend.pyx

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1291485477 -3600
    # Node ID cd198aaa8581071c9dea2518f7ff21d290c5f8f8
    # Parent  214981100765f40322a4c90db831d069bbec0689
    trac 10341 -- Fixing MixedIntegerLinearProgram.show() and how the variables' names are managed
    
    diff -r 214981100765 -r cd198aaa8581 sage/numerical/backends/cplex_backend.pyx
    a b  
    695695        status = CPXgetlb(self.env, self.lp, &lb, index, index)
    696696        check(status)
    697697
    698         return (lb if lb != -CPX_INFBOUND else None,
    699                 ub if ub != +CPX_INFBOUND else None)
     698        return (None if lb <= -int(CPX_INFBOUND) else lb,
     699                None if ub >= +int(CPX_INFBOUND) else ub)
    700700
    701701    cpdef add_col(self, list indices, list coeffs):
    702702        r"""
     
    11381138            status = CPXgetub(self.env, self.lp, &ub, index, index)
    11391139            check(status)
    11401140
    1141             return ub if ub != CPX_INFBOUND else None
     1141            return ub if ub < int(CPX_INFBOUND) else None
    11421142
    11431143        else:
    11441144
     
    11791179        if value == False:
    11801180            status = CPXgetlb(self.env, self.lp, &lb, index, index)
    11811181            check(status)
    1182             return lb if lb != -CPX_INFBOUND else None
     1182            return None if lb <= int(-CPX_INFBOUND) else lb
    11831183
    11841184        else:
    11851185            x = 'L'
  • sage/numerical/mip.pxd

    diff -r 214981100765 -r cd198aaa8581 sage/numerical/mip.pxd
    a b  
    2525    cdef dict _dict
    2626    cdef int _vtype
    2727    cdef char * _name
     28    cdef bint _hasname
  • sage/numerical/mip.pyx

    diff -r 214981100765 -r cd198aaa8581 sage/numerical/mip.pyx
    a b  
    6868      0.0 <= x_0 +x_1 +x_2 -14.0 x_3 <= 0.0
    6969      0.0 <= x_1 +2.0 x_2 -8.0 x_3 <= 0.0
    7070      0.0 <= 2.0 x_2 -3.0 x_3 <= 0.0
    71       -1.0 x_0 +x_1 +x_2 <= 0.0
    72       -1.0 x_3 <= -1.0
     71      -x_0 +x_1 +x_2 <= 0.0
     72      -x_3 <= -1.0
    7373    Variables:
    7474      x_0 is an integer variable (min=0.0, max=+oo)
    7575      x_1 is an integer variable (min=-oo, max=+oo)
     
    8787
    8888include "../ext/stdsage.pxi"
    8989include "../ext/interrupt.pxi"
     90include "../ext/cdefs.pxi"
    9091from copy import deepcopy
    9192
    9293cdef class MixedIntegerLinearProgram:
     
    274275
    275276        self._backend.problem_name(name)
    276277
    277     # def _update_variables_name(self):
    278     #     r"""
    279     #     Updates the names of the variables.
    280 
    281     #     Only called before writing the Problem to a MPS or LP file.
    282        
    283     #     EXAMPLE::
    284 
    285     #         sage: p=MixedIntegerLinearProgram()
    286     #         sage: v=p.new_variable(name="Test")
    287     #         sage: v[5]+v[99]
    288     #         x_0 +x_1
    289     #         sage: p._update_variables_name()
    290     #     """
    291 
    292     #     for v in self._mipvariables:
    293     #         v._update_variables_name()
    294 
    295 
    296     def new_variable(self, real=False, binary=False, integer=False, dim=1,name=None):
     278    def new_variable(self, real=False, binary=False, integer=False, dim=1,name=""):
    297279        r"""
    298280        Returns an instance of ``MIPVariable`` associated
    299281        to the current instance of ``MixedIntegerLinearProgram``.
     
    345327            ...
    346328            ValueError: Exactly one of the available types has to be True
    347329        """
    348         if name==None:
    349             name="V"+str(len(self._mipvariables))
    350 
    351330        if sum([real, binary, integer]) >= 2:
    352331            raise ValueError("Exactly one of the available types has to be True")
    353332
     
    369348
    370349        EXAMPLES:
    371350
    372         When constraints have names ::
     351        When constraints and variables have names ::
     352
     353            sage: p = MixedIntegerLinearProgram()
     354            sage: x = p.new_variable(name="Hey")
     355            sage: p.set_objective(x[1] + x[2])
     356            sage: p.add_constraint(-3*x[1] + 2*x[2], max=2, name="Constraint_1")
     357            sage: p.show()
     358            Maximization:
     359              Hey[1] +Hey[2]
     360            Constraints:
     361              Constraint_1: -3.0 Hey[1] +2.0 Hey[2] <= 2.0
     362            Variables:
     363              Hey[1] is a continuous variable (min=0.0, max=+oo)
     364              Hey[2] is a continuous variable (min=0.0, max=+oo)
     365
     366        Without any names ::
    373367
    374368            sage: p = MixedIntegerLinearProgram()
    375369            sage: x = p.new_variable()
    376370            sage: p.set_objective(x[1] + x[2])
    377             sage: p.add_constraint(-3*x[1] + 2*x[2], max=2, name="Constraint_1")
     371            sage: p.add_constraint(-3*x[1] + 2*x[2], max=2)
    378372            sage: p.show()
    379373            Maximization:
    380                x_0 +x_1
     374              x_0 +x_1
    381375            Constraints:
    382               Constraint_1: -3.0 x_0 +2.0 x_1 <= 2.0
     376              -3.0 x_0 +2.0 x_1 <= 2.0
    383377            Variables:
    384               x_0 is a real variable (min=0.0, max=+oo)
    385               x_1 is a real variable (min=0.0, max=+oo)
     378              x_0 is a continuous variable (min=0.0, max=+oo)
     379              x_1 is a continuous variable (min=0.0, max=+oo)
    386380        """
    387381
    388382        cdef int i, j
    389383        cdef double c
    390384        cdef GenericBackend b = self._backend
    391         #self._update_variables_name()
    392385
     386        # inv_variables associates a MIPVariable object to an id
    393387        inv_variables = [0]*len(self._variables)
    394         for (v,id) in self._variables.iteritems():
     388        for (v, id) in self._variables.iteritems():
    395389            inv_variables[id]=v
    396390
    397         value = ( "Maximization:\n"
    398                   if b.is_maximization()
    399                   else "Minimization:\n" )
    400         value+="  "
     391
     392        # varid_name associates variables id to names
     393        varid_name = {}
     394
     395        for 0<= i < b.ncols():
     396            s = b.col_name(i)
     397            varid_name[i] = ("x_"+str(i)) if s == "" else s
     398
     399        ##### Sense and objective function
     400
     401        print ("Maximization:" if b.is_maximization() else "Minimization:")
     402        print " ",
    401403       
    402404        first = True
    403405        for 0<= i< b.ncols():
    404406            c = b.objective_coefficient(i)
    405             if c != 0:
     407            if c == 0:
     408                continue
    406409
    407                 value+= ((" +" if (not first and c>0) else " ") +
    408                          str(inv_variables[i]*b.objective_coefficient(i))
    409                          )
    410                 first = False
     410            print (("+" if (not first and c>0) else "") +
     411                   ("" if c == 1 else ("-" if c == -1 else str(c)+" "))+varid_name[i]
     412                   ),
     413            first = False
    411414
    412         value += "\nConstraints:"
     415        print
    413416
     417        ##### Constraints
     418        print "Constraints:"
    414419
    415420        for 0<= i < b.nrows():
    416421
     
    418423
    419424            lb, ub = b.row_bounds(i)
    420425
    421             value += ("\n  "+
    422                       (b.row_name(i)+": " if b.row_name(i)!="" else "")+
    423                       (str(lb)+" <= " if lb!=None else "")
    424                       )
     426            print " ",
     427
     428
     429            # Constraint's name
     430            if b.row_name(i):
     431                print b.row_name(i)+":",
     432
     433            # Lower bound
     434            if lb is not None:
     435                print str(lb)+" <=",
    425436
    426437            first = True
    427438
    428             for j,v in sorted(zip(indices, values)):
     439            for j,c in sorted(zip(indices, values)):
    429440
    430                 value += (("+" if (not first and v>=0) else "") +
    431                           str(inv_variables[j]*v) +" ")
     441                if c == 0:
     442                    continue
    432443
     444                print (("+" if (not first and c>0) else "") +
     445                       ("" if c == 1 else ("-" if c == -1 else str(c)+" "))+varid_name[j]
     446                       ),
    433447                first = False
    434448
    435             value += ("<= "+str(ub) if ub!=None else "")
     449            # Upper bound
     450            print ("<= "+str(ub) if ub!=None else "")
    436451
    437         value += "\nVariables:"
     452
     453        ##### Variables
     454        print "Variables:"
    438455
    439456        for 0<= i < b.ncols():
    440             value += "\n  " + str(inv_variables[i]) + " is"
     457            print "  " + varid_name[i] + " is",
    441458
    442459            if b.is_variable_integer(i):
    443                 value += " an integer variable"
     460                print "an integer variable",
    444461            elif b.is_variable_binary(i):
    445                 value += " an boolean variable"
     462                print "a boolean variable",
    446463            else:
    447                 value += " a real variable"
     464                print "a continuous variable",
    448465
    449466            lb, ub = b.col_bounds(i)
    450467
    451             value += " (min=" + \
    452                 ( str(lb)
    453                   if lb != None
    454                   else "-oo" ) + \
    455                 ", max=" + \
    456                 ( str(ub)
    457                   if ub != None
    458                   else "+oo" ) + \
    459                 ")"
    460         print value
     468            print "(min=" + ( str(lb) if lb != None else "-oo" )+",",
     469            print "max=" + ( str(ub) if ub != None else "+oo" )+")"
     470
    461471
    462472    def write_mps(self,filename,modern=True):
    463473        r"""
     
    734744            Maximization:
    735745            <BLANKLINE>
    736746            Constraints:
    737               -2.0 x_0 -1.0 x_1 <= 9.0
     747              -2.0 x_0 -x_1 <= 9.0
    738748            Variables:
    739               x_0 is a real variable (min=0.0, max=+oo)
    740               x_1 is a real variable (min=0.0, max=+oo)
     749              x_0 is a continuous variable (min=0.0, max=+oo)
     750              x_1 is a continuous variable (min=0.0, max=+oo)
    741751
    742752        Empty constraint::
    743753
     
    10821092
    10831093        return self._backend.get_objective_value()
    10841094
    1085 
    1086     def _add_element_to_ring(self, vtype):
    1087         r"""
    1088         Creates a new variable in the (Mixed) Integer Linear Program.
    1089 
    1090         INPUT:
    1091 
    1092         - ``vtype`` (integer) -- Defines the type of the variables
    1093           (default is ``REAL``).
    1094 
    1095         OUTPUT:
    1096 
    1097         - The newly created variable.
    1098 
    1099         EXAMPLE::
    1100 
    1101             sage: p = MixedIntegerLinearProgram()
    1102             sage: v = p.new_variable()
    1103             sage: print p
    1104             Mixed Integer Program  ( maximization, 0 variables, 0 constraints )
    1105             sage: p._add_element_to_ring(-1)
    1106             x_0
    1107             sage: print p
    1108             Mixed Integer Program  ( maximization, 1 variables, 0 constraints )
    1109         """
    1110 
    1111         v = LinearFunction({len(self._variables) : 1})
    1112 
    1113         self._variables[v] = len(self._variables)
    1114         self._backend.add_variable()
    1115         self._backend.set_variable_type(self._backend.ncols()-1,vtype)
    1116         return v
    1117 
    11181095    def set_min(self, v, min):
    11191096        r"""
    11201097        Sets the minimum value of a variable.
     
    11361113            sage: p.set_min(v[1],6)
    11371114            sage: p.get_min(v[1])
    11381115            6.0
     1116            sage: p.set_min(v[1], None)
     1117            sage: p.get_min(v[1])
     1118
    11391119        """
    11401120        self._backend.variable_lower_bound(self._variables[v], min)
    11411121
     
    11861166            sage: p.set_min(v[1],6)
    11871167            sage: p.get_min(v[1])
    11881168            6.0
     1169            sage: p.set_min(v[1], None)
     1170            sage: p.get_min(v[1])
    11891171        """
    11901172
    11911173        return self._backend.variable_lower_bound(self._variables[v])
     
    12871269    ``MixedIntegerLinearProgram``.
    12881270    """
    12891271
    1290     def __init__(self, p, vtype, dim=1, name=""):
     1272    def __cinit__(self, p, vtype, dim=1, name=""):
    12911273        r"""
    12921274        Constructor for ``MIPVariable``.
    12931275
     
    12951277
    12961278        - ``p`` -- the instance of ``MixedIntegerLinearProgram`` to which the
    12971279          variable is to be linked.
     1280
    12981281        - ``vtype`` (integer) -- Defines the type of the variables
    12991282          (default is ``REAL``).
     1283
    13001284        - ``dim`` -- the integer defining the definition of the variable.
     1285
    13011286        - ``name`` -- A name for the ``MIPVariable``.
    13021287
    13031288        For more informations, see the method
     
    13131298        self._p = p
    13141299        self._vtype = vtype
    13151300
    1316         #####################################################
    1317         self._name="x"
     1301        self._hasname = (len(name) >0)
    13181302
     1303        # create a temporary char *
     1304        cdef char *name_c = name
     1305        # and copy it over
     1306        self._name = <char*>sage_malloc(len(name)+1)
     1307        strcpy(self._name, name_c)
     1308       
     1309    def __dealloc__(self):
     1310        if self._name:
     1311            sage_free(self._name)
    13191312
    13201313    def __getitem__(self, i):
    13211314        r"""
     
    13321325            sage: v[0]
    13331326            x_0
    13341327        """
     1328        cdef MIPVariable s = self
     1329
     1330        cdef int j
     1331
    13351332        if self._dict.has_key(i):
    13361333            return self._dict[i]
    13371334        elif self._dim == 1:
    1338             self._dict[i] = self._p._add_element_to_ring(self._vtype)
     1335
     1336            j = self._p._backend.add_variable(0.0, None, False, True, False, 0.0,
     1337                                              (str(self._name) + "[" + str(i) + "]")
     1338                                               if self._hasname else None)
     1339
     1340            v = LinearFunction({j : 1})
     1341            self._p._variables[v] = j
     1342            self._p._backend.set_variable_type(j,self._vtype)
     1343            self._dict[i] = v
     1344
     1345            return v
     1346
     1347        else:
     1348            self._dict[i] = MIPVariable(
     1349                self._p,
     1350                self._vtype,
     1351                dim=self._dim-1,
     1352                name = ("" if not self._hasname
     1353                        else (str(self._name) + "[" + str(i) + "]")))
     1354
    13391355            return self._dict[i]
    1340         else:
    1341             self._dict[i] = MIPVariable(self._p, self._vtype, dim=self._dim-1)
    1342             return self._dict[i]
    1343 
    1344     # def _update_variables_name(self, prefix=None):
    1345     #     r"""
    1346     #     Updates the names of the variables in the parent instant of ``MixedIntegerLinearProgram``.
    1347 
    1348     #     Only called before writing the Problem to a MPS or LP file.
    1349        
    1350     #     EXAMPLE::
    1351 
    1352     #         sage: p=MixedIntegerLinearProgram()
    1353     #         sage: v=p.new_variable(name="Test")
    1354     #         sage: v[5]+v[99]
    1355     #         x_0 +x_1
    1356     #         sage: v._update_variables_name()
    1357     #     """
    1358 
    1359     #     if prefix == None:
    1360     #         prefix = self._name
    1361 
    1362     #     if self._dim == 1:
    1363     #         for (k,v) in self._dict.iteritems():
    1364     #             name = prefix + "[" + str(k) + "]"
    1365     #             self._p._backend.col_name(self._p._variables[v], name)
    1366     #             #self._p._variables_name[self._p._variables[v]]=prefix + "[" + str(k) + "]"
    1367     #     else:
    1368     #         for v in self._dict.itervalues():
    1369     #             v._update_variables_name(prefix=prefix + "(" + str(k) + ")")
    1370                                
    13711356
    13721357    def __repr__(self):
    13731358        r"""