Ticket #11606: trac_11606_add_only_new_constraints_to_lp_using_sets.patch

File trac_11606_add_only_new_constraints_to_lp_using_sets.patch, 5.3 KB (added by john_perry, 10 years ago)
  • sage/numerical/mip.pxd

    # HG changeset patch
    # User John Perry <john.perry@usm.edu>
    # Date 1324502701 21600
    # Node ID ba4aa7c81a6d773f50f7bdbefd71feba340b1734
    # Parent  b72663c760492cc8c360d328a6d370c8f88d2069
    Trac 11606: simplify constraints in linear programs
    
    diff --git a/sage/numerical/mip.pxd b/sage/numerical/mip.pxd
    a b  
    2020    cdef int __REAL
    2121    cdef int __INTEGER
    2222    cpdef int number_of_constraints(self)
     23    cdef int _check_redundant
     24    cdef set _constraints
    2325
    2426cdef class MIPVariable:
    2527    cdef MixedIntegerLinearProgram _p
  • sage/numerical/mip.pyx

    diff --git a/sage/numerical/mip.pyx b/sage/numerical/mip.pyx
    a b  
    152152         4.0
    153153    """
    154154   
    155     def __init__(self, solver = None, maximization=True, constraint_generation = False):
     155    def __init__(self, solver = None, maximization=True, constraint_generation = False, check_redundant = False):
    156156        r"""
    157157        Constructor for the ``MixedIntegerLinearProgram`` class.
    158158
     
    185185
    186186        - ``constraint_generation`` -- whether to require the returned solver to
    187187          support constraint generation (excludes Coin). ``False by default``.
     188         
     189        - ``check_redundant`` -- whether to check that constraints added to the
     190          program are redundant with constraints already in the program.
     191          Only obvious redundancies are checked: to be considered redundant,
     192          either a constraint is equal to another constraint in the program,
     193          or it is a constant multiple of the other. To make this search
     194          effective and efficient, constraints are normalized; thus, the
     195          constraint `-x_1 < 0` will be stored as `x_1 > 0`.
    188196
    189197        .. SEEALSO::
    190198
     
    214222
    215223        # Associates an index to the variables
    216224        self._variables = {}
     225       
     226        # Check for redundant constraints
     227        self._check_redundant = check_redundant
     228        if check_redundant:
     229            self._constraints = set()
    217230
    218231    def __repr__(self):
    219232         r"""
     
    258271            p._default_mipvariable = self._default_mipvariable
    259272        except AttributeError:
    260273            pass
     274       
     275        try:
     276            p._check_redundant = self._check_redundant
     277            p._constraints = copy(self._constraints)
     278        except AttributeError:
     279            pass
    261280
    262281        p._backend = (<GenericBackend> self._backend).copy()
    263282        return p
     
    918937            ...
    919938            ValueError: min and max arguments are required to be numerical
    920939
     940        Do not add redundant elements (notice only one copy of each constraint is added)::
     941       
     942            sage: lp = MixedIntegerLinearProgram(check_redundant=True)
     943            sage: for each in xrange(10): lp.add_constraint(lp[0]-lp[1],min=1)
     944            sage: lp.show()
     945            Maximization:
     946            <BLANKLINE>
     947            Constraints:
     948              1.0 <= x_0 -x_1 
     949            Variables:
     950              x_0 is a continuous variable (min=0.0, max=+oo)
     951              x_1 is a continuous variable (min=0.0, max=+oo)
     952               
     953        We check for constant multiples of constraints as well::
     954         
     955            sage: for each in xrange(10): lp.add_constraint(2*lp[0]-2*lp[1],min=2)
     956            sage: lp.show()
     957            Maximization:
     958            <BLANKLINE>
     959            Constraints:
     960              1.0 <= x_0 -x_1 
     961            Variables:
     962              x_0 is a continuous variable (min=0.0, max=+oo)
     963              x_1 is a continuous variable (min=0.0, max=+oo)
     964         
     965        But if the constant multiple is negative, we should add it anyway (once)::
     966         
     967              sage: for each in xrange(10): lp.add_constraint(-2*lp[0]+2*lp[1],min=-2)
     968              sage: lp.show()
     969              Maximization:
     970              <BLANKLINE>
     971              Constraints:
     972                1.0 <= x_0 -x_1 
     973                x_0 -x_1 <= 1.0
     974              Variables:
     975                x_0 is a continuous variable (min=0.0, max=+oo)
     976                x_1 is a continuous variable (min=0.0, max=+oo)
    921977        """
    922978        if linear_function is None or linear_function is 0:
    923979            return None
     
    942998            indices = []
    943999            values = []
    9441000
    945             C = [(v,coeff) for (v,coeff) in f.iteritems() if v != -1]
     1001            if self._check_redundant:
     1002              b = self._backend
     1003              from __builtin__ import min as min_function
     1004              i = min_function([v for (v,coeff) in f.iteritems() if coeff != 0])
     1005              c = f[i]
     1006              C = [(v,coeff/c) for (v,coeff) in f.iteritems() if v != -1]
     1007              if c > 0:
     1008                min = min/c if min != None else None
     1009                max = max/c if max != None else None
     1010              else:
     1011                tempmin = max/c if max != None else None
     1012                tempmax = min/c if min != None else None
     1013                min, max = tempmin, tempmax
     1014              if (tuple(C),min,max) in self._constraints:
     1015                return None
     1016              else:
     1017                self._constraints.add((tuple(C),min,max))
     1018            else:
     1019              C = [(v,coeff) for (v,coeff) in f.iteritems() if v != -1]
    9461020
    9471021            if min == None and max == None:
    9481022                raise ValueError("Both max and min are set to None ? Weird!")