source: trunk/coopr/opt/solver/shellcmd.py @ 1670

Last change on this file since 1670 was 1670, checked in by wehart, 11 years ago

Various updates:

  1. Rework of CBC parser to handle infeasiblility results.
  1. Rework of Pyomo presolver to collect data the is needed for the NL writer. Rework of the NL writer to use this new data. (This has apparently been broken for a while. I'm not sure why our tests have failed to detect that!)
  1. Adding the --save-model option to Pyomo's command-line, which allows the user to specify the file that they want saved. Coopr will do the work of converting the model to the requested format.
File size: 6.7 KB
Line 
1#  _________________________________________________________________________
2#
3#  Coopr: A COmmon Optimization Python Repository
4#  Copyright (c) 2008 Sandia Corporation.
5#  This software is distributed under the BSD License.
6#  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7#  the U.S. Government retains certain rights in this software.
8#  For more information, see the Coopr README.txt file.
9#  _________________________________________________________________________
10
11__all__ = ['SystemCallSolver']
12
13import sys
14import os
15import pyutilib
16from coopr.opt.base import *
17from coopr.opt.base.solver import *
18import tempfile
19
20
21class SystemCallSolver(OptSolver):
22    """ A generic command line solver """
23
24    def __init__(self, **kwds):
25        """ Constructor """
26        OptSolver.__init__(self, **kwds)
27        if 'keepFiles' in kwds:
28            self.keepFiles = kwds['keepFiles']
29        else:
30            self.keepFiles = False
31        self.soln_file=None
32        self.log_file=None
33        self._timelimit=None
34        self._timer=""
35
36    def available(self, exception_flag=True):
37        """ True if the solver is available """
38        if self._assert_available:
39            return True
40        if not OptSolver.available(self,exception_flag):
41            return False
42        ans=self.executable()
43        if ans is None:
44           if exception_flag:
45              if self.executable() is None:
46                 raise pyutilib.ApplicationError, "No executable found for solver `"+self.name+"'"
47              else:
48                 raise pyutilib.ApplicationError, "Bad path for application `PICO' used by solver "+self.name+"': "+self.executable()
49           return False
50        return True
51
52    def create_command_line(self,executable,problem_files):
53        """
54        Create the command line that is executed.
55        """
56        raise NotImplementedError       #pragma:nocover
57
58    def process_logfile(self):
59        """
60        Process the logfile for information about the optimization process.
61        """
62        raise NotImplementedError       #pragma:nocover
63
64    def process_other_data(self,results):
65        """
66        Process auxilliary data files generated by the optimizer (e.g. solution files)
67        """
68        pass        #pragma:nocover
69
70    def _executable(self):
71        """
72        Returns the executable used by this solver.
73        """
74        raise NotImplementedError
75
76    def _presolve(self, *args, **kwds):
77        """
78        Peform presolves.
79        """
80        if 'keepFiles' in kwds:
81            self.keepFiles = kwds['keepFiles']
82            del kwds['keepFiles']
83        OptSolver._presolve(self, *args, **kwds)
84        #
85        # Verify that the input problem exists       
86        #
87        for filename in self._problem_files:
88            if not os.path.exists(filename):
89                raise ValueError, "Solver failed to locate input problem file="+filename
90        #
91        # Create command line
92        #
93        self._command = self.create_command_line(self.executable(),self._problem_files)
94        self.log_file=self._command.log_file
95        #
96        # The pre-cleanup is probably unncessary, but also not harmful.
97        #
98        if self.log_file is not None and os.path.exists(self.log_file):
99           os.remove(self.log_file)
100        if self.soln_file is not None and os.path.exists(self.soln_file):
101           os.remove(self.soln_file)
102
103           
104    def _apply_solver(self):
105        if pyutilib.registered_executable("timer"):
106            self._timer=pyutilib.registered_executable("timer").get_path()
107        #
108        # Execute the command
109        #
110        pyutilib.plugin.PluginGlobals.env("coopr.opt").log.debug("Running "+self._command.cmd)
111
112        # display the log/solver file names prior to execution. this is useful
113        # in case something crashes unexpectedly, which is not without precedent.
114        if self.keepFiles:
115           if self.log_file is not None:
116              print "Solver log file=" + self.log_file
117           if self.soln_file is not None:
118              print "Solver solution file=" + self.soln_file
119           if self._problem_files is not []:
120               print "Solver problem files=",self._problem_files
121
122        sys.stdout.flush()
123        [rc,log] = self._execute_command(self._command)
124        sys.stdout.flush()
125        self._status = pyutilib.Bunch(rc=rc, log=log)
126
127    def _postsolve(self):
128        if self.log_file is not None:
129           OUTPUT=open(self.log_file,"w")
130           print >>OUTPUT, "Solver command line: "+self._command.cmd
131           print >>OUTPUT, ""
132           print >>OUTPUT, self._status.log
133           OUTPUT.close()
134
135        # JPW: The cleanup of the problem file probably shouldn't be here, but rather
136        #      in the base OptSolver class. That would require movement of the keepFiles
137        #      attribute and associated cleanup logic to the base class, which I didn't
138        #      feel like doing at this present time. the base class remove_files method
139        #      should clean up the problem file.           
140
141        if self.log_file is not None and not os.path.exists(self.log_file):
142           raise IOError, "File " + self.log_file + " not generated while executing "+self.path
143        results = None
144        if self._results_format is not None:
145           results = self.process_output(self._status.rc)
146           if not self.keepFiles:
147              pyutilib.TempfileManager.clear_tempfiles()
148
149        return results
150
151    def _execute_command(self,command):
152        """
153        Execute the command
154        """
155        try:
156            [rc, log] = pyutilib.run_command(command.cmd, timelimit=self._timelimit, env=command.env, tee=self.tee, shell=True)
157        except pyutilib.WindowsError, err:
158            raise pyutilib.ApplicationError, "Could not execute the command: "+command.cmd+"\tError message: "+str(err)
159        sys.stdout.flush()
160        return [rc,log]
161
162    def process_output(self,rc):
163        """
164        Process the output files.
165        """
166        if self._results_format is None:
167           raise ValueError, "Results format is None"
168        if self.results_reader is None:
169           if self._results_format is ResultsFormat.log:
170              results = self.process_logfile()
171           else:
172              raise ValueError, "Results format `"+str(self._results_format)+"' is has not been registered"
173        else:
174           results = self.results_reader(self.results_file)
175        self.process_other_data(results)
176        if rc != None:
177           results.solver.error_rc=rc
178           if rc != 0:
179              results.solver.status=SolverStatus.error
180        return results
181
182    def _default_results_format(self, prob_format):
183        """ Returns the default results format for different problem
184            formats.
185        """
186        return ResultsFormat.log
187
188
Note: See TracBrowser for help on using the repository browser.