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

Last change on this file since 1987 was 1987, checked in by jwatson, 10 years ago

Missing an import of SolverStatus? enum in shellcmd.py, triggering an error in an exception case.

File size: 7.1 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
15from coopr.opt.base import *
16from coopr.opt.base.solver import *
17from coopr.opt.results import SolverStatus
18import tempfile
19
20import pyutilib.common
21import pyutilib.services
22import pyutilib.subprocess
23import pyutilib.plugin.core
24import pyutilib.misc
25
26class SystemCallSolver(OptSolver):
27    """ A generic command line solver """
28
29    def __init__(self, **kwds):
30        """ Constructor """
31        OptSolver.__init__(self, **kwds)
32        if 'keepFiles' in kwds:
33            self.keepFiles = kwds['keepFiles']
34        else:
35            self.keepFiles = False
36        self.soln_file=None
37        self.log_file=None
38        self._timelimit=None
39        self._timer=""
40
41    def available(self, exception_flag=True):
42        """ True if the solver is available """
43        if self._assert_available:
44            return True
45        if not OptSolver.available(self,exception_flag):
46            return False
47        ans=self.executable()
48        if ans is None:
49           if exception_flag:
50              if self.executable() is None:
51                 raise pyutilib.common.ApplicationError, "No executable found for solver `"+self.name+"'"
52              else:
53                 raise pyutilib.common.ApplicationError, "Bad path for application `PICO' used by solver "+self.name+"': "+self.executable()
54           return False
55        return True
56
57    def create_command_line(self,executable,problem_files):
58        """
59        Create the command line that is executed.
60        """
61        raise NotImplementedError       #pragma:nocover
62
63    def process_logfile(self):
64        """
65        Process the logfile for information about the optimization process.
66        """
67        return SolverResults()
68
69    def process_soln_file(self,results):
70        """
71        Process auxilliary data files generated by the optimizer (e.g. solution files)
72        """
73        return results
74
75    def _executable(self):
76        """
77        Returns the executable used by this solver.
78        """
79        raise NotImplementedError
80
81    def _presolve(self, *args, **kwds):
82        """
83        Peform presolves.
84        """
85        if 'keepFiles' in kwds:
86            self.keepFiles = kwds['keepFiles']
87            del kwds['keepFiles']
88        OptSolver._presolve(self, *args, **kwds)
89        #
90        # Verify that the input problem exists       
91        #
92        for filename in self._problem_files:
93            if not os.path.exists(filename):
94                raise ValueError, "Solver failed to locate input problem file="+filename
95        #
96        # Create command line
97        #
98        self._command = self.create_command_line(self.executable(),self._problem_files)
99        self.log_file=self._command.log_file
100        #
101        # The pre-cleanup is probably unncessary, but also not harmful.
102        #
103        if self.log_file is not None and os.path.exists(self.log_file):
104           os.remove(self.log_file)
105        if self.soln_file is not None and os.path.exists(self.soln_file):
106           os.remove(self.soln_file)
107
108           
109    def _apply_solver(self):
110        if pyutilib.services.registered_executable("timer"):
111            self._timer=pyutilib.services.registered_executable("timer").get_path()
112        #
113        # Execute the command
114        #
115        pyutilib.plugin.core.PluginGlobals.env("coopr.opt").log.debug("Running "+self._command.cmd)
116
117        # display the log/solver file names prior to execution. this is useful
118        # in case something crashes unexpectedly, which is not without precedent.
119        if self.keepFiles:
120           if self.log_file is not None:
121              print "Solver log file=" + self.log_file
122           if self.soln_file is not None:
123              print "Solver solution file=" + self.soln_file
124           if self._problem_files is not []:
125               print "Solver problem files=",self._problem_files
126
127        sys.stdout.flush()
128        [rc,log] = self._execute_command(self._command)
129        sys.stdout.flush()
130        self._status = pyutilib.misc.Bunch(rc=rc, log=log)
131
132    def _postsolve(self):
133
134        if self.log_file is not None:
135           OUTPUT=open(self.log_file,"w")
136           print >>OUTPUT, "Solver command line: "+self._command.cmd
137           print >>OUTPUT, ""
138           print >>OUTPUT, self._status.log
139           OUTPUT.close()
140
141        # JPW: The cleanup of the problem file probably shouldn't be here, but rather
142        #      in the base OptSolver class. That would require movement of the keepFiles
143        #      attribute and associated cleanup logic to the base class, which I didn't
144        #      feel like doing at this present time. the base class remove_files method
145        #      should clean up the problem file.           
146
147        if self.log_file is not None and not os.path.exists(self.log_file):
148           raise IOError, "File " + self.log_file + " not generated while executing "+self.path
149        results = None
150        if self._results_format is not None:
151           results = self.process_output(self._status.rc)
152           if not self.keepFiles:
153              pyutilib.services.TempfileManager.clear_tempfiles()
154              # in some cases, the solution filename is not generated via the temp-file mechanism,
155              # instead being automatically derived from the input lp/nl filename. so, we may
156              # have to clean it up manually.
157              if os.path.exists(self.soln_file):
158                 os.remove(self.soln_file)
159
160        return results
161
162    def _execute_command(self,command):
163        """
164        Execute the command
165        """
166        try:
167            [rc, log] = pyutilib.subprocess.run(command.cmd, timelimit=self._timelimit, env=command.env, tee=self.tee, shell=True)
168        except pyutilib.common.WindowsError, err:
169            raise pyutilib.common.ApplicationError, "Could not execute the command: "+command.cmd+"\tError message: "+str(err)
170        sys.stdout.flush()
171        return [rc,log]
172
173    def process_output(self,rc):
174        """
175        Process the output files.
176        """
177        if self._results_format is None:
178           raise ValueError, "Results format is None"
179        results = self.process_logfile()
180        if self.results_reader is None:
181           self.process_soln_file(results)
182        else:
183           results = self.results_reader(self.results_file, res=results)
184        if rc != None:
185           results.solver.error_rc=rc
186           if rc != 0:
187              results.solver.status=SolverStatus.error
188        return results
189
190    def _default_results_format(self, prob_format):
191        """ Returns the default results format for different problem
192            formats.
193        """
194        return ResultsFormat.soln
195
196
Note: See TracBrowser for help on using the repository browser.