Changeset 2903


Ignore:
Timestamp:
Aug 3, 2010 12:58:43 PM (9 years ago)
Author:
prsteel
Message:

Reverting previous change to give a better commit message...

File:
1 edited

Legend:

Unmodified
Added
Removed
  • coopr.plugins/trunk/coopr/plugins/mip/GLPK.py

    r2902 r2903  
    3939        #
    4040        self._valid_problem_formats = [
    41                ProblemFormat.mod, ProblemFormat.cpxlp, ProblemFormat.mps]
     41               ProblemFormat.mod, ProblemFormat.cpxlp, ProblemFormat.mps ]
    4242        self._valid_result_formats = {
    43             ProblemFormat.mod: ResultsFormat.soln,
    44             ProblemFormat.cpxlp: ResultsFormat.soln,
    45             ProblemFormat.mps: ResultsFormat.soln,
     43            ProblemFormat.mod   : ResultsFormat.soln,
     44            ProblemFormat.cpxlp : ResultsFormat.soln,
     45            ProblemFormat.mps   : ResultsFormat.soln,
    4646        }
    4747
     
    5151        self._capabilities.integer = True
    5252
     53
    5354    def executable(self):
    5455        executable = registered_executable('glpsol')
    5556        if executable is None:
    56             msg = "Could not locate the 'glpsol' executable, which is " \
     57            msg = "Could not locate the 'glpsol' executable, which is "       \
    5758                  "required for solver '%s'"
    58             PluginGlobals.env().log.error(msg % self.name)
     59            PluginGlobals.env().log.error( msg % self.name )
    5960            self.enable = False
    6061            return None
     
    6263        return executable.get_path()
    6364
    64     def create_command_line(self, executable, problem_files):
     65
     66    def create_command_line(self,executable,problem_files):
    6567        #
    6668        # Define log file
    6769        #
    6870        if self.log_file is None:
    69             self.log_file = TempfileManager.create_tempfile(suffix='.glpk.log')
     71           self.log_file = TempfileManager.create_tempfile( suffix='.glpk.log')
    7072
    7173        #
     
    7476        if self.soln_file is None:
    7577            self.soln_file = \
    76                            TempfileManager.create_tempfile(suffix='.glpk.soln')
     78                  TempfileManager.create_tempfile(suffix='.glpk.soln')
    7779
    7880        #
    7981        # Define results file
    8082        #
    81         if self._results_format is None \
     83        if self._results_format is None                                       \
    8284           or self._results_format == ResultsFormat.soln:
    8385            self.results_file = self.soln_file
     
    8890        cmd = [self._timer, '"%s"' % executable]
    8991        for key in self.options:
    90             if isinstance(self.options[key], basestring) \
    91                    and ' ' in self.options[key]:
    92                 cmd.append('--%s "%s"' % (key, str(self.options[key])))
     92            if isinstance(self.options[key],basestring)                      \
     93               and ' ' in self.options[key]:
     94                cmd.append('--%s "%s"' % (key, str(self.options[key])) )
    9395            else:
    94                 cmd.append('--%s %s' % (key, str(self.options[key])))
     96                cmd.append('--%s %s' % (key, str(self.options[key])) )
    9597
    9698        if self._timelimit is not None and self._timelimit > 0.0:
    97             cmd.append('--tmlim ' + str(self._timelimit))
     99            cmd.append('--tmlim ' + str(self._timelimit) )
    98100
    99101        if (self.mipgap is not None) and (self.mipgap > 0.0):
    100             cmd.append('--mipgap ' + str(self.mipgap))
    101         cmd.append('--output ' + self.soln_file)
     102            cmd.append('--mipgap ' + str(self.mipgap) )
     103        cmd.append('--output ' + self.soln_file )
    102104
    103105        if self._problem_format == ProblemFormat.cpxlp:
    104             cmd.append('--cpxlp ' + problem_files[0])
     106            cmd.append('--cpxlp ' + problem_files[0] )
    105107        elif self._problem_format == ProblemFormat.mps:
    106             cmd.append('--freemps ' + problem_files[0])
     108            cmd.append('--freemps ' + problem_files[0] )
    107109        elif self._problem_format == ProblemFormat.mod:
    108             cmd.append('--math ' + problem_files[0])
    109             cmd.append('--data "%s"' % fname for fname in problem_files[1:])
    110 
    111         cmd = ' '.join(cmd)
    112 
    113         return Bunch(cmd=cmd, log_file=self.log_file, env=None)
     110            cmd.append('--math ' + problem_files[0] )
     111            cmd.append('--data "%s"' % fname for fname in problem_files[1:] )
     112
     113        cmd = ' '.join( cmd )
     114
     115        return Bunch( cmd=cmd, log_file=self.log_file, env=None )
    114116
    115117    def process_logfile(self):
     
    121123        # Initial values
    122124        #
    123         # results.solver.statistics.branch_and_bound.
    124         #     number_of_created_subproblems=0
    125         # results.solver.statistics.branch_and_bound.
    126         #     number_of_bounded_subproblems=0
     125        #results.solver.statistics.branch_and_bound.number_of_created_subproblems=0
     126        #results.solver.statistics.branch_and_bound.number_of_bounded_subproblems=0
    127127        soln = results.solution.add()
    128         soln.objective['f'] = float('inf')
     128        soln.objective['f']=float('inf')
    129129        #
    130130        # Process logfile
     
    136136        # Parse logfile lines
    137137        #
    138 
    139         # Handle long variable names
    140         stats = results.solver.statistics
    141 
    142138        for line in output.split("\n"):
    143             tokens = re.split('[ \t]+', line.strip())
    144             if len(tokens) > 4 and tokens[1] == "objval":
    145                 soln.objective['f'] = tokens[3]
    146             elif len(tokens) > 3 and tokens[0] == "Objective" and \
    147                      tokens[1] == "value":
    148                 soln.objective['f'] = tokens[3]
    149             elif len(tokens) > 4 and tokens[0] == "!" and \
    150                      tokens[2] == "objval":
    151                 soln.objective['f'] = tokens[4]
    152             elif len(tokens) > 4 and tokens[0] == "+" and \
    153                      tokens[2] == "objval":
    154                 soln.objective['f'] = tokens[4]
    155             elif len(tokens) > 4 and tokens[0] == "*" and \
    156                      tokens[2] == "objval":
    157                 soln.objective['f'] = tokens[4]
    158             elif len(tokens) > 4 and tokens[0] == "+" and \
    159                      tokens[2] == "mip" and tokens[4] == "not":
    160                 soln.objective['f'] = "unknown"
    161                 results.problem.lower_bound = tokens[8]
    162             elif len(tokens) > 4 and tokens[0] == "+" and \
    163                      tokens[1] == "mip" and tokens[4] == "not":
    164                 soln.objective['f'] = "unknown"
    165                 results.problem.lower_bound = tokens[7]
    166             elif len(tokens) > 4 and tokens[0] == "+" and \
    167                      tokens[2] == "mip" and tokens[4] != "not":
    168                 soln.objective['f'] = tokens[4]
    169                 if tokens[6] != "tree":
    170                     results.problem.lower_bound = tokens[6]
    171             elif len(tokens) > 4 and tokens[0] == "+" and \
    172                      tokens[1] == "mip" and tokens[4] != "not":
    173                 soln.objective['f'] = tokens[3]
    174                 results.problem.lower_bound = tokens[5]
    175             elif len(tokens) == 6 and tokens[0] == "OPTIMAL" and \
    176                      tokens[1] == "SOLUTION" and tokens[5] == "PRESOLVER":
    177                 stats.branch_and_bound.number_of_created_subproblems = 0
    178                 stats.branch_and_bound.number_of_bounded_subproblems = 0
    179                 soln.status = SolutionStatus.optimal
    180             elif len(tokens) == 7 and tokens[1] == "OPTIMAL" and \
    181                      tokens[2] == "SOLUTION" and tokens[6] == "PRESOLVER":
    182                 stats.branch_and_bound.number_of_created_subproblems = 0
    183                 stats.branch_and_bound.number_of_bounded_subproblems = 0
    184                 soln.status = SolutionStatus.optimal
    185             elif len(tokens) > 10 and tokens[0] == "+" and \
    186                      tokens[8] == "empty":
    187                 stats.branch_and_bound.number_of_created_subproblems = tokens[11][:-1]
    188                 stats.branch_and_bound.number_of_bounded_subproblems = tokens[11][:-1]
    189             elif len(tokens) > 9 and tokens[0] == "+" and \
    190                      tokens[7] == "empty":
    191                 stats.branch_and_bound.number_of_created_subproblems = tokens[10][:-1]
    192                 stats.branch_and_bound.number_of_bounded_subproblems = tokens[10][:-1]
    193             elif len(tokens) == 2 and tokens[0] == "sys":
    194                 results.solver.system_time = tokens[1]
    195             elif len(tokens) == 2 and tokens[0] == "user":
    196                 results.solver.user_time = tokens[1]
    197             elif len(tokens) > 2 and tokens[0] == "OPTIMAL" and \
    198                      tokens[1] == "SOLUTION":
    199                 soln.status = SolutionStatus.optimal
    200             elif len(tokens) > 2 and tokens[0] == "INTEGER" and \
    201                      tokens[1] == "OPTIMAL":
    202                 soln.status = SolutionStatus.optimal
    203                 stats.branch_and_bound.number_of_created_subproblems = 0
    204                 stats.branch_and_bound.number_of_bounded_subproblems = 0
    205             elif len(tokens) > 2 and tokens[0] == "TIME" and \
    206                      tokens[2] == "EXCEEDED;":
    207                 soln.status = SolutionStatus.stoppedByLimit
     139          tokens = re.split('[ \t]+',line.strip())
     140          if len(tokens) > 4 and tokens[1] == "objval":
     141             soln.objective['f'] = tokens[3]
     142          elif len(tokens) > 3 and tokens[0] == "Objective" and tokens[1] == "value":
     143             soln.objective['f'] = tokens[3]
     144          elif len(tokens) > 4 and tokens[0] == "!" and tokens[2] == "objval":
     145             soln.objective['f'] = tokens[4]
     146          elif len(tokens) > 4 and tokens[0] == "+" and tokens[2] == "objval":
     147             soln.objective['f'] = tokens[4]
     148          elif len(tokens) > 4 and tokens[0] == "*" and tokens[2] == "objval":
     149             soln.objective['f'] = tokens[4]
     150          elif len(tokens) > 4 and tokens[0] == "+" and tokens[2] == "mip" and tokens[4] == "not":
     151             soln.objective['f'] = "unknown"
     152             results.problem.lower_bound = tokens[8]
     153          elif len(tokens) > 4 and tokens[0] == "+" and tokens[1] == "mip" and tokens[4] == "not":
     154             soln.objective['f'] = "unknown"
     155             results.problem.lower_bound = tokens[7]
     156          elif len(tokens) > 4 and tokens[0] == "+" and tokens[2] == "mip" and tokens[4] != "not":
     157             soln.objective['f'] = tokens[4]
     158             if tokens[6] != "tree":
     159                results.problem.lower_bound = tokens[6]
     160          elif len(tokens) > 4 and tokens[0] == "+" and tokens[1] == "mip" and tokens[4] != "not":
     161             soln.objective['f'] = tokens[3]
     162             results.problem.lower_bound = tokens[5]
     163          elif len(tokens) == 6 and tokens[0] == "OPTIMAL" and tokens[1] == "SOLUTION" and tokens[5] == "PRESOLVER":
     164             results.solver.statistics.branch_and_bound.number_of_created_subproblems = 0
     165             results.solver.statistics.branch_and_bound.number_of_bounded_subproblems = 0
     166             soln.status = SolutionStatus.optimal
     167          elif len(tokens) == 7 and tokens[1] == "OPTIMAL" and tokens[2] == "SOLUTION" and tokens[6] == "PRESOLVER":
     168             results.solver.statistics.branch_and_bound.number_of_created_subproblems = 0
     169             results.solver.statistics.branch_and_bound.number_of_bounded_subproblems = 0
     170             soln.status = SolutionStatus.optimal
     171          elif len(tokens) > 10 and tokens[0] == "+" and tokens[8] == "empty":
     172             results.solver.statistics.branch_and_bound.number_of_created_subproblems = tokens[11][:-1]
     173             results.solver.statistics.branch_and_bound.number_of_bounded_subproblems = tokens[11][:-1]
     174          elif len(tokens) > 9 and tokens[0] == "+" and tokens[7] == "empty":
     175             results.solver.statistics.branch_and_bound.number_of_created_subproblems = tokens[10][:-1]
     176             results.solver.statistics.branch_and_bound.number_of_bounded_subproblems = tokens[10][:-1]
     177          elif len(tokens) == 2 and tokens[0] == "sys":
     178             results.solver.system_time=tokens[1]
     179          elif len(tokens) == 2 and tokens[0] == "user":
     180             results.solver.user_time=tokens[1]
     181          elif len(tokens) > 2 and tokens[0] == "OPTIMAL" and tokens[1] == "SOLUTION":
     182             soln.status = SolutionStatus.optimal
     183          elif len(tokens) > 2 and tokens[0] == "INTEGER" and tokens[1] == "OPTIMAL":
     184             soln.status = SolutionStatus.optimal
     185             results.solver.statistics.branch_and_bound.number_of_created_subproblems = 0
     186             results.solver.statistics.branch_and_bound.number_of_bounded_subproblems = 0
     187          elif len(tokens) > 2 and tokens[0] == "TIME" and tokens[2] == "EXCEEDED;":
     188             soln.status = SolutionStatus.stoppedByLimit
    208189        if results.problem.upper_bound == "inf":
    209             results.problem.upper_bound = 'Infinity'
     190           results.problem.upper_bound = 'Infinity'
    210191        if results.problem.lower_bound == "-inf":
    211             results.problem.lower_bound = "-Infinity"
     192           results.problem.lower_bound = "-Infinity"
    212193        try:
    213194            val = results.problem.upper_bound
     
    229210            pass
    230211        if soln.status is SolutionStatus.optimal:
    231             soln.gap = 0.0
     212           soln.gap=0.0
    232213        elif soln.status is SolutionStatus.stoppedByLimit:
    233             soln.gap = "Infinity"  # until proven otherwise
    234             if "lower_bound" in dir(results.problem):
    235                 if results.problem.lower_bound is "-Infinity":
    236                     soln.gap = "Infinity"
    237                 elif not results.problem.lower_bound is None:
    238                     if "upper_bound" not in dir(results.problem):
    239                         gap = "Infinity"
    240                     elif results.problem.upper_bound is None:
    241                         gap = "Infinity"
    242                     else:
    243                         soln.gap = eval(soln.objective['f']) - \
    244                                    eval(results.problem.lower_bound)
    245             elif "upper_bound" in dir(results.problem):
    246                 if results.problem.upper_bound is "Infinity":
    247                     soln.gap = "Infinity"
    248                 elif not results.problem.upper_bound is None:
    249                     soln.gap = eval(results.problem.upper_bound) - \
    250                                eval(soln.objective['f'])
     214           soln.gap = "Infinity" # until proven otherwise
     215           if "lower_bound" in dir(results.problem):
     216              if results.problem.lower_bound is "-Infinity":
     217                 soln.gap="Infinity"
     218              elif not results.problem.lower_bound is None:
     219                 if "upper_bound" not in dir(results.problem):
     220                    gap="Infinity"
     221                 elif results.problem.upper_bound is None:
     222                    gap="Infinity"
     223                 else:
     224                    soln.gap=eval(soln.objective['f']) - eval(results.problem.lower_bound)
     225           elif "upper_bound" in dir(results.problem):
     226              if results.problem.upper_bound is "Infinity":
     227                 soln.gap="Infinity"
     228              elif not results.problem.upper_bound is None:
     229                 soln.gap=eval(results.problem.upper_bound) - eval(soln.objective['f'])
    251230        if results.solver.status is SolverStatus.error:
    252             results.solution.delete(0)
     231           results.solution.delete(0)
    253232        return results
    254233
    255     def process_soln_file(self, results):
     234    def process_soln_file(self,results):
    256235
    257236        # the only suffixes that we extract from GLPK are
     
    261240        extract_duals = False
    262241        for suffix in self.suffixes:
    263             flag = False
    264             if re.match(suffix, "dual"):
     242            flag=False
     243            if re.match(suffix,"dual"):
    265244                extract_duals = True
    266                 flag = True
     245                flag=True
    267246            if not flag:
    268                 raise RuntimeError, \
    269                       ("***GLPK solver plugin cannot extract solution " + \
    270                        "suffix='%s'") % (suffix)
    271 
    272         lp_solution = True  # if false, we're dealing with a MIP!
     247                raise RuntimeError,"***GLPK solver plugin cannot extract solution suffix="+suffix
     248
     249        lp_solution = True # if false, we're dealing with a MIP!
    273250        if not os.path.exists(self.soln_file):
    274             return
     251           return
    275252        soln = results.solution(0)
    276         INPUT = open(self.soln_file, "r")
     253        INPUT = open(self.soln_file,"r")
    277254
    278255        try:
    279256
    280             state = 0  # 0=initial header, 1=constraints, 2=variables, -1=done
    281 
    282             results.problem.number_of_objectives = 1
    283 
    284             # for validation of the total count read and the order
    285             number_of_constraints_read = 0
    286             number_of_variables_read = 0
    287 
    288             # constraint names and their value/bounds can be split
    289             # across multiple lines
    290             active_constraint_name = ""
    291 
    292             # variable names and their value/bounds can be split across
    293             # multiple lines
    294             active_variable_name = ""
    295 
    296             for line in INPUT:
    297                 tokens = re.split('[ \t]+', line.strip())
    298 
    299                 if (len(tokens) == 1) and (len(tokens[0]) == 0):
    300                     pass
    301                 elif state == 0:
    302                     #
    303                     # Processing initial header
    304                     #
    305                     if len(tokens) == 2 and tokens[0] == "Problem:":
    306                         # the problem name may be absent, in which case
    307                         # the "Problem:" line will be skipped.
    308                         results.problem.name = tokens[1]
    309                     elif len(tokens) == 2 and tokens[0] == "Rows:":
    310                         results.problem.number_of_constraints = eval(tokens[1])
    311                     elif len(tokens) == 2 and tokens[0] == "Columns:":
    312                         lp_solution = True
    313                         results.problem.number_of_variables = eval(tokens[1])
    314                     elif len(tokens) > 2 and tokens[0] == "Columns:":
    315                         lp_solution = False
    316                         results.problem.number_of_variables = eval(tokens[1])
    317                     elif len(tokens) == 2 and tokens[0] == "Non-zeros:":
    318                         results.problem.number_of_nonzeros = eval(tokens[1])
    319                     elif len(tokens) >= 2 and tokens[0] == "Status:":
    320                         if tokens[1] == "OPTIMAL":
    321                             soln.status = SolutionStatus.optimal
    322                         elif len(tokens) == 3 and tokens[1] == "INTEGER" and \
    323                                  tokens[2] == "NON-OPTIMAL":
    324                             soln.status = SolutionStatus.bestSoFar
    325                         elif len(tokens) == 3 and tokens[1] == "INTEGER" and \
    326                                  tokens[2] == "OPTIMAL":
    327                             soln.status = SolutionStatus.optimal
    328                         elif len(tokens) == 3 and tokens[1] == "INTEGER" and \
    329                                  tokens[2] == "UNDEFINED":
    330                             soln.status = SolutionStatus.stoppedByLimit
    331                         elif (len(tokens) == 2) and (tokens[1] == "UNDEFINED"):
    332                             soln.status = SolutionStatus.infeasible
    333                         else:
    334                             print ("WARNING: Read unknown status while " + \
    335                                    "parsing GLPK solution file - " + \
    336                                    "status='%s'") % (" ".join(tokens[1:]))
    337                     elif len(tokens) >= 2 and tokens[0] == "Objective:":
    338                         if tokens[4] == "(MINimum)":
    339                             results.problem.sense = ProblemSense.minimize
    340                         else:
    341                             results.problem.sense = ProblemSense.maximize
    342                         soln.objective['f'] = tokens[3]
    343                         if soln.status is SolutionStatus.optimal:
    344                             if tokens[4] == "(MINimum)":
    345                                 results.problem.lower_bound = soln.objective['f'].value
    346                                 if "upper_bound" in dir(results.problem):
    347                                     del results.problem.upper_bound
    348                             else:
    349                                 results.problem.upper_bound = soln.objective['f'].value
    350                                 if "lower_bound" in dir(results.problem):
    351                                     del results.problem.lower_bound
    352                         # the objective is the last entry in the problem section - move on to constraints.
    353                         state = 1
    354 
    355                 elif state == 1:
    356                     #
    357                     # Process Constraint Info
    358                     #
    359 
    360                     if (len(tokens) == 2) and (len(active_constraint_name) == 0):
    361                         number_of_constraints_read = number_of_constraints_read + 1
    362                         active_constraint_name = tokens[1].strip()
    363                         index = eval(tokens[0].strip())
    364 
    365                         # sanity check - the indices should be in sequence.
    366                         if index != number_of_constraints_read:
    367                             raise ValueError, \
    368                                   ("***ERROR: Unexpected constraint index " + \
    369                                    "encountered on line=%s; expected " + \
    370                                    "value=%s; actual value=%s") % \
    371                                    (line, str(number_of_consrtaints_read),
    372                                     str(index))
    373                     else:
    374                         index = None
    375                         activity = None
    376                         lower_bound = None
    377                         upper_bound = None
    378                         marginal = None
    379 
    380                         # extract the field names and process accordingly. there
    381                         # is some wasted processing w.r.t. single versus double-line
    382                         # entries, but it's not significant enough to worry about.
    383 
    384                         index_string = line[0:6].strip()
    385                         name_string = line[7:19].strip()
    386                         activity_string = line[23:36].strip()
    387                         lower_bound_string = line[37:50].strip()
    388                         upper_bound_string = line[51:64].strip()
    389 
    390                         state_string = None
    391                         marginal_string = None
    392 
    393                         # skip any headers
    394                         if (index_string == "------") or (index_string == "No."):
    395                             continue
    396 
    397                         if len(index_string) > 0:
    398                             index = eval(index_string)
    399 
    400                         if lp_solution is True:
    401                             state_string = line[20:22].strip()
    402                             marginal_string = line[65:78].strip()
    403                             if (activity_string != "< eps") and (len(activity_string) > 0):
    404                                 activity = eval(activity_string)
    405                             else:
    406                                 activity = 0.0
    407                                 if (lower_bound_string != "< eps") and (len(lower_bound_string) > 0):
    408                                     lower_bound = eval(lower_bound_string)
    409                                 else:
    410                                     lower_bound = 0.0
    411                                 if state_string != "NS":
    412                                     if (upper_bound_string != "< eps") and (len(upper_bound_string) > 0):
    413                                         upper_bound = eval(upper_bound_string)
    414                                     else:
    415                                         upper_bound = 0.0
    416                                 if (marginal_string != "< eps") and (len(marginal_string) > 0):
    417                                     marginal = eval(marginal_string)
    418                                 else:
    419                                     marginal = 0.0
    420 
    421                         else:
    422                             # no constraint-related attributes/values are extracted currently for MIPs.
    423                             pass
    424 
    425                         constraint_name = None
    426                         if len(active_constraint_name) > 0:
    427                             # if there is an active constraint name, the identifier was
    428                             # too long for everything to be on a single line; the second
    429                             # line contains all of the value information.
    430                             constraint_name = active_constraint_name
    431                             active_constraint_name = ""
    432                         else:
    433                             # everything is on a single line.
    434                             constraint_name = name_string
    435                             number_of_constraints_read = number_of_constraints_read + 1
    436                             # sanity check - the indices should be in sequence.
    437                             if index != number_of_constraints_read:
    438                                 raise ValueError,"***ERROR: Unexpected constraint index encountered on line="+line+"; expected value="+str(number_of_constraints_read)+"; actual value="+str(index)
    439 
    440                         if lp_solution is True:
    441                             # GLPK doesn't report slacks directly.
    442                             constraint_dual = activity
    443                             if state_string == "B":
    444                                 constraint_dual = 0.0
    445                             elif (state_string == "NS") or (state_string == "NL") or (state_string == "NU"):
    446                                 constraint_dual = marginal
    447                             else:
    448                                 raise ValueError, "Unknown status="+tokens[0]+" encountered for constraint="+active_constraint_name+" in line="+line+" of solution file="+self.soln_file
    449 
    450                             if extract_duals is True:
    451                                 soln.constraint[constraint_name].dual = constraint_dual
    452 
    453                         else:
    454                             # there isn't anything interesting to do with constraints in the MIP case.
    455                             pass
    456 
    457                         # if all of the constraints have been read, exit.
    458                         if number_of_constraints_read == results.problem.number_of_constraints:
    459                             state = 2
    460 
    461                 elif state == 2:
    462                     #
    463                     # Process Variable Info
    464                     #
    465 
    466                     if (len(tokens) == 2) and (len(active_variable_name) == 0):
    467 
    468                         # in the case of name over-flow, there are only two tokens
    469                         # on the first of two lines for the variable entry.
    470                         number_of_variables_read = number_of_variables_read + 1
    471                         active_variable_name = tokens[1].strip()
    472                         index = eval(tokens[0].strip())
    473 
    474                         # sanity check - the indices should be in sequence.
    475                         if index != number_of_variables_read:
    476                             raise ValueError,"***ERROR: Unexpected variable index encountered on line="+line+"; expected value="+str(number_of_variables_read)+"; actual value="+str(index)
    477 
    478                     else:
    479 
    480                         index = None
    481                         activity = None
    482                         lower_bound = None
    483                         upper_bound = None
    484                         marginal = None
    485 
    486                         # extract the field names and process accordingly. there
    487                         # is some wasted processing w.r.t. single versus double-line
    488                         # entries, but it's not significant enough to worry about.
    489 
    490                         index_string = line[0:6].strip()
    491                         name_string = line[7:19].strip()
    492                         activity_string = line[23:36].strip()
    493                         lower_bound_string = line[37:50].strip()
    494                         upper_bound_string = line[51:64].strip()
    495 
    496                         state_string = None
    497                         marginal_string = None
    498 
    499                         # skip any headers
    500                         if (index_string == "------") or (index_string == "No."):
    501                             continue
    502 
    503                         if len(index_string) > 0:
    504                             index = eval(index_string)
    505 
    506                         if lp_solution is True:
    507 
    508                             state_string = line[20:22].strip()
    509                             marginal_string = line[65:78].strip()
    510 
    511                             if (activity_string != "< eps") and (len(activity_string) > 0):
    512                                 activity = eval(activity_string)
    513                             else:
    514                                 activity = 0.0
    515                                 if (lower_bound_string != "< eps") and (len(lower_bound_string) > 0):
    516                                     lower_bound = eval(lower_bound_string)
    517                                 else:
    518                                     lower_bound = 0.0
    519                             if state_string != "NS":
    520                                 if (upper_bound_string != "< eps") and (len(upper_bound_string) > 0):
    521                                     upper_bound = eval(upper_bound_string)
    522                                 else:
    523                                     upper_bound = 0.0
    524                             if (marginal_string != "< eps") and (len(marginal_string) > 0):
    525                                 marginal = eval(marginal_string)
    526                             else:
    527                                 marginal = 0.0
    528                         else:
    529                             if (activity_string != "< eps") and (len(activity_string) > 0):
    530                                 activity = eval(activity_string)
    531                             else:
    532                                 activity = 0.0
    533 
    534                         variable_name = None
    535                         if len(active_variable_name) > 0:
    536                             # if there is an active variable name, the identifier was
    537                             # too long for everything to be on a single line; the second
    538                             # line contains all of the value information.
    539                             variable_name = active_variable_name
    540                             active_variable_name = ""
    541                         else:
    542                             # everything is on a single line.
    543                             variable_name = name_string
    544                             number_of_variables_read = number_of_variables_read + 1
    545                             # sanity check - the indices should be in sequence.
    546                             if index != number_of_variables_read:
    547                                 raise ValueError,"***ERROR: Unexpected variable index encountered on line="+line+"; expected value="+str(number_of_variables_read)+"; actual value="+str(index)
    548 
    549                         if lp_solution is True:
    550                             # the "activity" column always specifies the variable value.
    551                             # embedding the if-then-else to validate the basis status.
    552                             # we are currently ignoring all bound-related information.
    553                             variable_value = None
    554                             if state_string in ('B', 'NL', 'NS', 'NU', 'NF'):
    555                                 # NF = non-basic free (unbounded) variable
    556                                 # NL = non-basic variable at its lower bound
    557                                 # NU = non-basic variable at its upper bound
    558                                 # NS = non-basic fixed variable
    559                                 variable_value = activity
    560                             else:
    561                                 raise ValueError, "Unknown status="+state_string+" encountered for variable="+variable_name+" in the following line of the GLPK solution file="+self.soln_file+":\n"+line
    562 
    563                             soln.variable[variable_name].value = variable_value
    564                         else:
    565                             soln.variable[variable_name].value = activity
    566 
    567                     # if all of the variables have been read, exit.
    568                     if number_of_variables_read == results.problem.number_of_variables:
    569                         state = -1
    570 
    571                 if state==-1:
    572                     break
    573 
    574             INPUT.close()
     257           state = 0 # 0=initial header, 1=constraints, 2=variables, -1=done
     258
     259           results.problem.number_of_objectives = 1
     260
     261           number_of_constraints_read = 0 # for validation of the total count read and the order
     262           number_of_variables_read = 0
     263           active_constraint_name = "" # constraint names and their value/bounds can be split across multiple lines
     264           active_variable_name = "" # variable names and their value/bounds can be split across multiple lines
     265
     266           for line in INPUT:
     267             tokens = re.split('[ \t]+',line.strip())
     268
     269             if (len(tokens) == 1) and (len(tokens[0]) == 0):
     270                pass
     271             elif state == 0:
     272                #
     273                # Processing initial header
     274                #
     275                if len(tokens) == 2 and tokens[0] == "Problem:":
     276                   # the problem name may be absent, in which case the "Problem:" line will be skipped.
     277                   results.problem.name = tokens[1]
     278                elif len(tokens) == 2 and tokens[0] == "Rows:":
     279                   results.problem.number_of_constraints = eval(tokens[1])
     280                elif len(tokens) == 2 and tokens[0] == "Columns:":
     281                   lp_solution = True
     282                   results.problem.number_of_variables = eval(tokens[1])
     283                elif len(tokens) > 2 and tokens[0] == "Columns:":
     284                   lp_solution = False
     285                   results.problem.number_of_variables = eval(tokens[1])
     286                elif len(tokens) == 2 and tokens[0] == "Non-zeros:":
     287                   results.problem.number_of_nonzeros = eval(tokens[1])
     288                elif len(tokens) >= 2 and tokens[0] == "Status:":
     289                   if tokens[1] == "OPTIMAL":
     290                      soln.status = SolutionStatus.optimal
     291                   elif len(tokens) == 3 and tokens[1] == "INTEGER" and tokens[2] == "NON-OPTIMAL":
     292                      soln.status = SolutionStatus.bestSoFar
     293                   elif len(tokens) == 3 and tokens[1] == "INTEGER" and tokens[2] == "OPTIMAL":
     294                      soln.status = SolutionStatus.optimal
     295                   elif len(tokens) == 3 and tokens[1] == "INTEGER" and tokens[2] == "UNDEFINED":
     296                      soln.status = SolutionStatus.stoppedByLimit
     297                   elif (len(tokens) == 2) and (tokens[1] == "UNDEFINED"):
     298                      soln.status = SolutionStatus.infeasible
     299                   else:
     300                      print "WARNING: Read unknown status while parsing GLPK solution file - status="+" ".join(tokens[1:])
     301                elif len(tokens) >= 2 and tokens[0] == "Objective:":
     302                   if tokens[4] == "(MINimum)":
     303                      results.problem.sense = ProblemSense.minimize
     304                   else:
     305                      results.problem.sense = ProblemSense.maximize
     306                   soln.objective['f']=tokens[3]
     307                   if soln.status is SolutionStatus.optimal:
     308                      if tokens[4] == "(MINimum)":
     309                           results.problem.lower_bound = soln.objective['f'].value
     310                           if "upper_bound" in dir(results.problem):
     311                               del results.problem.upper_bound
     312                      else:
     313                           results.problem.upper_bound = soln.objective['f'].value
     314                           if "lower_bound" in dir(results.problem):
     315                               del results.problem.lower_bound
     316                   # the objective is the last entry in the problem section - move on to constraints.
     317                   state = 1
     318
     319             elif state == 1:
     320                #
     321                # Process Constraint Info
     322                #
     323
     324                if (len(tokens) == 2) and (len(active_constraint_name) == 0):
     325
     326                   number_of_constraints_read = number_of_constraints_read + 1
     327                   active_constraint_name = tokens[1].strip()
     328                   index = eval(tokens[0].strip())
     329
     330                   # sanity check - the indices should be in sequence.
     331                   if index != number_of_constraints_read:
     332                      raise ValueError,"***ERROR: Unexpected constraint index encountered on line="+line+"; expected value="+str(number_of_constraints_read)+"; actual value="+str(index)
     333
     334                else:
     335
     336                   index = None
     337                   activity = None
     338                   lower_bound = None
     339                   upper_bound = None
     340                   marginal = None
     341
     342                   # extract the field names and process accordingly. there
     343                   # is some wasted processing w.r.t. single versus double-line
     344                   # entries, but it's not significant enough to worry about.
     345
     346                   index_string = line[0:6].strip()
     347                   name_string = line[7:19].strip()
     348                   activity_string = line[23:36].strip()
     349                   lower_bound_string = line[37:50].strip()
     350                   upper_bound_string = line[51:64].strip()
     351
     352                   state_string = None
     353                   marginal_string = None
     354
     355                   # skip any headers
     356                   if (index_string == "------") or (index_string == "No."):
     357                      continue
     358
     359                   if len(index_string) > 0:
     360                      index = eval(index_string)
     361
     362                   if lp_solution is True:
     363                      state_string = line[20:22].strip()
     364                      marginal_string = line[65:78].strip()
     365                      if (activity_string != "< eps") and (len(activity_string) > 0):
     366                         activity = eval(activity_string)
     367                      else:
     368                         activity = 0.0
     369                      if (lower_bound_string != "< eps") and (len(lower_bound_string) > 0):
     370                         lower_bound = eval(lower_bound_string)
     371                      else:
     372                         lower_bound = 0.0
     373                      if state_string != "NS":
     374                         if (upper_bound_string != "< eps") and (len(upper_bound_string) > 0):
     375                            upper_bound = eval(upper_bound_string)
     376                         else:
     377                            upper_bound = 0.0
     378                      if (marginal_string != "< eps") and (len(marginal_string) > 0):
     379                         marginal = eval(marginal_string)
     380                      else:
     381                         marginal = 0.0
     382
     383                   else:
     384                       # no constraint-related attributes/values are extracted currently for MIPs.
     385                       pass
     386
     387                   constraint_name = None
     388                   if len(active_constraint_name) > 0:
     389                      # if there is an active constraint name, the identifier was
     390                      # too long for everything to be on a single line; the second
     391                      # line contains all of the value information.
     392                      constraint_name = active_constraint_name
     393                      active_constraint_name = ""
     394                   else:
     395                      # everything is on a single line.
     396                      constraint_name = name_string
     397                      number_of_constraints_read = number_of_constraints_read + 1
     398                      # sanity check - the indices should be in sequence.
     399                      if index != number_of_constraints_read:
     400                         raise ValueError,"***ERROR: Unexpected constraint index encountered on line="+line+"; expected value="+str(number_of_constraints_read)+"; actual value="+str(index)
     401
     402                   if lp_solution is True:
     403                      # GLPK doesn't report slacks directly.
     404                      constraint_dual = activity
     405                      if state_string == "B":
     406                         constraint_dual = 0.0
     407                      elif (state_string == "NS") or (state_string == "NL") or (state_string == "NU"):
     408                         constraint_dual = marginal
     409                      else:
     410                         raise ValueError, "Unknown status="+tokens[0]+" encountered for constraint="+active_constraint_name+" in line="+line+" of solution file="+self.soln_file
     411
     412                      if extract_duals is True:
     413                         soln.constraint[constraint_name].dual = constraint_dual
     414
     415                   else:
     416                      # there isn't anything interesting to do with constraints in the MIP case.
     417                      pass
     418
     419                   # if all of the constraints have been read, exit.
     420                   if number_of_constraints_read == results.problem.number_of_constraints:
     421                      state = 2
     422
     423             elif state == 2:
     424                #
     425                # Process Variable Info
     426                #
     427
     428                if (len(tokens) == 2) and (len(active_variable_name) == 0):
     429
     430                   # in the case of name over-flow, there are only two tokens
     431                   # on the first of two lines for the variable entry.
     432                   number_of_variables_read = number_of_variables_read + 1
     433                   active_variable_name = tokens[1].strip()
     434                   index = eval(tokens[0].strip())
     435
     436                   # sanity check - the indices should be in sequence.
     437                   if index != number_of_variables_read:
     438                      raise ValueError,"***ERROR: Unexpected variable index encountered on line="+line+"; expected value="+str(number_of_variables_read)+"; actual value="+str(index)
     439
     440                else:
     441
     442                   index = None
     443                   activity = None
     444                   lower_bound = None
     445                   upper_bound = None
     446                   marginal = None
     447
     448                   # extract the field names and process accordingly. there
     449                   # is some wasted processing w.r.t. single versus double-line
     450                   # entries, but it's not significant enough to worry about.
     451
     452                   index_string = line[0:6].strip()
     453                   name_string = line[7:19].strip()
     454                   activity_string = line[23:36].strip()
     455                   lower_bound_string = line[37:50].strip()
     456                   upper_bound_string = line[51:64].strip()
     457
     458                   state_string = None
     459                   marginal_string = None
     460
     461                   # skip any headers
     462                   if (index_string == "------") or (index_string == "No."):
     463                      continue
     464
     465                   if len(index_string) > 0:
     466                      index = eval(index_string)
     467
     468                   if lp_solution is True:
     469
     470                      state_string = line[20:22].strip()
     471                      marginal_string = line[65:78].strip()
     472
     473                      if (activity_string != "< eps") and (len(activity_string) > 0):
     474                         activity = eval(activity_string)
     475                      else:
     476                         activity = 0.0
     477                      if (lower_bound_string != "< eps") and (len(lower_bound_string) > 0):
     478                         lower_bound = eval(lower_bound_string)
     479                      else:
     480                         lower_bound = 0.0
     481                      if state_string != "NS":
     482                         if (upper_bound_string != "< eps") and (len(upper_bound_string) > 0):
     483                            upper_bound = eval(upper_bound_string)
     484                         else:
     485                            upper_bound = 0.0
     486                      if (marginal_string != "< eps") and (len(marginal_string) > 0):
     487                         marginal = eval(marginal_string)
     488                      else:
     489                         marginal = 0.0
     490
     491                   else:
     492
     493                      if (activity_string != "< eps") and (len(activity_string) > 0):
     494                         activity = eval(activity_string)
     495                      else:
     496                         activity = 0.0
     497
     498                   variable_name = None
     499                   if len(active_variable_name) > 0:
     500                      # if there is an active variable name, the identifier was
     501                      # too long for everything to be on a single line; the second
     502                      # line contains all of the value information.
     503                      variable_name = active_variable_name
     504                      active_variable_name = ""
     505                   else:
     506                      # everything is on a single line.
     507                      variable_name = name_string
     508                      number_of_variables_read = number_of_variables_read + 1
     509                      # sanity check - the indices should be in sequence.
     510                      if index != number_of_variables_read:
     511                         raise ValueError,"***ERROR: Unexpected variable index encountered on line="+line+"; expected value="+str(number_of_variables_read)+"; actual value="+str(index)
     512
     513                   if lp_solution is True:
     514                      # the "activity" column always specifies the variable value.
     515                      # embedding the if-then-else to validate the basis status.
     516                      # we are currently ignoring all bound-related information.
     517                      variable_value = None
     518                      if state_string in ('B', 'NL', 'NS', 'NU', 'NF'):
     519                         # NF = non-basic free (unbounded) variable
     520                         # NL = non-basic variable at its lower bound
     521                         # NU = non-basic variable at its upper bound
     522                         # NS = non-basic fixed variable
     523                         variable_value = activity
     524                      else:
     525                         raise ValueError, "Unknown status="+state_string+" encountered for variable="+variable_name+" in the following line of the GLPK solution file="+self.soln_file+":\n"+line
     526
     527                      soln.variable[variable_name].value = variable_value
     528                   else:
     529                      soln.variable[variable_name].value = activity
     530
     531                # if all of the variables have been read, exit.
     532                if number_of_variables_read == results.problem.number_of_variables:
     533                   state = -1
     534
     535             if state==-1:
     536                break
     537
     538           INPUT.close()
    575539
    576540        except ValueError, msg:
    577             INPUT.close()
    578             raise RuntimeError, msg
     541           INPUT.close()
     542           raise RuntimeError, msg
    579543        except Exception:
    580             INPUT.close()
    581             raise RuntimeError, "Unexpected input encountered in GLPK solution file, yielding parse failure; line="+str(line)
     544           INPUT.close()
     545           raise RuntimeError, "Unexpected input encountered in GLPK solution file, yielding parse failure; line="+str(line)
    582546
    583547class MockGLPK(GLPK,mockmip.MockMIP):
Note: See TracChangeset for help on using the changeset viewer.