Changeset 2170


Ignore:
Timestamp:
Jan 25, 2010 6:35:49 PM (10 years ago)
Author:
wehart
Message:

A rework of the NL/LP file writers. This now uses the
canonical expression representation. I'm pretty sure that the LP writer
is OK, but much less sure about the NL writer. Also, it's clear that we don't
have adequate tests of the writers to ensure that all different types of
models are written correctly.

Location:
coopr.pyomo/trunk/coopr/pyomo
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • coopr.pyomo/trunk/coopr/pyomo/base/constraint.py

    r2125 r2170  
    7979        self.sense = tmpsense
    8080        self.rule = tmprule
     81        self.trivial=False
    8182
    8283    def clear(self):
     
    239240            self._data[None].name=tmpname
    240241        self.rule = tmprule
     242        self.trivial=False
    241243
    242244    def clear(self):
  • coopr.pyomo/trunk/coopr/pyomo/expr/canonical_repn.py

    r2108 r2170  
    99#  _________________________________________________________________________
    1010
    11 __all__ = ['generate_canonical_repn', 'as_expr']
     11__all__ = ['generate_canonical_repn', 'as_expr', 'is_constant', 'is_linear', 'is_quadratic', 'is_nonlinear']
    1212
    1313import pyutilib.plugin.core
    1414from coopr.pyomo.base import IPyomoPresolver, IPyomoPresolveAction, Model
    1515from coopr.pyomo.base import expr
    16 from coopr.pyomo.base.var import _VarValue
     16from coopr.pyomo.base.var import _VarValue, Var
    1717import copy
    1818
     19
     20#
     21# A frozen dictionary that can be hashed.  This dictionary isn't _really_
     22# frozen, but it acts hashable.
     23#
    1924class frozendict(dict):
    2025    __slots__ = ('_hash',)
     
    2429            rval = self._hash = hash(frozenset(self.iteritems()))
    2530        return rval
     31
    2632
    2733
     
    118124
    119125#
    120 # The canonical representation is a dictionary.  Each element is a mapping
    121 # from a term degree to terms in the expression.  If the term degree is
    122 # None, then the map value is simply an expression of terms without a
    123 # specific degree.  Otherwise, the map value is a dictionary of terms to
    124 # their coefficients.  A term is represented as a frozen dictionary that
    125 # maps variable id to variable power.  A constant term is represented
    126 # with None.
    127 #
    128 # Examples:
    129 #  Let x[1] ... x[4] be the first 4 variables, and
    130 #      y[1] ... y[4] be the next 4 variables
    131 #
    132 # 1.3                           {0:{ None :1.3}}
    133 # 3.2*x[1]                      {1:{ {0:1} :3.2}}
    134 # 2*x[1]*y[2] + 3*x[2] + 4      {0:{None:4.0}, 1:{{1:1}:3.0}, 2:{{0:1, 5:1}:2.0}}
    135 # log(y[1]) + x[1]*x[1]         {2:{{0:2}:1.0}, None:log(y[1])}
     126# Temporary canonical expressions
    136127#
    137128temp_const = { 0: {None:0.0} }   
     
    139130temp_nonl = { None: None }   
    140131
    141 
     132#
     133# Internal function for collecting canonical representation, which is
     134# called recursively.
     135#
    142136def collect_canonical_repn(exp, model):
    143     #ans = do_collect_canonical_repn(exp, model)
    144     #exp.pprint()
    145     #print "HERE",ans
    146     #return ans
    147     #def do_collect_canonical_repn(exp, model):
    148 
    149137    global temp_const
    150138    global temp_var
     
    225213
    226214#
    227 # This function generates a canonical representation for a Pyomo expression
     215# Generate a canonical representation of an expression.
     216#
     217# The canonical representation is a dictionary.  Each element is a mapping
     218# from a term degree to terms in the expression.  If the term degree is
     219# None, then the map value is simply an expression of terms without a
     220# specific degree.  Otherwise, the map value is a dictionary of terms to
     221# their coefficients.  A term is represented as a frozen dictionary that
     222# maps variable id to variable power.  A constant term is represented
     223# with None.
     224#
     225# Examples:
     226#  Let x[1] ... x[4] be the first 4 variables, and
     227#      y[1] ... y[4] be the next 4 variables
     228#
     229# 1.3                           {0:{ None :1.3}}
     230# 3.2*x[1]                      {1:{ {0:1} :3.2}}
     231# 2*x[1]*y[2] + 3*x[2] + 4      {0:{None:4.0}, 1:{{1:1}:3.0}, 2:{{0:1, 5:1}:2.0}}
     232# log(y[1]) + x[1]*x[1]         {2:{{0:2}:1.0}, None:log(y[1])}
    228233#
    229234def generate_canonical_repn(expr, model):
    230235    return collect_canonical_repn(expr, model)
    231236
     237def is_constant(repn):
     238    """Return True if the canonical representation is a constant expression"""
     239    return (0 in repn) and (len(repn) == 1)
     240
     241def is_nonlinear(repn):
     242    """Return True if the canonical representation is a nonlinear expression"""
     243    for key in repn:
     244        if not key in [0,1]:
     245            return True
     246    return False
     247
     248def is_linear(repn):
     249    """Return True if the canonical representation is a linear expression."""
     250    return (1 in repn) and not is_nonlinear(repn)
     251
     252def is_quadratic(repn):
     253    """Return True if the canonical representation is a quadratic expression."""
     254    if not 2 in repn:
     255        return False
     256    for key in repn:
     257        if key is None or key > 2:
     258            return False
     259    return True
     260
  • coopr.pyomo/trunk/coopr/pyomo/io/ampl.py

    r2160 r2170  
    5959        Con = model.active_components(Constraint)
    6060        Vars = model.active_components(Var)
    61         Onontriv = model.Onontriv
    62         for obj in Onontriv:
    63                 O = Obj[obj]
    64                 no += len(O._Onz)
    65         Cnontriv = model.Cnontriv
    66         for con in Cnontriv:
    67                 C = Con[con]
    68                 nc += len(C._Cnz)
    69                 for i in C._Cnz:
    70                   if C[i].lower is not None:
    71                            L = self._get_bound(C[i].lower)
    72                            if C[i].upper is not None:
    73                                     U = self._get_bound(C[i].upper)
    74                                     if (L == U):
    75                                              neqn += 1
    76                                     elif L > U:
    77                                              raise ValueError, "Constraint " + str(con) +\
     61        #
     62        # Count number of objectives
     63        #
     64        for obj in Obj:
     65            if Obj[obj].trivial:
     66                continue
     67            for i in Obj[obj]:
     68                if not is_constant(Obj[obj][i].repn):
     69                    no += 1
     70        #
     71        # Count number of constraints
     72        #
     73        for con in Con:
     74            C = Con[con]
     75            if C.trivial:
     76                continue
     77            for i in C:
     78                if is_constant(C[i].repn):
     79                    continue
     80                nc += 1
     81                if C[i].lower is not None:
     82                    L = self._get_bound(C[i].lower) if C[i].lower is not None else -inf
     83                    U = self._get_bound(C[i].upper) if C[i].upper is not None else inf
     84                    if (L == U):
     85                        neqn += 1
     86                elif L > U:
     87                    raise ValueError, "Constraint " + str(con) +\
    7888                                             "[" + str(i) + "]: lower bound = " + str(L) +\
    7989                                             " > upper bound = " + str(U)
    80                                     else:
    81                                              nrange += 1
    82 
     90                elif C[i].lower is not None and C[i].upper is not None:
     91                    nrange += 1
     92        #
    8393        icv = 0
    8494        Ilist = []
     
    167177        nsno = model.statistics.number_of_variables
    168178        ngc = ngo = 0
     179        # Compute # of nonzeros in gradient
    169180        for key in Obj:
    170                 for obj in Obj[key]._linterm:
    171                     ngo += len(Obj[key]._linterm[obj])
     181            if Obj[key].trivial:
     182                continue
     183            for ondx in Obj[key]:
     184                ngo += len(Obj[key][ondx].repn.get(1,{}))
     185        # Compute # of nonzeros in Jacobian
    172186        cu = {}
    173187        for i in xrange(nsno):
    174188                cu[i] = 0
    175         #Con = model.components(Constraint)
    176         for key in Cnontriv:
    177                 C = Con[key]
    178                 for cndx in C._Cnz:
    179                   LT = C._linterm[cndx]
     189        for key in Con:
     190            C = Con[key]
     191            if C.trivial:
     192                continue
     193            for cndx in C:
     194                for d in C[cndx].repn.get(1,{}):
     195                    ngc += 1
     196                    cu[d.keys()[0]] += 1
     197                  #LT = C._linterm[cndx]
    180198                  #print "HERE",LT.keys()
    181                   for i in LT:
     199                  #for i in LT:
    182200                           #print "HERE",i,type(LT[i]),LT[i],type(LT[i][1]),LT[i][1]
    183                            if i != '0':
    184                               ngc += 1
    185                               cu[LT[i][1].id] += 1
     201                           #if i != '0':
     202                              #ngc += 1
     203                              #cu[LT[i][1].id] += 1
    186204        print >>OUTPUT, " " + str(ngc), str(ngo) + "\t# nonzeros in Jacobian, gradients"
    187205        #
     
    197215        #
    198216        nc = 0
    199         for key in Cnontriv:
    200                 for cndx in Con[key]._Cnz:
    201                   print >>OUTPUT, "C" + str(nc) + "\t#" + str(key) + "[" + str(cndx) + "]"
    202                   nc += 1
    203                   #if '0' in Con[key]._linterm[cndx]:
    204                   #  print >>OUTPUT, "n"+str(Con[key]._linterm[cndx]['0'][0])
    205                   #else:
    206                   #  print >>OUTPUT, "n0"
    207                   print >>OUTPUT, "n0"
     217        for key in Con:
     218            if Con[key].trivial:
     219                continue
     220            for ndx in Con[key]:
     221                if is_constant(Con[key][ndx].repn):
     222                    continue
     223                print >>OUTPUT, "C" + str(nc) + "\t#" + str(key) + "[" + str(ndx) + "]"
     224                nc += 1
     225                print >>OUTPUT, "n0"
    208226        #
    209227        # "O" lines
    210228        #
    211229        no = 0
    212         for key in Obj.keys():
    213                 k = 0
    214                 if Obj[key].sense == maximize:
    215                         k = 1
    216                 for cndx in Obj[key]._Onz:
    217                   print >>OUTPUT, "O" + str(no) + " "+str(k)+"\t#" + str(key) + "[" + str(cndx) + "]"
    218                   no += 1
    219                   LT = Obj[key]._linterm[cndx]
    220                   if "0" in LT:
    221                         print >>OUTPUT, "n" + str(LT["0"][0])
    222                   else:
    223                         print >>OUTPUT, "n0"
     230        for key in Obj:
     231            k = 0
     232            if Obj[key].sense == maximize:
     233                k = 1
     234            for ndx in Obj[key]:
     235                if is_constant(Obj[key][ndx].repn):
     236                    continue
     237                print >>OUTPUT, "O" + str(no) + " "+str(k)+"\t#" + str(key) + "[" + str(ndx) + "]"
     238                no += 1
     239                if 0 in Obj[key][ndx].repn:
     240                    print >>OUTPUT, "n" + str(Obj[key][ndx].repn[0][None])
     241                else:
     242                    print >>OUTPUT, "n0"
    224243        #
    225244        # "r" lines
     
    227246        print >>OUTPUT, "r"
    228247        nc=0
    229         for key in Cnontriv:
    230                 C = Con[key]
    231                 for cndx in C._Cnz:
    232                   if '0' in Con[key]._linterm[cndx]:
    233                         offset=Con[key]._linterm[cndx]['0'][0]
    234                   else:
    235                         offset=0
    236                   if C[cndx]._equality:
    237                            print >>OUTPUT, "4", self._get_bound(C[cndx].lower)-offset,
    238                   else:
    239                            if C[cndx].lower is None:
    240                                     if C[cndx].upper is None:
    241                                              print >>OUTPUT,"3",
    242                                     else:
    243                                              print >>OUTPUT,"1", self._get_bound(C[cndx].upper)-offset,
    244                            else:
    245                                     if C[cndx].upper is None:
    246                                              print >>OUTPUT,"2", self._get_bound(C[cndx].lower)-offset,
    247                                     else:
    248                                              print >>OUTPUT,"0",\
    249                                                       self._get_bound(C[cndx].lower)-offset,\
    250                                                       self._get_bound(C[cndx].upper)-offset,
    251                   print >>OUTPUT, " # c"+ str(nc)+"  "+str(key) + "[" + str(cndx) + "]"
    252                   symbol_map["c" + str(nc)] = str(key) + "[" + str(cndx) + "]"
    253                   nc += 1
     248        for key in Con:
     249            if Con[key].trivial:
     250                continue
     251            C = Con[key]
     252            for ndx in C:
     253                if is_constant(C[ndx].repn):
     254                    continue
     255                if 0 in C[ndx].repn:
     256                    offset=C[ndx].repn[0][None]
     257                else:
     258                    offset=0
     259                if C[ndx]._equality:
     260                    print >>OUTPUT, "4", self._get_bound(C[ndx].lower)-offset,
     261                else:
     262                    if C[ndx].lower is None:
     263                        if C[ndx].upper is None:
     264                            print >>OUTPUT,"3",
     265                        else:
     266                            print >>OUTPUT,"1", self._get_bound(C[ndx].upper)-offset,
     267                    else:
     268                        if C[ndx].upper is None:
     269                            print >>OUTPUT,"2", self._get_bound(C[ndx].lower)-offset,
     270                        else:
     271                            print >>OUTPUT,"0",\
     272                                    self._get_bound(C[ndx].lower)-offset,\
     273                                    self._get_bound(C[ndx].upper)-offset,
     274                print >>OUTPUT, " # c"+ str(nc)+"  "+str(key) + "[" + str(ndx) + "]"
     275                symbol_map["c" + str(nc)] = str(key) + "[" + str(ndx) + "]"
     276                nc += 1
    254277        #
    255278        # "b" lines
     
    304327        #
    305328        nc = 0
    306         for key in Cnontriv:
    307                 C = Con[key]
    308                 for cndx in C._Cnz:
    309                   LT = C._linterm[cndx]
    310                   LT_len = len(LT) - ('0' in LT)
    311                   print >>OUTPUT, "J" + str(nc), LT_len
    312                   nc += 1
    313                   for x in LT:
    314                            if x != '0':
    315                               p = LT[x]
    316                               print >>OUTPUT, p[1].id, p[0]
     329        for key in Con:
     330            if Con[key].trivial:
     331                continue
     332            con = Con[key]
     333            for ndx in con:
     334                if is_constant(con[ndx].repn):
     335                    continue
     336                linear = con[ndx].repn.get(1,{})
     337                for id in linear:
     338                    print >>OUTPUT, id, linear[id]
     339                #LT = C._linterm[cndx]
     340                #LT_len = len(LT) - ('0' in LT)
     341                #print >>OUTPUT, "J" + str(nc), LT_len
     342                #nc += 1
     343                #for x in LT:
     344                    #if x != '0':
     345                        #p = LT[x]
     346                        #print >>OUTPUT, p[1].id, p[0]
    317347        #
    318348        # "G" lines
     
    320350        no = 0
    321351        for key in Obj:
    322                 OLT = Obj[key]._linterm
    323                 Ng = 0
    324                 for j in OLT:
    325                         Ng += len(OLT[j])
    326                 print >>OUTPUT, "G" + str(no), Ng
     352            if Obj[key].trivial:
     353                continue
     354            obj = Obj[key]
     355            for ndx in obj:
     356                linear = obj[ndx].repn.get(1,{})
     357                print >>OUTPUT, "G" + str(no), len(linear)
    327358                no += 1
    328                 for j in OLT:
    329                         LT = OLT[j]
    330                         for x in LT:
    331                                 if x != '0':
    332                                    p = LT[x]
    333                                    print >>OUTPUT, p[1].id, p[0]
     359                for id in linear:
     360                    print >>OUTPUT, id, linear[id]
     361                #for j in OLT:
     362                    #LT = OLT[j]
     363                    #for x in LT:
     364                        #if x != '0':
     365                            #p = LT[x]
     366                            #print >>OUTPUT, p[1].id, p[0]
    334367
    335368        return symbol_map
  • coopr.pyomo/trunk/coopr/pyomo/io/cpxlp.py

    r2028 r2170  
    2121from coopr.pyomo.base import *
    2222from coopr.opt.base import problem, AbstractProblemWriter
     23from coopr.pyomo.expr import *
     24import math
    2325
    2426def convert_name(namestr):
     
    8789        return a[0]
    8890
    89     def _print_linterm(self, x, OUTPUT, print_mult=True, cleanup_names=False, print_offset=False):
    90         if len(x) <= 0:
    91            raise ValueError, "ERROR: zero-length value in _print_linterm"
    92         # x maps variable labels to (numeric-coefficient, _VarValue) pairs.
    93         # y will consist of pairs of variable names and their corresponding coefficients,
    94         # basically just stripping out the "_VarValue" component of the input x.       
    95         y = []
    96         for i in x.keys():
    97            output_label = i
    98            if (self._output_prefixes is True) and (isinstance(x[i][1], _VarValue) is True):
    99               parent_model = x[i][1].var.model
    100               if parent_model is None:
    101                  raise ValueError, "Variable="+x[i][1].var.name+" has no parent model defined - required when outputting LP files when _output_prefixes is enabled"
    102               output_label = parent_model.name + "_" + output_label
    103            y.append((output_label,x[i][0]))
    104         y = sorted(y, key=self._collect_key)
    105 #        print "_print_linterm x: ",x
    106 #        print "_print_linterm y: ",y
    107         op = None
    108         offset=0.0
     91    def _print_expr(self, model, x, OUTPUT, print_offset=False):
    10992        max_terms_on_line=5 # this is the line-limit hack
    11093        terms_output = 0
    111         for i in y:
    112                   c = i[1]
    113                   if op != None:
    114                            if c < 0:
    115                                     c = -c
    116                                     op = "-"
    117                            print >>OUTPUT, op,
    118                   if i[0] == "0":
    119                      # a key equal to "0" indicates the offset
    120                      if print_offset:
    121                         print >>OUTPUT, c, "ONE_VAR_CONSTANT"
    122                         terms_output += 1
    123                         op = "+"
    124                      else:
    125                         offset = c
    126                         op = None
    127                   else:
    128                      print >>OUTPUT, c,
    129                      print >>OUTPUT, convert_name(i[0]),
    130                      terms_output += 1
    131                      if terms_output >= max_terms_on_line:
    132                         print >>OUTPUT, ""
    133                         terms_output = 0
    134                      op = "+"
     94        #
     95        # Linear
     96        #
     97        if 1 in x:
     98            keys = x[1].keys()
     99            keys.sort()
     100            for id in keys:
     101                coef = x[1][id]
     102                name = convert_name(model._var[id.keys()[0]].name)
     103                print >>OUTPUT, ('- %f' % math.fabs(coef) if coef < 0.0 else '+ %f' % coef), name,
     104                terms_output += 1
     105                if terms_output >= max_terms_on_line:
     106                    print >>OUTPUT, ""
     107                    print >>OUTPUT, "     ",
     108                    terms_output = 0
     109        #
     110        # Quadratic
     111        #
     112        if 2 in x:
     113            keys = x[2].keys()
     114            keys.sort()
     115            for id in keys:
     116                coef = x[2][id]
     117                print >>OUTPUT, ('- %f' % math.fabs(coef) if coef < 0.0 else '+ %f' % coef),
     118                for var in id:
     119                    name = convert_name(model._var[var].name)
     120                    if id[var] > 1:
     121                        print "%s^%d" % (name,id[var]),
     122                    else:
     123                        print name,
     124                terms_output += 1
     125                if terms_output >= max_terms_on_line:
     126                    print >>OUTPUT, ""
     127                    print >>OUTPUT, "     ",
     128                    terms_output = 0
     129        #
     130        # Constant offset
     131        #
     132        offset=0.0
     133        if 0 in x:
     134            offset = x[0][None]
     135        if print_offset and offset != 0.0:
     136            print >>OUTPUT, ('- %f' % math.fabs(offset) if offset < 0.0 else '+ %f' % offset), "ONE_VAR_CONSTANT"
     137            terms_output += 1
     138        #
     139        # Return constant offset
     140        #
    135141        return offset
    136 
    137     def _print_quadterm(self, x, is_minimizing, OUTPUT):
    138         # the LP format doesn't allow for expression of constant terms in the objective.
    139         # a work-around involves tracking the sum of constant terms in the quadratic
    140         # quadratic terms, and then writing that out with a dummy variable forced equal
    141         # to one.
    142         print >>OUTPUT, ""
    143         for arg in x._args:
    144             if isinstance(arg,expr._ProductExpression):
    145                 # NOTE: we need to handle quadratics defined with the 'pow' term here.
    146                 # WARNING: The following code is very specific to progressive hedging, with
    147                 #          a very specific format assumed. we do need to handle more general
    148                 #          expressions, but we'll worry about that at a latter time.
    149                 blend = arg._numerator[0]()
    150 
    151                 if blend is 1:
    152 
    153                    rho = arg._numerator[1]()
    154 
    155                    pow_expression = arg._numerator[2]
    156                
    157                    base = pow_expression._args[0]
    158                    exponent = pow_expression._args[1]
    159 
    160                    if not isinstance(base,expr._SumExpression):
    161                        raise ValueError, "Quadratic term base must be a _SumExpression"
    162                    if not isinstance(exponent,numvalue.NumericConstant):
    163                        raise ValueError, "Quadratic term exponent must be a NumericConstant"
    164                    variable = base._args[0]
    165                    offset = base._args[1]
    166                    if variable.status is not VarStatus.unused:
    167 
    168                       if is_minimizing is True:
    169                          print >>OUTPUT, " + [" + str(rho) + " " + convert_name(variable.label) + "^2]/2",
    170                       else:
    171                          print >>OUTPUT, " - [" + str(rho) + " " + convert_name(variable.label) + "^2]/2",
    172 
    173                       if (is_minimizing is True):
    174                          if offset.value < 0.0:
    175                             print >>OUTPUT, " + " + str(abs(rho*offset.value)) + " " + convert_name(variable.label),                   
    176                          else:
    177                             print >>OUTPUT, " - " + str(rho*offset.value) + " " + convert_name(variable.label),
    178                       else:
    179                          if offset.value < 0.0:
    180                             print >>OUTPUT, " - " + str(abs(rho*offset.value)) + " " + convert_name(variable.label),                   
    181                          else:
    182                             print >>OUTPUT, " + " + str(rho*offset.value) + " " + convert_name(variable.label),
    183 
    184                       objective_offset = (rho * offset.value * offset.value / 2.0)
    185                       if is_minimizing is True:
    186                          print >>OUTPUT, " + " + str(objective_offset) + " ONE_VAR_CONSTANT"
    187                       else:
    188                          print >>OUTPUT, " - " + str(objective_offset) + " ONE_VAR_CONSTANT"
    189                      
    190             elif isinstance(arg,numvalue.NumericConstant):
    191                 # this is the "0.0" element that forms the initial expression - the
    192                 # quadratic sub-expressions aren't known to the presolve routines.
    193                 # ideally unnecessary - hacked in for now.
    194                 pass
    195 
    196             else:
    197                 print `arg`
    198                 raise ValueError, "Unknown expression sub-type found in quadratic objective expression"   
    199142
    200143    def _print_model_LP(self, model, OUTPUT):
     
    206149        #
    207150        if self._output_objectives is True:
    208            printed_quadterm = False
     151           #printed_quadterm = False
    209152           if len(_obj) == 0:
    210153              raise ValueError, "ERROR: No objectives defined for input model=" + str(model.name) + "; cannot write legal LP file"
     
    215158           print >>OUTPUT, "obj: ",
    216159           obj = _obj[ _obj.keys()[0] ]
    217            for key in obj._linterm:
    218                 if (len(obj._linterm[key]) == 0) or ((len(obj._linterm[key]) == 1) and (obj._linterm[key].keys()[0] == "0")):
     160           for key in obj:
     161                if is_constant(obj[key].repn):
     162                    print "WARNING: ignoring objective %s[%s] which is constant" % (str(obj),str(key))
    219163                    continue
    220                 self._print_linterm(obj._linterm[key], OUTPUT, print_mult=False, cleanup_names=True, print_offset=True)
    221            if obj._quad_subexpr is not None:
    222                self._print_quadterm(obj._quad_subexpr, (_obj[ _obj.keys()[0] ].sense == minimize), OUTPUT)
    223                printed_quadterm = True
     164                if is_nonlinear(obj[key].repn) and not is_quadratic(obj[key].repn):
     165                    raise ValueError, "Cannot write legal LP file.  Objective %s[%s] has nonlinear terms that are not quadratic." % (str(obj),str(key))
     166                self._print_expr(model, obj[key].repn, OUTPUT, print_offset=True)
    224167           print >>OUTPUT, ""
    225168       
    226169        #
    227170        # Constraints
    228         #
    229         # the "Cnontriv" attribute of the model is created on-the-fly, by the _Collect method in problem_utils.py.
    230171        #
    231172        # if there are no non-trivial constraints, you'll end up with an empty constraint block. CPLEX is OK with
     
    243184           
    244185           CON = model.active_components(Constraint)
    245            for key in model.Cnontriv:
     186           have_nontrivial=False
     187           for key in CON:
     188             if CON[key].trivial:
     189                continue
     190             have_nontrivial=True
    246191             i=0
    247192             C = CON[key]
    248              for cndx in C.keys():
     193             for cndx in C:
    249194               if not C[cndx].active:
    250195                    continue
    251196               try:
    252                   # there are conditions, e.g., when fixing variables, under which a constraint block might be empty.
    253                   # ignore these, for both practical reasons and the fact that the CPLEX LP format requires a variable
    254                   # in the constraint body. it is also possible that the body of the constraint consists of only a
    255                   # constant, in which case the "variable" of
    256                   if (len(C._linterm[cndx]) > 1) or ((len(C._linterm[cndx]) == 1) and (C._linterm[cndx].keys()[0] != "0")):
    257                      prefix = ""
    258                      if self._output_prefixes is True:
     197                    # there are conditions, e.g., when fixing variables, under which a constraint block might be empty.
     198                    # ignore these, for both practical reasons and the fact that the CPLEX LP format requires a variable
     199                    # in the constraint body. it is also possible that the body of the constraint consists of only a
     200                    # constant, in which case the "variable" of
     201                    if is_constant(C[cndx].repn):
     202                        print "WARNING: ignoring constraint %s[%s] which is constant" % (str(C),str(cndx))
     203                        continue
     204                    if is_nonlinear(C[cndx].repn):
     205                        raise ValueError, "Cannot write legal LP file.  Constraint %s[%s] has a body with nonlinear terms." % (str(C),str(cndx))
     206                    prefix = ""
     207                    if self._output_prefixes is True:
    259208                        if C.model is None:
    260209                           raise RuntimeError, "Constraint="+C._data[cndx].label+" has no model attribute - no label prefix can be assigned"
    261210                        prefix = C.model.name+"_"
    262211
    263                      if C._data[cndx]._equality:
     212                    if C._data[cndx]._equality:
    264213                         #
    265214                         # Equality constraint
    266215                         #
    267216                         print >>OUTPUT, prefix + "c_e_" + convert_name(C._data[cndx].label) + "_: ",
    268                          offset = self._print_linterm(C._linterm[cndx], OUTPUT, print_mult=False, cleanup_names=True)
     217                         offset = self._print_expr(model, C[cndx].repn, OUTPUT)
    269218                         print >>OUTPUT, "=",
    270219                         self._print_bound(C._data[cndx].lower, OUTPUT, -offset)
    271220                         print >>OUTPUT, ""
    272221                         i=i+1
    273                      else:
     222                    else:
    274223                         #
    275224                         # Inequality constraint
     
    277226                         if C._data[cndx].lower is not None:
    278227                            print >>OUTPUT, prefix + "c_l_" + convert_name(C._data[cndx].label) + "_: ",
    279                             offset = self._print_linterm(C._linterm[cndx], OUTPUT, print_mult=False, cleanup_names=True)
     228                            offset = self._print_expr(model, C[cndx].repn, OUTPUT)
    280229                            print >>OUTPUT, ">=",
    281230                            self._print_bound(C._data[cndx].lower, OUTPUT, -offset)
     
    284233                         if C._data[cndx].upper is not None:
    285234                            print >>OUTPUT, prefix + "c_u_" + convert_name(C._data[cndx].label) + "_: ",
    286                             offset = self._print_linterm(C._linterm[cndx], OUTPUT, print_mult=False, cleanup_names=True)
     235                            offset = self._print_expr(model, C[cndx].repn, OUTPUT)
    287236                            print >>OUTPUT, "<=",
    288237                            self._print_bound(C._data[cndx].upper, OUTPUT, -offset)
     
    292241                  print msg
    293242                  raise ValueError, "ERROR: Failed to output constraint="+C.name+", index="+`cndx`+" in generation of LP format file"
    294            if len(model.Cnontriv) == 0:
     243           if not have_nontrivial:
    295244             print "WARNING: Empty constraint block written in LP format - solver may error"
    296245         
  • coopr.pyomo/trunk/coopr/pyomo/presolve/__init__.py

    r1420 r2170  
    1616import generic_varlabels
    1717#import numeric_varlabels
    18 import collect_linear_terms
     18#import collect_linear_terms
     19import compute_canonical_repn
    1920import simple_presolver
  • coopr.pyomo/trunk/coopr/pyomo/presolve/simple_presolver.py

    r1768 r2170  
    4949        self._initialize()
    5050        tmp = self.actions.service(action)
     51        if tmp is None:
     52            raise ValueError, "Cannot activate unknown action %s" % action
    5153        self.active_actions.add(action)
    5254        if rank is None:
  • coopr.pyomo/trunk/coopr/pyomo/scripting/pyomo.py

    r2160 r2170  
    202202    if options.save_model or options.only_instance:
    203203        return Container(instance=instance)
    204     results = util.apply_optimizer(options, instance)
    205     if not util.process_results(options, instance, results):
     204    results, opt = util.apply_optimizer(options, instance)
     205    if not util.process_results(options, instance, results, opt):
    206206        return Container(instance=instance, results=results) #pragma:nocover
    207207    util.apply_postprocessing(options, instance, results)
  • coopr.pyomo/trunk/coopr/pyomo/scripting/util.py

    r2160 r2170  
    222222    if results == None:
    223223            raise ValueError, "opt.solve returned None"
    224     return results
     224    return results, opt
    225225
    226226#
    227227# Process results
    228228#
    229 def process_results(options, instance, results):
     229def process_results(options, instance, results, opt):
    230230   
    231231    if options.log:
  • coopr.pyomo/trunk/coopr/pyomo/tests/expr/test_canonical.py

    r2056 r2170  
    4545        #PluginGlobals.pprint()
    4646        self.plugin = SimplePresolver()
    47         self.plugin.deactivate_action("collect_linear_terms")
     47        self.plugin.deactivate_action("compute_canonical_repn")
    4848
    4949    def tearDown(self):
     
    5151           os.unlink("unknown.lp")
    5252        pyutilib.services.TempfileManager.clear_tempfiles()
    53         self.plugin.activate_action("collect_linear_terms")
     53        self.plugin.activate_action("compute_canonical_repn")
    5454
    5555    def test_expr1(self):
Note: See TracChangeset for help on using the changeset viewer.