Ticket #11606: trac_11606_add_only_new_constraints_to_lp.patch

File trac_11606_add_only_new_constraints_to_lp.patch, 4.4 KB (added by john_perry, 10 years ago)
  • sage/numerical/mip.pyx

    # HG changeset patch
    # User John Perry <john.perry@usm.edu>
    # Date 1314085617 25200
    # Node ID b3a05353a75602f25fbad1d4022328c3d357feec
    # Parent  361a4ad7d52c69b64ae2e658ffd0820af0d87e93
    trace 11606: do not add obviously redundant constraints
    
    diff -r 361a4ad7d52c -r b3a05353a756 sage/numerical/mip.pyx
    a b  
    670670
    671671        self._backend.set_objective(values)
    672672           
    673     def add_constraint(self, linear_function, max=None, min=None, name=None):
     673    def add_constraint(self, linear_function, max=None, min=None, name=None, check_redundant=False):
    674674        r"""
    675675        Adds a constraint to self.
    676676
     
    687687        - ``min`` -- A lower bound on the constraint.  This must be a
    688688          numerical value.
    689689        - ``name`` -- A name for the constraint.
     690        - ``check_redundant`` -- whether to check that the constraint is redundant with another constraint already in the program
    690691
    691692        EXAMPLE:
    692693
     
    773774            Traceback (most recent call last):
    774775            ...
    775776            ValueError: min and max arguments are required to be numerical
    776 
     777       
     778        Do not add redundant elements (notice only one copy of each constraint is added)::
     779       
     780            sage: lp = MixedIntegerLinearProgram()
     781            sage: for each in xrange(10): lp.add_constraint(lp[0]-lp[1],min=1,check_redundant=True)
     782            sage: lp.show()
     783            Maximization:
     784            <BLANKLINE>
     785            Constraints:
     786              1.0 <= x_0 -x_1
     787            Variables:
     788              x_0 is a continuous variable (min=0.0, max=+oo)
     789              x_1 is a continuous variable (min=0.0, max=+oo)
     790             
     791        We check for constant multiples of constraints as well:
     792       
     793            sage: for each in xrange(10): lp.add_constraint(2*lp[0]-2*lp[1],min=2,check_redundant=True)
     794            sage: lp.show()
     795            Maximization:
     796            <BLANKLINE>
     797            Constraints:
     798              1.0 <= x_0 -x_1
     799            Variables:
     800              x_0 is a continuous variable (min=0.0, max=+oo)
     801              x_1 is a continuous variable (min=0.0, max=+oo)
     802       
     803        But if the constant multiple is negative, we should add anyway:
     804       
     805              sage: for each in xrange(10): lp.add_constraint(-2*lp[0]+2*lp[1],min=-2,check_redundant=True)
     806              sage: lp.show()
     807              Maximization:
     808              <BLANKLINE>
     809              Constraints:
     810                1.0 <= x_0 -x_1
     811                -2.0 <= -2.0 x_0 +2.0 x_1
     812              Variables:
     813                x_0 is a continuous variable (min=0.0, max=+oo)
     814                x_1 is a continuous variable (min=0.0, max=+oo)
     815       
    777816        """
    778817        if linear_function is None or linear_function is 0:
    779818            return None
     
    785824
    786825            raise ValueError("min and max arguments are required to be numerical")
    787826
     827        cdef GenericBackend b
     828        cdef int i, j, found, row_good
     829        cdef float ratio
     830       
    788831        if isinstance(linear_function, LinearFunction):
    789832
    790833            f = linear_function.dict()
     
    802845
    803846            if min == None and max == None:
    804847                raise ValueError("Both max and min are set to None ? Weird!")
     848           
     849            if check_redundant:
     850                b = self._backend
     851                i = 0
     852                found = 0
     853                while not found and i < b.nrows():
     854                    bi = b.row(i)
     855                    lb, ub = b.row_bounds(i)
     856                    if set(bi[0]) == set(f.keys()):
     857                        ratio = bi[1][0] / f[bi[0][0]]
     858                        if ratio > 0.0 \
     859                                and ((lb == None and min == None) or (lb != None and min != None and lb / min == ratio)) \
     860                                and ((ub == None and max == None) or (ub != None and max != None and ub / max == ratio)):
     861                            row_good = 1
     862                            j = 1
     863                            while row_good and j < len(bi[0]):
     864                                if ratio != bi[1][j] / f[bi[0][j]]:
     865                                    row_good = 0
     866                                j += 1
     867                            if row_good:
     868                                return None
     869                    i += 1
    805870
    806871            self._backend.add_linear_constraint(C, min, max, name)
    807872