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

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

Rework of Coopr to use the new PyUtilib? package decomposition.

NOTE: to use Coopr with this update, we need to work with a new version of coopr_install.

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