Source code for pyomo.opt.results.results_

#  ___________________________________________________________________________
#
#  Pyomo: Python Optimization Modeling Objects
#  Copyright (c) 2008-2025
#  National Technology and Engineering Solutions of Sandia, LLC
#  Under the terms of Contract DE-NA0003525 with National Technology and
#  Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
#  rights in this software.
#  This software is distributed under the 3-clause BSD License.
#  ___________________________________________________________________________

import math
import sys
import copy
import json
import logging
import os.path

from pyomo.common.dependencies import yaml, yaml_load_args
import pyomo.opt
from pyomo.opt.results.container import undefined, ignore, ListContainer, MapContainer
import pyomo.opt.results.solution
from pyomo.opt.results.solution import default_print_options as dpo
import pyomo.opt.results.problem
import pyomo.opt.results.solver

from io import StringIO

logger = logging.getLogger(__name__)


def _guess_format(filename):
    "Return a standardized file format by looking at the filename extension"
    return {'.json': 'json', '.jsn': 'json', '.yaml': 'yaml', '.yml': 'yaml'}.get(
        os.path.splitext(filename)[1].lower(), None
    )


[docs] class SolverResults(MapContainer): undefined = undefined default_print_options = dpo
[docs] def __init__(self): super().__init__() self._sections = [] self._descriptions = {} self.add( 'problem', ListContainer(pyomo.opt.results.problem.ProblemInformation), False, "Problem Information", ) self.add( 'solver', ListContainer(pyomo.opt.results.solver.SolverInformation), False, "Solver Information", ) self.add( 'solution', pyomo.opt.results.solution.SolutionSet(), False, "Solution Information", )
def add(self, name, value, active, description): self.declare(name, value=value, active=active) tmp = self._convert(name) self._sections.append(tmp) self._descriptions[tmp] = description def json_repn(self, options=None): if options is None: return self._repn_(SolverResults.default_print_options) else: return self._repn_(options) def _repn_(self, option): if not option.schema and not self._active and not self._required: return ignore tmp = {} for key in self._sections: rep = dict.__getitem__(self, key)._repn_(option) if not rep == ignore: tmp[key] = rep return tmp def write(self, **kwds): _format = kwds.pop('format', None) if _format: _format = _format.lower() if 'filename' in kwds: filename = kwds.pop('filename') _guess = _guess_format(filename) if not _format: _format = _guess if _guess and _format != _guess: logger.warning( "writing results to file (%s) using what appears " "to be an incompatible format (%s)" % (filename, _format) ) if 'ostream' in kwds: raise ValueError("Cannot specify both filename and ostream") with open(filename, "w") as OUTPUT: return self.write(ostream=OUTPUT, format=_format, **kwds) ostream = kwds.pop('ostream', sys.stdout) if not _format: _format = 'yaml' if _format == 'yaml': self.write_yaml(ostream=ostream, **kwds) elif _format == 'json': self.write_json(ostream=ostream, **kwds) else: raise ValueError("Unknown results file format: %s" % (_format,)) def write_json(self, **kwds): ostream = kwds.pop('ostream', sys.stdout) option = copy.copy(SolverResults.default_print_options) # TODO: verify that we need this for-loop for key, val in kwds.items(): setattr(option, key, val) repn = self.json_repn(option) for soln in repn.get('Solution', []): for data in ['Variable', 'Constraint', 'Objective']: remove = set() if data not in soln: continue data_value = soln[data] if not isinstance(data_value, dict): continue if not data_value: # a variable/constraint/objective may have no # entries, e.g., if duals or slacks weren't # extracted in a solution. soln[data] = "No values" continue for kk, vv in data_value.items(): # TODO: remove this if-block. This is a hack if not type(vv) is dict: vv = {'Value': vv} tmp = {} for k, v in vv.items(): # TODO: remove this if-block. This is a hack if v is not None and math.fabs(v) > 1e-16: tmp[k] = v if len(tmp) > 0: soln[data][kk] = tmp else: remove.add((data, kk)) for item in remove: del soln[item[0]][item[1]] json.dump(repn, ostream, indent=4, sort_keys=True) def write_yaml(self, **kwds): ostream = kwds.pop('ostream', sys.stdout) option = copy.copy(SolverResults.default_print_options) # TODO: verify that we need this for-loop for key in kwds: setattr(option, key, kwds[key]) repn = self._repn_(option) ostream.write("# ==========================================================\n") ostream.write("# = Solver Results =\n") ostream.write("# ==========================================================\n") for key, item in self.items(): if not key in repn: continue ostream.write( "# ----------------------------------------------------------\n" ) ostream.write("# %s\n" % self._descriptions[key]) ostream.write( "# ----------------------------------------------------------\n" ) ostream.write(key + ": ") if isinstance(item, ListContainer): item.pprint(ostream, option, prefix="", repn=repn[key]) else: item.pprint(ostream, option, prefix=" ", repn=repn[key]) def read(self, **kwds): _format = kwds.pop('format', None) if _format: _format = _format.lower() if 'filename' in kwds: filename = kwds.pop('filename') if not _format: _format = _guess_format(filename) if 'istream' in kwds: raise ValueError("Cannot specify both filename and istream") with open(filename, "r") as INPUT: return self.read(istream=INPUT, format=_format, **kwds) istream = kwds.pop('istream', sys.stdin) if not _format or _format == 'yaml': repn = yaml.load(istream, **yaml_load_args) elif _format == 'json': repn = json.load(istream) else: raise ValueError(f"Unknown SolverResults format: '{_format}'") for key, item in repn.items(): dict.__getitem__(self, key).load(item) def __repr__(self): return str(self._repn_(SolverResults.default_print_options)) def __str__(self): ostream = StringIO() option = SolverResults.default_print_options self.pprint(ostream, option, repn=self._repn_(option)) return ostream.getvalue()
if __name__ == '__main__': results = SolverResults() results.write(schema=True) # print results