Ticket #12823: trac_12823_const_for_obj_funs.patch

File trac_12823_const_for_obj_funs.patch, 18.4 KB (added by john_perry, 8 years ago)
  • sage/numerical/backends/coin_backend.pxd

    # HG changeset patch
    # User John Perry <john.perry@usm.edu>
    # Date 1334188685 18000
    # Node ID 8ae435d3ca273c3a8c5e3fa549359ca54cbdbf6b
    # Parent  7b24b99e8010598a816eddaa817a594b30e3cdb1
    Trac 12823: Constant values for objective functions
    
    diff --git a/sage/numerical/backends/coin_backend.pxd b/sage/numerical/backends/coin_backend.pxd
    a b  
    121121
    122122        # add row
    123123        void addRow(CoinPackedVectorBase & vec, double rowlb, double rowub)
     124        void deleteRows(int num, int *)
    124125
    125126        # io
    126127        void writeMps(char *filename, char *extension, double objSense)
     
    180181    cdef OsiSolverInterface * si
    181182    cdef CbcModel * model
    182183    cdef int log_level
    183     cdef double obj_value
    184184
    185185    cdef list col_names, row_names
    186186    cdef str prob_name
  • sage/numerical/backends/coin_backend.pyx

    diff --git a/sage/numerical/backends/coin_backend.pyx b/sage/numerical/backends/coin_backend.pyx
    a b  
    298298        else:
    299299            return self.si.getObjCoefficients()[variable]
    300300
    301     cpdef set_objective(self, list coeff):
     301    cpdef set_objective(self, list coeff, double d = 0.0):
    302302        r"""
    303303        Sets the objective function.
    304304
     
    323323        for i,v in enumerate(coeff):
    324324            self.si.setObjCoeff(i, v)
    325325
     326        self.obj_value = d
     327
    326328    cpdef set_verbosity(self, int level):
    327329        r"""
    328330        Sets the log (verbosity) level
     
    341343
    342344        self.model.setLogLevel(level)
    343345
     346    cpdef remove_constraint(self, int i):
     347        r"""
     348        Remove a constraint from self.
     349
     350        INPUT:
     351
     352        - ``i`` -- index of the constraint to remove
     353
     354        WARN::
     355
     356            Coin numbers constraints starting at 0, not at 1. If your program has
     357            ``n`` constraints and you ask it to remove constraint ``n``, IT WILL CRASH!
     358
     359        EXAMPLE::
     360
     361            sage: p = MixedIntegerLinearProgram(solver='Coin')
     362            sage: x,y = p[0], p[1]
     363            sage: p.add_constraint(2*x + 3*y, max = 6)
     364            sage: p.add_constraint(3*x + 2*y, max = 6)
     365            sage: p.set_objective(x + y + 7)
     366            sage: p.set_integer(x); p.set_integer(y)
     367            sage: p.solve()
     368            9.0
     369            sage: p.get_values([x,y])
     370            [2.0, 0.0]
     371            sage: p.remove_constraint(0)
     372            sage: p.solve()
     373            10.0
     374            sage: p.get_values([x,y])
     375            [0.0, 3.0]
     376        """
     377        cdef int rows[1]
     378
     379        rows[0] = i
     380        self.si.deleteRows(1,rows)
     381
     382    cpdef remove_constraints(self, constraints):
     383        r"""
     384        Remove several constraints.
     385 
     386        INPUT:
     387 
     388        - ``constraints`` -- an iterable containing the indices of the rows to remove.
     389
     390        WARN::
     391
     392            Coin numbers constraints starting at 0, not at 1. If your program has
     393            ``n`` constraints and you ask it to remove constraint ``n``, IT WILL CRASH!
     394
     395        EXAMPLE::
     396
     397            sage: p = MixedIntegerLinearProgram(solver='Coin')
     398            sage: x,y = p[0], p[1]
     399            sage: p.add_constraint(2*x + 3*y, max = 6)
     400            sage: p.add_constraint(3*x + 2*y, max = 6)
     401            sage: p.set_objective(x + y + 7)
     402            sage: p.set_integer(x); p.set_integer(y)
     403            sage: p.solve()
     404            9.0
     405            sage: p.get_values([x,y])
     406            [2.0, 0.0]
     407            sage: p.remove_constraints([0])
     408            sage: p.solve()
     409            10.0
     410            sage: p.get_values([x,y])
     411            [0.0, 3.0]
     412        """
     413        cdef int i
     414        cdef int m = len(constraints)
     415        cdef int * rows = <int *>sage_malloc(m * sizeof(int *))
     416
     417        for i in xrange(m): rows[i] = constraints[i]
     418        self.si.deleteRows(m, rows)
     419        sage_free(rows)
    344420
    345421    cpdef add_linear_constraints(self, int number, lower_bound, upper_bound, names = None):
    346422        """
     
    682758            sage: p.get_variable_value(1)                          # optional - Coin
    683759            1.5
    684760        """
    685         return self.model.solver().getObjValue()
     761        return self.model.solver().getObjValue() + self.obj_value
    686762
    687763    cpdef double get_variable_value(self, int variable):
    688764        r"""
     
    10411117        p.si = self.si.clone(1)
    10421118        p.row_names = copy(self.row_names)
    10431119        p.col_names = copy(self.col_names)
     1120        p.obj_value = self.obj_value
    10441121        # Maybe I should copy this, not sure -- seems complicated, though
    10451122        p.prob_name = self.prob_name
    10461123
  • sage/numerical/backends/generic_backend.pxd

    diff --git a/sage/numerical/backends/generic_backend.pxd b/sage/numerical/backends/generic_backend.pxd
    a b  
    1111    cpdef set_variable_type(self, int variable, int vtype)
    1212    cpdef set_sense(self, int sense)
    1313    cpdef objective_coefficient(self, int variable, coeff=*)
    14     cpdef set_objective(self, list coeff)
     14    cpdef set_objective(self, list coeff, double d=*)
    1515    cpdef set_verbosity(self, int level)
    1616    cpdef add_linear_constraint(self, constraints, lower_bound, upper_bound, name=*)
     17    cpdef remove_constraint(self, int)
     18    cpdef remove_constraints(self, constraints)
    1719    cpdef add_col(self, list indices, list coeffs)
    1820    cpdef add_linear_constraints(self, int number, lower_bound, upper_bound, names=*)
    1921    cpdef int solve(self) except -1
     
    3739    cpdef variable_lower_bound(self, int index, value = *)
    3840    cpdef solver_parameter(self, name, value=*)
    3941
     42    cdef double obj_value
     43
    4044cpdef GenericBackend get_solver(constraint_generation = ?, solver = ?)
  • sage/numerical/backends/generic_backend.pyx

    diff --git a/sage/numerical/backends/generic_backend.pyx b/sage/numerical/backends/generic_backend.pyx
    a b  
    197197        """
    198198        raise NotImplementedError()
    199199
    200     cpdef  set_objective(self, list coeff):
     200    cpdef  set_objective(self, list coeff, double d = 0.0):
    201201        """
    202202        Set the objective function.
    203203
     
    234234        """
    235235        raise NotImplementedError()
    236236
     237    cpdef remove_constraint(self, int i):
     238      """
     239      Remove a constraint.
     240
     241      INPUT:
     242
     243      - ``i`` -- index of the constraint to remove.
     244      """
     245      raise NotImplementedError()
     246
     247    cpdef remove_constraints(self, constraints):
     248      """
     249      Remove several constraints.
     250
     251      INPUT:
     252
     253      - ``constraints`` -- an iterable containing the indices of the rows to remove.
     254      """
     255      raise NotImplementedError()
     256
    237257    cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):
    238258        """
    239259        Add a linear constraint.
  • sage/numerical/backends/glpk_backend.pxd

    diff --git a/sage/numerical/backends/glpk_backend.pxd b/sage/numerical/backends/glpk_backend.pxd
    a b  
    5252     void glp_set_obj_dir(c_glp_prob *, int)
    5353     void glp_add_rows(c_glp_prob *, int)
    5454     void glp_add_cols(c_glp_prob *, int)
     55     void glp_del_rows(c_glp_prob *, int, int *)
    5556     void glp_set_row_name(c_glp_prob *, int, char *)
    5657     void glp_set_col_name(c_glp_prob *, int, char *)
    5758     void glp_set_row_bnds(c_glp_prob *, int, int, double, double)
  • sage/numerical/backends/glpk_backend.pyx

    diff --git a/sage/numerical/backends/glpk_backend.pyx b/sage/numerical/backends/glpk_backend.pyx
    a b  
    311311        else:
    312312            glp_set_prob_name(self.lp, name)
    313313
    314     cpdef set_objective(self, list coeff):
     314    cpdef set_objective(self, list coeff, double d = 0.0):
    315315        """
    316316        Set the objective function.
    317317
     
    335335        for i,v in enumerate(coeff):
    336336            glp_set_obj_coef(self.lp, i+1, v)
    337337
     338        glp_set_obj_coef(self.lp, 0, d)
     339
     340        self.obj_value = d
     341
    338342    cpdef set_verbosity(self, int level):
    339343        """
    340344        Set the verbosity level
     
    363367            self.iocp.msg_lev = GLP_MSG_ALL
    364368            self.smcp.msg_lev = GLP_MSG_ALL
    365369
     370    cpdef remove_constraint(self, int i):
     371        r"""
     372        Remove a constraint.
     373
     374        INPUT:
     375
     376        - ``i`` -- the index of the constraint to remove
     377
     378        EXAMPLE::
     379
     380            sage: p = MixedIntegerLinearProgram(solver='GLPK')
     381            sage: x,y = p[0], p[1]
     382            sage: p.add_constraint(2*x + 3*y, max = 6)
     383            sage: p.add_constraint(3*x + 2*y, max = 6)
     384            sage: p.set_objective(x + y + 7)
     385            sage: p.set_integer(x); p.set_integer(y)
     386            sage: p.solve()
     387            9.0
     388            sage: p.get_values([x,y])
     389            [1.0, 1.0]
     390            sage: p.remove_constraint(1)
     391            sage: p.solve()
     392            10.0
     393            sage: p.get_values([x,y])
     394            [0.0, 3.0]
     395        """
     396        cdef int rows[2]
     397
     398        rows[1] = i
     399        glp_del_rows(self.lp, 1, rows)
     400
     401    cpdef remove_constraints(self, constraints):
     402        r"""
     403        Remove several constraints.
     404 
     405        INPUT:
     406 
     407        - ``constraints`` -- an iterable containing the indices of the rows to remove.
     408
     409        WARN::
     410
     411            GLPK numbers constraints starting at 1, not at 0. If you ask GLPK to
     412            remove constraint 0, IT WILL CRASH!
     413
     414        Note that if names have been assigned to constraints,
     415        the names of constraints that are not deleted will shift.
     416
     417        EXAMPLE::
     418
     419            sage: p = MixedIntegerLinearProgram(solver='GLPK')
     420            sage: x,y = p[0], p[1]
     421            sage: p.add_constraint(2*x + 3*y, max = 6)
     422            sage: p.add_constraint(3*x + 2*y, max = 6)
     423            sage: p.set_objective(x + y + 7)
     424            sage: p.set_integer(x); p.set_integer(y)
     425            sage: p.solve()
     426            9.0
     427            sage: p.get_values([x,y])
     428            [1.0, 1.0]
     429            sage: p.remove_constraints([1])
     430            sage: p.solve()
     431            10.0
     432            sage: p.get_values([x,y])
     433            [0.0, 3.0]
     434        """
     435        cdef int i
     436        cdef int m = len(constraints)
     437        cdef int * rows = <int *>sage_malloc((m + 1) * sizeof(int *))
     438
     439        for i in xrange(m): rows[i + 1] = constraints[i]
     440        glp_del_rows(self.lp, m, rows)
     441        sage_free(rows)
     442
    366443    cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):
    367444        """
    368445        Add a linear constraint.
  • sage/numerical/mip.pyx

    diff --git a/sage/numerical/mip.pyx b/sage/numerical/mip.pyx
    a b  
    6565    Minimization:
    6666       x_3
    6767    Constraints:
    68       0.0 <= x_0 +x_1 +x_2 -14.0 x_3 <= 0.0
    69       0.0 <= x_1 +2.0 x_2 -8.0 x_3 <= 0.0
    70       0.0 <= 2.0 x_2 -3.0 x_3 <= 0.0
    71       -x_0 +x_1 +x_2 <= 0.0
    72       -x_3 <= -1.0
     68      0.0 <= x_0 + x_1 + x_2 - 14.0 x_3 <= 0.0
     69      0.0 <= x_1 + 2.0 x_2 - 8.0 x_3 <= 0.0
     70      0.0 <= 2.0 x_2 - 3.0 x_3 <= 0.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)
     
    522522            sage: p.add_constraint(-3*x[1] + 2*x[2], max=2, name="Constraint_1")
    523523            sage: p.show()
    524524            Maximization:
    525               Hey[1] +Hey[2]
     525              Hey[1] + Hey[2]
    526526            Constraints:
    527               Constraint_1: -3.0 Hey[1] +2.0 Hey[2] <= 2.0
     527              Constraint_1: -3.0 Hey[1] + 2.0 Hey[2] <= 2.0
    528528            Variables:
    529529              Hey[1] is a continuous variable (min=0.0, max=+oo)
    530530              Hey[2] is a continuous variable (min=0.0, max=+oo)
     
    537537            sage: p.add_constraint(-3*x[1] + 2*x[2], max=2)
    538538            sage: p.show()
    539539            Maximization:
    540               x_0 +x_1
     540              x_0 + x_1
    541541            Constraints:
    542               -3.0 x_0 +2.0 x_1 <= 2.0
     542              -3.0 x_0 + 2.0 x_1 <= 2.0
    543543            Variables:
    544544              x_0 is a continuous variable (min=0.0, max=+oo)
    545545              x_1 is a continuous variable (min=0.0, max=+oo)
     
    573573            if c == 0:
    574574                continue
    575575
    576             print (("+" if (not first and c>0) else "") +
    577                    ("" if c == 1 else ("-" if c == -1 else str(c)+" "))+varid_name[i]
     576            print (("+ " if (not first and c>0) else "") +
     577                   ("" if c == 1 else ("- " if c == -1 else str(c)+" "))+varid_name[i]
    578578                   ),
    579579            first = False
    580580
     581        if   b.obj_value > 0.0: print "+", b.obj_value
     582        elif b.obj_value < 0.0: print "-", -b.obj_value
     583
    581584        print
    582585
    583586        ##### Constraints
     
    607610                if c == 0:
    608611                    continue
    609612
    610                 print (("+" if (not first and c>0) else "") +
    611                        ("" if c == 1 else ("-" if c == -1 else str(c)+" "))+varid_name[j]
     613                print (("+ " if (not first and c>0) else "") +
     614                       ("" if c == 1 else ("- " if c == -1 else (str(c) + " " if first and c < 0 else ("- " + str(abs(c)) + " " if c < 0 else str(c)+" "))))+varid_name[j]
    612615                       ),
    613616                first = False
    614617
     
    825828        else:
    826829            f = {-1 : 0}
    827830       
    828         f.pop(-1,0)
     831        cdef double d = f.pop(-1,0.0)
    829832
    830833        for i in range(self._backend.ncols()):
    831             values.append(f.get(i,0))
    832 
    833 
    834         self._backend.set_objective(values)
     834            values.append(f.get(i,0.0))
     835
     836        self._backend.set_objective(values, d)
    835837           
    836838    def add_constraint(self, linear_function, max=None, min=None, name=None):
    837839        r"""
     
    915917            Maximization:
    916918            <BLANKLINE>
    917919            Constraints:
    918               -2.0 x_0 -x_1 <= 9.0
     920              -2.0 x_0 - x_1 <= 9.0
    919921            Variables:
    920922              x_0 is a continuous variable (min=0.0, max=+oo)
    921923              x_1 is a continuous variable (min=0.0, max=+oo)
     
    945947            Maximization:
    946948            <BLANKLINE>
    947949            Constraints:
    948               1.0 <= x_0 -x_1 
     950              1.0 <= x_0 - x_1 
    949951            Variables:
    950952              x_0 is a continuous variable (min=0.0, max=+oo)
    951953              x_1 is a continuous variable (min=0.0, max=+oo)
     
    957959            Maximization:
    958960            <BLANKLINE>
    959961            Constraints:
    960               1.0 <= x_0 -x_1 
     962              1.0 <= x_0 - x_1 
    961963            Variables:
    962964              x_0 is a continuous variable (min=0.0, max=+oo)
    963965              x_1 is a continuous variable (min=0.0, max=+oo)
     
    969971              Maximization:
    970972              <BLANKLINE>
    971973              Constraints:
    972                 1.0 <= x_0 -x_1 
    973                 x_0 -x_1 <= 1.0
     974                1.0 <= x_0 - x_1 
     975                x_0 - x_1 <= 1.0
    974976              Variables:
    975977                x_0 is a continuous variable (min=0.0, max=+oo)
    976978                x_1 is a continuous variable (min=0.0, max=+oo)
     
    10361038                self.add_constraint(functions[0] - functions[1], max=0, name=name)
    10371039                self.add_constraint(functions[1] - functions[2], max=0, name=name)
    10381040
     1041    def remove_constraint(self, int i):
     1042        r"""
     1043        Removes a constraint from self.
     1044
     1045        INPUT:
     1046
     1047        - ``i`` -- Index of the constraint to remove.
     1048
     1049        EXAMPLE::
     1050
     1051            sage: p = MixedIntegerLinearProgram()
     1052            sage: x, y = p[0], p[1]
     1053            sage: p.add_constraint(x + y, max = 10)
     1054            sage: p.add_constraint(x - y, max = 0)
     1055            sage: p.add_constraint(x - y, max = 0)
     1056            sage: p.add_constraint(x, max = 4)
     1057            sage: p.remove_constraint(2)
     1058            sage: p.show()
     1059            Maximization:
     1060            <BLANKLINE>
     1061            Constraints:
     1062              x_0 + x_1 <= 10.0
     1063              x_0 - x_1 <= 0.0
     1064              x_0 <= 4.0
     1065            ...
     1066            sage: p.number_of_constraints()
     1067            3
     1068
     1069        WARN::
     1070
     1071            Whether the first constraint is numbered 0 or 1 depends on the backend.
     1072            For GLPK, the first constraint has index 1; for Coin, it has index 0.
     1073            This is why the example above adds the same constraint twice,
     1074            and tries to remove on of its copies. Whether it removes the first
     1075            or the second depends on the backend.
     1076            Since supplying an invalid number WILL CAUSE A CRASH, please be careful!
     1077        """
     1078        self._backend.remove_constraint(i)
     1079
     1080    def remove_constraints(self, constraints):
     1081        """
     1082        Remove several constraints.
     1083 
     1084        INPUT:
     1085 
     1086        - ``constraints`` -- an iterable containing the indices of the rows to remove.
     1087 
     1088        Behavior may depend on the solver chosen.
     1089
     1090        EXAMPLE::
     1091
     1092            sage: p = MixedIntegerLinearProgram()
     1093            sage: x, y = p[0], p[1]
     1094            sage: p.add_constraint(x + y, max = 10)
     1095            sage: p.add_constraint(x - y, max = 0)
     1096            sage: p.add_constraint(x - y, max = 0)
     1097            sage: p.add_constraint(x, max = 4)
     1098            sage: p.remove_constraints([2])
     1099            sage: p.show()
     1100            Maximization:
     1101            <BLANKLINE>
     1102            Constraints:
     1103              x_0 + x_1 <= 10.0
     1104              x_0 - x_1 <= 0.0
     1105              x_0 <= 4.0
     1106            ...
     1107            sage: p.number_of_constraints()
     1108            3
     1109
     1110        WARN::
     1111
     1112            Whether the first constraint is numbered 0 or 1 depends on the backend.
     1113            For GLPK, the first constraint has index 1; for Coin, it has index 0.
     1114            This is why the example above adds the same constraint twice,
     1115            and tries to remove on of its copies. Whether it removes the first
     1116            or the second depends on the backend.
     1117            Since supplying an invalid number WILL CAUSE A CRASH, please be careful!
     1118
     1119        """
     1120        self._backend.remove_constraints(constraints)
     1121
    10391122    def set_binary(self, ee):
    10401123        r"""
    10411124        Sets a variable or a ``MIPVariable`` as binary.
     
    13071390            sage: p.set_binary(b)
    13081391            sage: p.solve(objective_only=True)
    13091392            4.0
     1393
     1394        Constants in the objective function are respected:
     1395
     1396            sage: p = MixedIntegerLinearProgram()
     1397            sage: x, y = p[0], p[1]
     1398            sage: p.add_constraint(2*x + 3*y, max = 6)
     1399            sage: p.add_constraint(3*x + 2*y, max = 6)
     1400            sage: p.set_objective(x + y + 7)
     1401            sage: p.set_integer(x); p.set_integer(y)
     1402            sage: p.solve()
     1403            9.0
    13101404        """
    13111405
    13121406        if solver != None: