Changeset 2314


Ignore:
Timestamp:
Feb 11, 2010 11:32:01 AM (10 years ago)
Author:
wehart
Message:

Merged revisions 2232-2313 via svnmerge from
https://software.sandia.gov/svn/public/coopr/coopr.plugins/trunk

........

r2238 | wehart | 2010-02-01 19:44:17 -0700 (Mon, 01 Feb 2010) | 2 lines


Update of changelog.

........

r2240 | wehart | 2010-02-01 19:47:16 -0700 (Mon, 01 Feb 2010) | 2 lines


Tagging the coopr.plugins 2.3 release

........

r2252 | wehart | 2010-02-03 13:57:01 -0700 (Wed, 03 Feb 2010) | 2 lines


Changes due to termination condition refinement

........

r2265 | wehart | 2010-02-05 08:23:35 -0700 (Fri, 05 Feb 2010) | 3 lines


Extending the Pyomo converter to allow the conversion of both Pyomo Model objects
as well as Python modules that contain a Model definition.

........

r2266 | wehart | 2010-02-05 10:59:43 -0700 (Fri, 05 Feb 2010) | 7 lines


Adding an AMPL converter, which runs AMPL to convert *.mod files to *.nl (or *.mps).
This is needed because the current glpsol convert cannot handle nonlinear problems.


NOTE: this plugin will not gracefully handle situtations where the AMPL license
is already in use. I don't have access to a regular AMPL
installation to test this case.

........

r2281 | jwatson | 2010-02-08 11:26:54 -0700 (Mon, 08 Feb 2010) | 1 line


Adding a suffixes attribute to the base solver class. This is a list of suffixes that the solver will - assuming it can - load into a solution. Examples are rc, dual, slack, etc. I modified the derived solver plugin classes to throw an exception if provided a suffix that it can't handle. I have little doubt that this change will cause some tests to fail - I'll look at this in a bit. The change was motivated by the expense of querying a solution, loading a solution, and shipping a lot of unnecessary information across the network.

........

r2284 | jwatson | 2010-02-08 11:42:15 -0700 (Mon, 08 Feb 2010) | 3 lines


Fix to CPLEX plugin relating to suffix processing - working on a laptop, and couldn't test fully!

........

r2308 | wehart | 2010-02-10 20:29:42 -0700 (Wed, 10 Feb 2010) | 6 lines


Generalizing the suffix management in the MIP solvers so
they match regular expressions for suffixes. This allows
the user to specify the '.*' suffix, which matches everything.


Reworked the MIP tests, which all pass now.

........

Location:
coopr.plugins/stable/2.3
Files:
27 edited
3 copied

Legend:

Unmodified
Added
Removed
  • coopr.plugins/stable/2.3

  • coopr.plugins/stable/2.3/coopr/plugins/converter/__init__.py

    r2201 r2314  
    1212pyutilib.component.core.PluginGlobals.push_env( 'coopr.opt' )
    1313
     14import ampl
    1415import glpsol
    1516import pico
  • coopr.plugins/stable/2.3/coopr/plugins/converter/glpsol.py

    r2201 r2314  
    1818import pyutilib.subprocess
    1919import pyutilib.common
     20
    2021
    2122class GlpsolMIPConverter(ManagedSingletonPlugin):
  • coopr.plugins/stable/2.3/coopr/plugins/converter/pico.py

    r2201 r2314  
    1919import pyutilib.common
    2020import pyutilib.subprocess
     21
    2122
    2223class PicoMIPConverter(ManagedSingletonPlugin):
     
    4849            return True
    4950        return False
     51
     52    def available(self):
     53        cmd = self.executable.service("pico_convert")
     54        return not cmd is None
    5055
    5156    def apply(self, *args):
  • coopr.plugins/stable/2.3/coopr/plugins/converter/pyomo.py

    r2201 r2314  
    1212__all__ = ['PyomoMIPConverter']
    1313
     14import coopr.pyomo
    1415from coopr.opt.base import *
    1516from pico import PicoMIPConverter
     
    1920from pyutilib.component.executables import *
    2021import pyutilib.services
     22
    2123
    2224class PyomoMIPConverter(ManagedSingletonPlugin):
     
    3941        if from_type == ProblemFormat.pyomo and to_type == ProblemFormat.cpxlp:
    4042            return True
    41         if from_type == ProblemFormat.pyomo and to_type == ProblemFormat.mps:
     43        if self.pico_converter.available() and from_type == ProblemFormat.pyomo and to_type == ProblemFormat.mps:
    4244            return True
    4345        return False
     
    4951        """
    5052
     53        if isinstance(args[2], basestring):
     54            instance = None
     55        else:
     56            instance = args[2]
     57        #elif isinstance(args[2], coopr.pyomo.Model):
     58            #instance = args[2]
     59        #else:
     60            #raise IOError, "Bad data type for conversion: %s" % str(type(args[2]))
     61
    5162        if args[1] is ProblemFormat.cpxlp:
    5263            problem_filename = pyutilib.services.TempfileManager.create_tempfile(suffix = '.pyomo.lp')
    53             (problem_filename, varmap) = args[2].write(filename=problem_filename,format=ProblemFormat.cpxlp)
    54             return (problem_filename,),None # no map file is necessary
    55         elif args[1] is ProblemFormat.mps:
     64            if instance:
     65                (problem_filename, varmap) = instance.write(filename=problem_filename,format=ProblemFormat.cpxlp)
     66                return (problem_filename,),None # no map file is necessary
     67            else:
     68                model = coopr.pyomo.scripting.pyomo2lp(['--save-model',problem_filename,args[2]])
     69                return (model.filename,),model.symbol_map
     70
     71        elif args[1] in [ProblemFormat.mps, ProblemFormat.nl]:
     72            problem_filename = pyutilib.services.TempfileManager.create_tempfile(suffix = '.pyomo.nl')
     73            if instance:
     74                (problem_filename, varmap) = instance.write(filename=problem_filename,format=ProblemFormat.nl)
     75            else:
     76                model = coopr.pyomo.scripting.pyomo2nl(['--save-model',problem_filename,args[2]])
     77                problem_filename = model.filename
     78                varmap = model.symbol_map
     79            if args[1] is ProblemFormat.nl:
     80                return (problem_filename,),varmap
     81            #
     82            # Convert from NL to MPS
     83            #
    5684            # TBD: We don't support a variable map file when going from NL to MPS within the PICO converter.
    57             problem_filename = pyutilib.services.TempfileManager.create_tempfile(suffix = '.pyomo.nl')
    58             (problem_filename, varmap) = args[2].write(filename=problem_filename,format=ProblemFormat.nl)
     85            # NOTE: this is a problem with the MPS writer that is provided by COIN-OR
     86            # NOTE: we should generalize this so it doesn't strictly depend on the PICO converter utility.
     87            #
    5988            ans = self.pico_converter.apply(ProblemFormat.nl,ProblemFormat.mps,problem_filename)
    6089            os.remove(problem_filename)
    6190            return ans
    62         elif args[1] is ProblemFormat.nl:
    63             problem_filename = pyutilib.services.TempfileManager.create_tempfile(suffix = '.pyomo.nl')
    64             (problem_filename, symbol_map) = args[2].write(filename=problem_filename,format=ProblemFormat.nl)
    65             return (problem_filename,),symbol_map # map file is necessary
    6691
  • coopr.plugins/stable/2.3/coopr/plugins/mip/CBC.py

    r2201 r2314  
    257257    def process_soln_file(self,results):
    258258
     259        # the only suffixes that we extract from CBC are
     260        # constraint duals and variable reduced-costs. scan
     261        # through the solver suffix list and throw an
     262        # exception if the user has specified any others.
     263        extract_duals = False
     264        extract_reduced_costs = False
     265        for suffix in self.suffixes:
     266           flag=False
     267           if re.match(suffix, "dual"):
     268              extract_duals = True
     269              flag=True
     270           if re.match(suffix, "rc"):
     271              extract_reduced_costs = True
     272              flag=True
     273           if not flag:
     274              raise RuntimeError,"***CBC solver plugin cannot extract solution suffix="+suffix
     275
    259276        # if dealing with SOL format files, we've already read
    260277        # this via the base class reader functionality.
     
    286303                raise RuntimeError, "CBC encountered unexpected line=("+line.strip()+") in solution file="+self.soln_file+"; constraint and variable sections already processed!"
    287304
    288           if processing_constraints is True:
     305          if (processing_constraints is True) and (extract_duals is True):
    289306             constraint = tokens[1]
    290307             constraint_ax = eval(tokens[2]) # CBC reports the constraint row times the solution vector - not the slack.
     
    296313             variable_name = tokens[1]
    297314             variable_value = eval(tokens[2])
    298              variable_reduced_cost = eval(tokens[3]) # currently ignored.
    299 
    300315             solution.variable[variable_name].value = variable_value
    301              solution.variable[variable_name].rc = variable_reduced_cost
     316
     317             if extract_reduced_costs is True:
     318                variable_reduced_cost = eval(tokens[3]) # currently ignored.
     319                solution.variable[variable_name].rc = variable_reduced_cost
    302320          else:
    303321             raise RuntimeError, "CBC encountered unexpected line=("+line.strip()+") in solution file="+self.soln_file+"; expecting header, but found data!"
  • coopr.plugins/stable/2.3/coopr/plugins/mip/CPLEX.py

    r2212 r2314  
    341341
    342342    def process_soln_file(self,results):
    343         lp_solution=False
     343
     344        # the only suffixes that we extract from CPLEX are
     345        # constraint duals, constraint slacks, and variable
     346        # reduced-costs. scan through the solver suffix list
     347        # and throw an exception if the user has specified
     348        # any others.
     349        extract_duals = False
     350        extract_slacks = False
     351        extract_reduced_costs = False
     352        for suffix in self.suffixes:
     353           flag=False
     354           if re.match(suffix,"dual"):
     355                extract_duals = True
     356                flag=True
     357           if re.match(suffix,"slack"):
     358                extract_slacks = True             
     359                flag=True
     360           if re.match(suffix,"rc"):
     361                extract_reduced_costs = True
     362                flag=True
     363           if not flag:
     364              raise RuntimeError,"***CPLEX solver plugin cannot extract solution suffix="+suffix
     365
     366        lp_solution = False
    344367        if not os.path.exists(self.soln_file):
    345368           return
     
    368391                   elif field_name == "value":
    369392                      variable_value = field_value
    370                    elif field_name == "reducedCost":
     393                   elif (extract_reduced_costs is True) and (field_name == "reducedCost"):
    371394                      variable_reduced_cost = field_value
    372                    elif field_name == "status":
     395                   elif (extract_reduced_costs is True) and (field_name == "status"):
    373396                      variable_status = field_value
    374397
     
    381404                   except:
    382405                       variable.value = variable_value
    383                    if not variable_reduced_cost is None:
     406                   if (variable_reduced_cost is not None) and (extract_reduced_costs is True):
    384407                        try:
    385408                            variable.rc = eval(variable_reduced_cost)
     
    395418                        except:
    396419                            raise ValueError, "Unexpected reduced-cost value="+str(variable_reduced_cost)+" encountered for variable="+variable_name
    397             elif tokens[0] == "constraint":
     420            elif (tokens[0] == "constraint") and ((extract_duals is True) or (extract_slacks is True)):
    398421                constraint_name = None
    399422                constraint_dual = None
     
    405428                      constraint_name = field_value
    406429                      constraint = soln.constraint[constraint_name]
    407                    elif field_name == "dual": # for LPs
     430                   elif (extract_duals is True) and (field_name == "dual"): # for LPs
    408431                      # assumes the name field is first.
    409432                      if eval(field_value) != 0.0:
    410433                        constraint.dual = eval(field_value)
    411                    elif field_name == "slack": # for MIPs
     434                   elif (extract_slacks is True) and (field_name == "slack"): # for MIPs
    412435                      # assumes the name field is first.
    413436                      if eval(field_value) != 0.0:
  • coopr.plugins/stable/2.3/coopr/plugins/mip/GLPK.py

    r2201 r2314  
    213213    def process_soln_file(self,results):
    214214
     215        # the only suffixes that we extract from GLPK are
     216        # constraint duals. scan through the solver suffix
     217        # list and throw an exception if the user has
     218        # specified any others.
     219        extract_duals = False
     220        for suffix in self.suffixes:
     221            flag=False
     222            if re.match(suffix,"dual"):
     223                extract_duals = True
     224                flag=True
     225            if not flag:
     226                raise RuntimeError,"***GLPK solver plugin cannot extract solution suffix="+suffix
     227
    215228        lp_solution = True # if false, we're dealing with a MIP!
    216229        if not os.path.exists(self.soln_file):
     
    361374                   if index != number_of_constraints_read:
    362375                      raise ValueError,"***ERROR: Unexpected constraint index encountered on line="+line+"; expected value="+str(number_of_constraints_read)+"; actual value="+str(index)
    363 
     376   
    364377                if lp_solution is True:
    365378                   # GLPK doesn't report slacks directly.
     
    372385                      raise ValueError, "Unknown status="+tokens[0]+" encountered for constraint="+active_constraint_name+" in line="+line+" of solution file="+self.soln_file
    373386
    374                    soln.constraint[constraint_name].dual = constraint_dual
     387                   if extract_duals is True:
     388                      soln.constraint[constraint_name].dual = constraint_dual
    375389                 
    376390                else:
  • coopr.plugins/stable/2.3/coopr/plugins/mip/PICO.py

    r2201 r2314  
    188188
    189189    def process_soln_file(self,results):
    190         #print "HERE",self._results_format, self._results_format is ResultsFormat.sol, self.results_reader
     190
    191191        if self._results_format is ResultsFormat.sol:
    192192           return
     193
     194        # the only suffixes that we extract from PICO are
     195        # constraint duals. scan through the solver suffix
     196        # list and throw an exception if the user has
     197        # specified any others.
     198        extract_duals = False
     199        for suffix in self.suffixes:
     200           if re.match(suffix,"dual"):
     201              extract_duals = True
     202           else:
     203              raise RuntimeError,"***PICO solver plugin cannot extract solution suffix="+suffix
    193204
    194205        #if os.path.exists(self.sol_file):
     
    225236                print "ERROR", line,tokens
    226237            tmp.append( (tokens[0],eval(tokens[2])) )
    227         if lp_flag:
     238        if (lp_flag is True) and (extract_duals is True):
    228239            for (var,val) in tmp:
    229240                soln.constraint[var].dual = val
  • coopr.plugins/stable/2.3/coopr/plugins/smanager/pyro.py

    r2201 r2314  
    8787                                 file=problem_file_string, filename=self._opt._problem_files[0], \
    8888                                 warmstart_file=warm_start_file_string, warmstart_filename=warm_start_file_name, \
    89                                  kwds=kwds, solver_options=solver_options, mipgap=self._opt.mipgap)
     89                                 kwds=kwds, solver_options=solver_options, mipgap=self._opt.mipgap, suffixes=self._opt.suffixes)
    9090        task = pyutilib.pyro.Task(data=data, id=ah.id)
    9191        self.client.add_task(task)
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/diet_glpk.txt

    r2048 r2314  
    2121Solver:
    2222- Status: ok
    23   Termination condition: unsure
     23  Termination condition: unknown
    2424  Error rc: 0
    2525
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test1_cbc.txt

    r2048 r2314  
    2121Solver:
    2222- Status: ok
    23   Termination condition: unsure
     23  Termination condition: unknown
    2424  Error rc: 0
    2525
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test1_glpk.txt

    r2048 r2314  
    2121Solver:
    2222- Status: ok
    23   Termination condition: unsure
     23  Termination condition: unknown
    2424  Error rc: 0
    2525
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test1_pico.txt

    r2048 r2314  
    2222Solver:
    2323- Status: ok
    24   Termination condition: unsure
     24  Termination condition: unknown
    2525  Error rc: 0
    2626
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test2_cbc.txt

    r1991 r2314  
    2121Solver:
    2222- Status: ok
    23   Termination condition: unsure
     23  Termination condition: unknown
    2424  Statistics:
    2525    Branch and bound:
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test2_glpk.txt

    r1919 r2314  
    2020Solver:
    2121- Status: ok
    22   Termination condition: unsure
     22  Termination condition: unknown
    2323  Statistics:
    2424    Branch and bound:
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test2_pico.txt

    r1919 r2314  
    2222Solver:
    2323- Status: ok
    24   Termination condition: unsure
     24  Termination condition: unknown
    2525  Statistics:
    2626    Branch and bound:
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test4_asl.txt

    r2215 r2314  
    2020- Status: ok
    2121  Message: CPLEX 11.0.1\x3a optimal solution; objective 88.578; 1 dual simplex iterations (0 in phase I)
    22   Termination condition: unsure
     22  Termination condition: unknown
    2323  Id: 0
    2424  Error rc: 0
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test4_cbc.txt

    r2048 r2314  
    2222- Status: ok
    2323  Message: Cbc 1.04 optimal, objective 9e+01; 1 iterations
    24   Termination condition: unsure
     24  Termination condition: unknown
    2525  Id: 0
    2626  Error rc: 0
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test4_glpk.txt

    r2048 r2314  
    2020Solver:
    2121- Status: ok
    22   Termination condition: unsure
     22  Termination condition: unknown
    2323  Error rc: 0
    2424
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test4_pico.txt

    r2048 r2314  
    2222- Status: ok
    2323  Message: PICO Solver\x3a final f = 88.578000
    24   Termination condition: unsure
     24  Termination condition: unknown
    2525  Id: 0
    2626  Error rc: 0
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test_asl.py

    r2215 r2314  
    5151        else:
    5252            self.asl = coopr.plugins.mip.MockASL(keepFiles=True)
     53        self.asl.suffixes=['.*']
    5354
    5455    def tearDown(self):
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test_cbc.py

    r1939 r2314  
    4545        else:
    4646            self.cbc = coopr.plugins.mip.MockCBC(keepFiles=True)
     47        self.cbc.suffixes=['.*']
    4748
    4849    def tearDown(self):
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test_convert.py

    r2201 r2314  
    2424import xml
    2525import filecmp
     26import shutil
    2627
    2728
     
    139140        self.failUnlessFileEqualsBaseline(ans[0][0], currdir+"test3_convert.lp")
    140141
     142    def test_mod_nl1(self):
     143        """ Convert from MOD to NL """
     144        try:
     145           ans = coopr.opt.convert_problem( (currdir+"test3.mod",), None, [ProblemFormat.nl])
     146        except pyutilib.common.ApplicationError, err:
     147           if not pyutilib.services.registered_executable("ampl") is None:
     148              self.fail("Unexpected ApplicationError - ampl is enabled but not available: '%s'" % str(err))
     149           return
     150        except ConverterError, err:
     151           if not pyutilib.services.registered_executable("ampl") is None:
     152              self.fail("Unexpected ConverterError - ampl is enabled but not available: '%s'" % str(err))
     153           return
     154        self.failUnless(ans[0][0].endswith('.nl'))
     155        #self.failUnlessFileEqualsBinaryFile(ans[0][0], currdir+"test_mod_nl1.nl")
     156
     157    def test_mod_nl2(self):
     158        """ Convert from MOD+DAT to NL """
     159        try:
     160           ans = coopr.opt.convert_problem( (currdir+"test5.mod",currdir+"test5.dat"), None, [ProblemFormat.nl])
     161        except pyutilib.common.ApplicationError, err:
     162           if not pyutilib.services.registered_executable("ampl") is None:
     163              self.fail("Unexpected ApplicationError - ampl is enabled but not available: '%s'" % str(err))
     164           return
     165        except ConverterError, err:
     166           if not pyutilib.services.registered_executable("ampl") is None:
     167              self.fail("Unexpected ConverterError - ampl is enabled but not available: '%s'" % str(err))
     168           return
     169        self.failUnless(ans[0][0].endswith('.nl'))
     170        #self.failUnlessFileEqualsBaseline(ans[0][0], currdir+"test_mod_nl2.nl")
     171
    141172    def test_mock_lp1(self):
    142173        """ Convert from Pyomo to LP """
     
    145176        self.failIfEqual(re.match(".*tmp.*pyomo.lp$",ans[0][0]), None)
    146177
     178    def test_pyomo_lp1(self):
     179        """ Convert from Pyomo to LP with file"""
     180        ans = coopr.opt.convert_problem( (currdir+'model.py',ProblemFormat.cpxlp,), None, [ProblemFormat.cpxlp])
     181        self.failIfEqual(re.match(".*tmp.*pyomo.lp$",ans[0][0]), None)
     182
    147183    def test_mock_lp2(self):
    148184        """ Convert from NL to LP """
     
    171207        os.remove(ans[0][0])
    172208
     209    def test_pyomo_mps1(self):
     210        """ Convert from Pyomo to MPS with file"""
     211        try:
     212           ans = coopr.opt.convert_problem( (currdir+'model.py',ProblemFormat.mps,), None, [ProblemFormat.mps])
     213        except ConverterError, err:
     214           if pyutilib.services.registered_executable("pico_convert") is None:
     215                return
     216           else:
     217                self.fail("Expected ApplicationError because pico_convert is not available: '%s'" % str(err))
     218        self.failUnlessEqual(ans[0][0][-16:],"pico_convert.mps")
     219        os.remove(ans[0][0])
     220
    173221    def test_mock_nl1(self):
    174222        """ Convert from Pyomo to NL """
     
    178226        os.remove(ans[0][0])
    179227
     228    def test_pyomo_nl1(self):
     229        """ Convert from Pyomo to NL with file"""
     230        ans = coopr.opt.convert_problem( (currdir+'model.py',ProblemFormat.nl,), None, [ProblemFormat.nl])
     231        self.failIfEqual(re.match(".*tmp.*pyomo.nl$",ans[0][0]), None)
     232        os.remove(ans[0][0])
     233
    180234    def test_error1(self):
    181235        """ No valid problem types """
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test_cplex.py

    r2048 r2314  
    5050        else:
    5151            self.cplex = coopr.plugins.mip.MockCPLEX(keepFiles=True)
     52        self.cplex.suffixes=['.*']
    5253
    5354    def tearDown(self):
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test_glpk.py

    r1939 r2314  
    4545        else:
    4646            self.glpk = coopr.plugins.mip.MockGLPK(keepFiles=True)
     47        self.glpk.suffixes=['.*']
    4748
    4849    def tearDown(self):
  • coopr.plugins/stable/2.3/coopr/plugins/tests/mip/test_pico.py

    r1969 r2314  
    5151        else:
    5252            self.pico = coopr.plugins.mip.MockPICO(keepFiles=True)
     53        self.pico.suffixes=['.*']
    5354
    5455    def tearDown(self):
Note: See TracChangeset for help on using the changeset viewer.