source: trunk/coopr/plugins/mip/PICO.py @ 1657

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

Removing coopr.opt-depricated, and
renaming coopr.core to coopr.opt.

Unfortunately, plugins are still not being properly loaded, so
some of the tests are failing.

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