source: trunk/coopr/plugins/mip/PICO.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: 9.8 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
12import re
13from coopr.opt.base import *
14from coopr.opt.solver import *
15import pyutilib.services
16import pyutilib.common
17import pyutilib.common
18import pyutilib.plugin.core
19import mockmip
20import os
21import copy
22
23
24class PICO(SystemCallSolver):
25    """The PICO LP/MIP solver
26    """
27
28    def __init__(self, **kwds):
29        #
30        # Call base constructor
31        #
32        kwds["type"] = "pico"
33        SystemCallSolver.__init__(self, **kwds)
34        #
35        # Setup valid problem formats, and valid results for each problem format
36        #
37        self._valid_problem_formats=[ProblemFormat.cpxlp, ProblemFormat.nl, ProblemFormat.mps]
38        self._valid_result_formats = {}
39        self._valid_result_formats[ProblemFormat.cpxlp] = [ResultsFormat.log]
40        self._valid_result_formats[ProblemFormat.nl] = [ResultsFormat.log]
41        self._valid_result_formats[ProblemFormat.mps] = [ResultsFormat.log]
42
43    def executable(self):
44        executable = pyutilib.services.registered_executable("PICO")
45        if executable is None:
46            pyutilib.plugin.core.PluginGlobals.env().log.error("Could not locate the 'PICO' executable, which is required for solver %s" % self.name)
47            self.enable = False
48            return None
49        return executable.get_path()
50
51    def create_command_line(self,executable,problem_files):
52        #
53        # Define log file
54        #
55        if self.log_file is None:
56           self.log_file = pyutilib.services.TempfileManager.create_tempfile(suffix="PICO.log")
57        fname = problem_files[0].split(os.sep)[-1]
58        if '.' in fname:
59            tmp = fname.split('.')
60            if len(tmp) > 2:
61                fname = '.'.join(tmp[:-1])
62            else:
63                fname = tmp[0]
64        if self.soln_file is None:
65           self.soln_file = pyutilib.services.TempfileManager.create_tempfile(suffix=fname+".soln")
66        self.sol_file = fname+".sol"
67        #
68        # Define results file
69        #
70        if self._results_format is None or self._results_format == ResultsFormat.log:
71           self.results_file = self.log_file
72        elif self._results_format == ResultsFormat.sol:
73           self.results_file = self.log_file
74           #self.results_file = self.tmpDir+os.sep+fname+".log"
75       
76        # Eventually, these formats will be added to PICO...
77        #
78        #elif self._results_format == ResultsFormat.osrl:
79           #self.results_file = self.tmpDir+os.sep+"PICO.osrl.xml"
80        #
81        # Define command line
82        #
83        env=copy.copy(os.environ)
84        if self._problem_format is None or self._problem_format == ProblemFormat.nl:
85           if "debug" in self.options:
86                opts = []
87           else:
88                opts = ["debug=2"]
89           for key in self.options:
90                if isinstance(self.options[key],basestring) and ' ' in self.options[key]:
91                    opts.append(key+"=\""+str(self.options[key])+"\"")
92                else:
93                    opt.append(key+"="+str(self.options[key]))
94           env["PICO_options"] = " ".join(opts)
95           proc = self._timer + " " + executable + " " + problem_files[0] + " -AMPL"
96        elif self._problem_format == ProblemFormat.cpxlp or self._problem_format == ProblemFormat.mps:
97           if "debug" in self.options:
98                opt = ""
99           else:
100                opt = " --debug 2"
101           for key in self.options:
102                if isinstance(self.options[key],basestring) and ' ' in self.options[key]:
103                    opt += " --"+key+"=\""+str(self.options[key])+"\""
104                else:
105                    opt += " --"+key+"="+str(self.options[key])
106           proc = self._timer + " " + executable + opt + " --output " + self.soln_file + " " + problem_files[0]
107        return pyutilib.misc.Bunch(cmd=proc, log_file=self.log_file, env=env)
108
109    def process_logfile(self):
110        """
111        Process a logfile
112        """
113        results = SolverResults()
114        #
115        # Initial values
116        #
117        results.solver.ncreated=0
118        results.solver.nbounded=0
119        soln = results.solution.create()
120        #
121        # Process logfile
122        #
123        OUTPUT = open(self.log_file)
124        output = "".join(OUTPUT.readlines())
125        OUTPUT.close()
126        #
127        # Parse logfile lines
128        #
129        for line in output.split("\n"):
130          tokens = re.split('[ \t]+',line.strip())
131          if len(tokens) > 3 and tokens[0] == "ABORTED:":
132             results.solver.status=SolverStatus.aborted
133          elif len(tokens) == 5 and tokens[0] == "Final" and tokens[1] == "Solution:":
134             soln.value = tokens[4]
135             soln.status = SolutionStatus.optimal
136          elif len(tokens) == 3 and tokens[0] == "LP" and tokens[1] == "value=":
137             soln.value = tokens[2]
138             soln.status=SolutionStatus.optimal
139             if results.problem.sense == ProblemSense.minimize:
140                results.problem.lower_bound = tokens[2]
141             else:
142                results.problem.upper_bound = tokens[2]
143          elif len(tokens) == 2 and tokens[0] == "Bound:":
144             if results.problem.sense == ProblemSense.minimize:
145                results.problem.lower_bound = tokens[1]
146             else:
147                results.problem.upper_bound = tokens[1]
148          elif len(tokens) == 3 and tokens[0] == "Created":
149             results.solver.ncreated = tokens[1]
150          elif len(tokens) == 3 and tokens[0] == "Bounded":
151             results.solver.nbounded = tokens[1]
152          elif len(tokens) == 2 and tokens[0] == "sys":
153             results.solver.systime=tokens[1]
154          elif len(tokens) == 2 and tokens[0] == "user":
155             results.solver.usrtime=tokens[1]
156          elif len(tokens) == 3 and tokens[0] == "Solving" and tokens[1] == "problem:":
157             results.problem.name = tokens[2]
158          elif len(tokens) == 4 and tokens[2] == "constraints:":
159             results.problem.num_constraints = tokens[3]
160          elif len(tokens) == 4 and tokens[2] == "variables:":
161             results.problem.num_variables = tokens[3]
162          elif len(tokens) == 4 and tokens[2] == "nonzeros:":
163             results.problem.num_nonzeros = tokens[3]
164          elif len(tokens) == 3 and tokens[1] == "Sense:":
165             if tokens[2] == "minimization":
166                results.problem.sense = ProblemSense.minimize
167             else:
168                results.problem.sense = ProblemSense.maximize
169
170        if results.solver.status is SolverStatus.aborted:
171           soln.optimality=SolutionStatus.unsure
172        if soln.status is SolutionStatus.optimal:
173           soln.gap=0.0
174           if results.problem.sense == ProblemSense.minimize:
175                results.problem.lower_bound = soln.value
176                if "upper_bound" in dir(results.problem):
177                    del results.problem.upper_bound
178           else:
179                results.problem.upper_bound = soln.value
180                if "lower_bound" in dir(results.problem):
181                    del results.problem.lower_bound
182        if results.solver.status is SolverStatus.error:
183           results.solution.delete(0)
184        return results
185
186    def process_other_data(self,results):
187        if os.path.exists(self.sol_file):
188            results_reader = ReaderFactory(ResultsFormat.sol)
189            results = results_reader(self.sol_file, results, results.solution(0))
190            #os.remove(self.sol_file)
191            return
192        if not os.path.exists(self.soln_file):
193           return
194        soln = results.solution(0)
195        results.problem.num_objectives=1
196        tmp=[]
197        flag=False
198        INPUT = open(self.soln_file,"r")
199        lp_flag=None
200        for line in INPUT:
201            tokens = re.split('[ \t]+',line.strip())
202            if tokens[0] == "Objective":
203                continue
204            #print "LINE",tokens
205            if lp_flag is None:
206                lp_flag = (tokens[0] == "LP")
207                continue
208            if tokens[0] == "Dual" and tokens[1] == "solution:":
209                # It looks like we've just been processing primal
210                # variables.
211                for (var,val) in tmp:
212                    soln.variable.add( var, val )
213                tmp=[]
214                continue
215            tmp.append( (tokens[0],tokens[2]) )
216        if lp_flag:
217            for (var,val) in tmp:
218                soln.dual.add( var, val )
219        else:
220            for (var,val) in tmp:
221                soln.variable.add( var, val )
222        INPUT.close()
223
224
225class MockPICO(PICO,mockmip.MockMIP):
226    """A Mock PICO solver used for testing
227    """
228
229    def __init__(self, **kwds):
230        try:
231           PICO.__init__(self,**kwds)
232        except pyutilib.common.ApplicationError: #pragma:nocover
233           pass                        #pragma:nocover
234        mockmip.MockMIP.__init__(self,"pico")
235
236    def available(self, exception_flag=True):
237        return PICO.available(self,exception_flag)
238
239    def create_command_line(self,executable,problem_files):
240        command = PICO.create_command_line(self,executable,problem_files)
241        mockmip.MockMIP.create_command_line(self,executable,problem_files)
242        return command
243
244    def executable(self):
245        return mockmip.MockMIP.executable(self)
246
247    def _execute_command(self,cmd):
248        return mockmip.MockMIP._execute_command(self,cmd)
249
250
251pyutilib.services.register_executable(name="pico")
252SolverRegistration("pico", PICO)
253SolverRegistration("_mock_pico", MockPICO)
Note: See TracBrowser for help on using the repository browser.