Exemple #1
0
    def _presolve(self, *args, **kwds):
        """
        Peform presolves.
        """
        TempfileManager.push()

        self._keepfiles = kwds.pop("keepfiles", False)
        self._define_signal_handlers = kwds.pop('use_signal_handling',None)

        OptSolver._presolve(self, *args, **kwds)

        #
        # Verify that the input problems exists
        #
        for filename in self._problem_files:
            if not os.path.exists(filename):
                msg = 'Solver failed to locate input problem file: %s'
                raise ValueError(msg % filename)
        #
        # Create command line
        #
        self._command = self.create_command_line(
            self.executable(), self._problem_files)

        self._log_file=self._command.log_file
        #
        # The pre-cleanup is probably unncessary, but also not harmful.
        #
        if (self._log_file is not None) and \
           os.path.exists(self._log_file):
            os.remove(self._log_file)
        if (self._soln_file is not None) and \
           os.path.exists(self._soln_file):
            os.remove(self._soln_file)
Exemple #2
0
 def tearDown(self):
     if os.path.exists("unknown.lp"):
         os.unlink("unknown.lp")
     TempfileManager.clear_tempfiles()
     if os.path.exists(os.path.join(currdir, 'result.yml')):
         os.remove(os.path.join(currdir, 'result.yml'))
     self.model = None
Exemple #3
0
    def _postsolve(self):

        # take care of the annoying (and empty) CPLEX temporary files in the current directory.
        # this approach doesn't seem overly efficient, but python os module functions don't
        # accept regular expression directly.
        filename_list = os.listdir(".")
        for filename in filename_list:
            # CPLEX temporary files come in two flavors - cplex.log and clone*.log.
            # the latter is the case for multi-processor environments.
            # IMPT: trap the possible exception raised by the file not existing.
            #       this can occur in pyro environments where > 1 workers are
            #       running CPLEX, and were started from the same directory.
            #       these logs don't matter anyway (we redirect everything),
            #       and are largely an annoyance.
            try:
                if re.match('cplex\.log', filename) != None:
                    os.remove(filename)
                elif re.match('clone\d+\.log', filename) != None:
                    os.remove(filename)
            except OSError:
                pass

        # let the base class deal with returning results.
        results = ILMLicensedSystemCallSolver._postsolve(self)

        # finally, clean any temporary files registered with the temp file
        # manager, created populated *directly* by this plugin. does not
        # include, for example, the execution script. but does include
        # the warm-start file.
        TempfileManager.pop(remove=not self._keepfiles)

        return results
Exemple #4
0
    def _presolve(self, *args, **kwds):
        """
        Peform presolves.
        """
        TempfileManager.push()

        self._keepfiles = kwds.pop("keepfiles", False)

        OptSolver._presolve(self, *args, **kwds)

        #
        # Verify that the input problems exists
        #
        for filename in self._problem_files:
            if not os.path.exists(filename):
                msg = 'Solver failed to locate input problem file: %s'
                raise ValueError(msg % filename)
        #
        # Create command line
        #
        self._command = self.create_command_line(
            self.executable(), self._problem_files)

        self._log_file=self._command.log_file
        #
        # The pre-cleanup is probably unncessary, but also not harmful.
        #
        if (self._log_file is not None) and \
           os.path.exists(self._log_file):
            os.remove(self._log_file)
        if (self._soln_file is not None) and \
           os.path.exists(self._soln_file):
            os.remove(self._soln_file)
Exemple #5
0
    def _presolve(self, *args, **kwds):

        # create a context in the temporary file manager for
        # this plugin - is "pop"ed in the _postsolve method.
        TempfileManager.push()

        # if the first argument is a string (representing a filename),
        # then we don't have an instance => the solver is being applied
        # to a file.
        self._warm_start_solve = kwds.pop('warmstart', False)
        self._warm_start_file_name = kwds.pop('warmstart_file', None)
        user_warmstart = False
        if self._warm_start_file_name is not None:
            user_warmstart = True

        # the input argument can currently be one of two things: an instance or a filename.
        # if a filename is provided and a warm-start is indicated, we go ahead and
        # create the temporary file - assuming that the user has already, via some external
        # mechanism, invoked warm_start() with a instance to create the warm start file.
        if self._warm_start_solve and \
                isinstance(args[0], string_types):
            # we assume the user knows what they are doing...
            pass
        elif self._warm_start_solve and \
                (not isinstance(args[0], string_types)):
            # assign the name of the warm start file *before* calling the base class
            # presolve - the base class method ends up creating the command line,
            # and the warm start file-name is (obviously) needed there.
            if self._warm_start_file_name is None:
                assert not user_warmstart
                self._warm_start_file_name = TempfileManager.\
                                             create_tempfile(suffix = '.cbc.soln')

        # let the base class handle any remaining keywords/actions.
        # let the base class handle any remaining keywords/actions.
        super(CBCSHELL, self)._presolve(*args, **kwds)

        # NB: we must let the base class presolve run first so that the
        # symbol_map is actually constructed!

        if (len(args) > 0) and (not isinstance(args[0], string_types)):

            if len(args) != 1:
                raise ValueError(
                    "CBCplugin _presolve method can only handle a single "
                    "problem instance - %s were supplied" % (len(args), ))

            # write the warm-start file - currently only supports MIPs.
            # we only know how to deal with a single problem instance.
            if self._warm_start_solve and (not user_warmstart):

                start_time = time.time()
                self._warm_start(args[0])
                end_time = time.time()
                if self._report_timing is True:
                    print("Warm start write time=%.2f seconds" %
                          (end_time - start_time))
Exemple #6
0
def run(args=None):
    #
    # Parse command-line options.
    #
    try:
        options_parser = \
            construct_options_parser("scenariotreeserver [options] hostname")
        (options, arguments) = options_parser.parse_args(args=args)
        if arguments:
            assert len(arguments) == 1
            options.host = arguments[0]
        else:
            options.host = None
    except SystemExit as _exc:
        # the parser throws a system exit if "-h" is specified - catch
        # it to exit gracefully.
        return _exc.code

    # for a one-pass execution, garbage collection doesn't make
    # much sense - so it is disabled by default. Because: It drops
    # the run-time by a factor of 3-4 on bigger instances.
    if options.disable_gc:
        gc.disable()
    else:
        gc.enable()

    if pstats_available and options.profile > 0:
        #
        # Call the main PH routine with profiling.
        #
        tfile = TempfileManager.create_tempfile(suffix=".profile")
        tmp = profile.runctx('run_server(options)',globals(),locals(),tfile)
        p = pstats.Stats(tfile).strip_dirs()
        p.sort_stats('time', 'cumulative')
        p = p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        p = p.sort_stats('cumulative','calls')
        p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        p = p.sort_stats('calls')
        p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        TempfileManager.clear_tempfiles()
        ans = [tmp, None]
    else:
        #
        # Call the main routine without profiling.
        #
        ans = run_server(options)

    gc.enable()

    return ans
Exemple #7
0
def run(args=None):
    #
    # Parse command-line options.
    #
    try:
        options_parser = \
            construct_options_parser("scenariotreeserver [options] hostname")
        (options, arguments) = options_parser.parse_args(args=args)
        if arguments:
            assert len(arguments) == 1
            options.host = arguments[0]
        else:
            options.host = None
    except SystemExit as _exc:
        # the parser throws a system exit if "-h" is specified - catch
        # it to exit gracefully.
        return _exc.code

    # for a one-pass execution, garbage collection doesn't make
    # much sense - so it is disabled by default. Because: It drops
    # the run-time by a factor of 3-4 on bigger instances.
    if options.disable_gc:
        gc.disable()
    else:
        gc.enable()

    if pstats_available and options.profile > 0:
        #
        # Call the main PH routine with profiling.
        #
        tfile = TempfileManager.create_tempfile(suffix=".profile")
        tmp = profile.runctx('run_server(options)', globals(), locals(), tfile)
        p = pstats.Stats(tfile).strip_dirs()
        p.sort_stats('time', 'cumulative')
        p = p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        p = p.sort_stats('cumulative', 'calls')
        p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        p = p.sort_stats('calls')
        p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        TempfileManager.clear_tempfiles()
        ans = [tmp, None]
    else:
        #
        # Call the main routine without profiling.
        #
        ans = run_server(options)

    gc.enable()

    return ans
Exemple #8
0
 def solve(self, model, timer: HierarchicalTimer = None):
     self.available(exception_flag=True)
     if timer is None:
         timer = HierarchicalTimer()
     try:
         TempfileManager.push()
         if self.config.filename is None:
             self._filename = TempfileManager.create_tempfile()
         else:
             self._filename = self.config.filename
         TempfileManager.add_tempfile(self._filename + '.lp', exists=False)
         TempfileManager.add_tempfile(self._filename + '.log', exists=False)
         timer.start('write lp file')
         self._writer.write(model, self._filename + '.lp', timer=timer)
         timer.stop('write lp file')
         res = self._apply_solver(timer)
         if self.config.report_timing:
             logger.info('\n' + str(timer))
         return res
     finally:
         # finally, clean any temporary files registered with the
         # temp file manager, created/populated *directly* by this
         # plugin.
         TempfileManager.pop(remove=not self.config.keepfiles)
         if not self.config.keepfiles:
             self._filename = None
Exemple #9
0
 def do_setup(self, flag):
     global tmpdir
     tmpdir = os.getcwd()
     os.chdir(currdir)
     TempfileManager.sequential_files(0)
     if flag:
         if not cplexamp_available:
             self.skipTest("The 'cplexamp' command is not available")
         self.asl = SolverFactory('asl:cplexamp')
     else:
         self.asl = SolverFactory('_mock_asl:cplexamp')
Exemple #10
0
    def _postsolve(self):

        # let the base class deal with returning results.
        results = super(CBCSHELL, self)._postsolve()

        # finally, clean any temporary files registered with the temp file
        # manager, created populated *directly* by this plugin. does not
        # include, for example, the execution script. but does include
        # the warm-start file.
        TempfileManager.pop(remove=not self._keepfiles)

        return results
Exemple #11
0
    def do_setup(self):
        global tmpdir
        tmpdir = os.getcwd()
        os.chdir(currdir)
        TempfileManager.sequential_files(0)

        self.scip = SolverFactory('scip', solver_io='nl')

        m = self.model = ConcreteModel()
        m.v = Var()
        m.o = Objective(expr=m.v)
        m.c = Constraint(expr=m.v >= 1)
Exemple #12
0
    def create_command_line(self, executable, problem_files):
        #
        # Define log file
        #
        if self._log_file is None:
            self._log_file = TempfileManager.create_tempfile(
                suffix='.glpk.log')

        #
        # Define solution file
        #
        self._glpfile = TempfileManager.create_tempfile(suffix='.glpk.glp')
        self._rawfile = TempfileManager.create_tempfile(suffix='.glpk.raw')
        self._soln_file = self._rawfile

        #
        # Define command line
        #
        cmd = [executable]
        if self._timer:
            cmd.insert(0, self._timer)
        for key in self.options:
            opt = self.options[key]
            if opt is None or (isinstance(opt, string_types)
                               and opt.strip() == ''):
                # Handle the case for options that must be
                # specified without a value
                cmd.append("--%s" % key)
            else:
                cmd.extend(["--%s" % key, str(opt)])
            #if isinstance(opt, basestring) and ' ' in opt:
            #    cmd.append('--%s "%s"' % (key, str(opt)))
            #else:
            #    cmd.append('--%s %s' % (key, str(opt)))

        if self._timelimit is not None and self._timelimit > 0.0:
            cmd.extend(['--tmlim', str(self._timelimit)])

        cmd.extend(['--write', self._rawfile])
        cmd.extend(['--wglp', self._glpfile])

        if self._problem_format == ProblemFormat.cpxlp:
            cmd.extend(['--cpxlp', problem_files[0]])
        elif self._problem_format == ProblemFormat.mps:
            cmd.extend(['--freemps', problem_files[0]])
        elif self._problem_format == ProblemFormat.mod:
            cmd.extend(['--math', problem_files[0]])
            for fname in problem_files[1:]:
                cmd.extend(['--data', fname])

        return Bunch(cmd=cmd, log_file=self._log_file, env=None)
Exemple #13
0
    def create_command_line(self, executable, problem_files):
        #
        # Define log file
        #
        if self._log_file is None:
            self._log_file = TempfileManager.create_tempfile(suffix='.glpk.log')

        #
        # Define solution file
        #
        self._glpfile = TempfileManager.create_tempfile(suffix='.glpk.glp')
        self._rawfile = TempfileManager.create_tempfile(suffix='.glpk.raw')
        self._soln_file = self._rawfile

        #
        # Define command line
        #
        cmd = [executable]
        if self._timer:
            cmd.insert(0, self._timer)
        for key in self.options:
            opt = self.options[key]
            if opt is None or (isinstance(opt, string_types) and opt.strip() == ''):
                # Handle the case for options that must be
                # specified without a value
                cmd.append("--%s" % key)
            else:
                cmd.extend(["--%s" % key, str(opt)])
            #if isinstance(opt, basestring) and ' ' in opt:
            #    cmd.append('--%s "%s"' % (key, str(opt)))
            #else:
            #    cmd.append('--%s %s' % (key, str(opt)))

        if self._timelimit is not None and self._timelimit > 0.0:
            cmd.extend(['--tmlim', str(self._timelimit)])

        cmd.extend(['--write', self._rawfile])
        cmd.extend(['--wglp', self._glpfile])

        if self._problem_format == ProblemFormat.cpxlp:
            cmd.extend(['--cpxlp', problem_files[0]])
        elif self._problem_format == ProblemFormat.mps:
            cmd.extend(['--freemps', problem_files[0]])
        elif self._problem_format == ProblemFormat.mod:
            cmd.extend(['--math', problem_files[0]])
            for fname in problem_files[1:]:
                cmd.extend(['--data', fname])

        return Bunch(cmd=cmd, log_file=self._log_file, env=None)
Exemple #14
0
def generate_scenario_tree_image(options):
    with ScenarioTreeInstanceFactory(options.model_location, options.scenario_tree_location) as factory:

        scenario_tree = factory.generate_scenario_tree(
            downsample_fraction=options.scenario_tree_downsample_fraction,
            bundles=options.scenario_bundle_specification,
            random_bundles=options.create_random_bundles,
            random_seed=options.scenario_tree_random_seed,
            verbose=options.verbose,
        )

        with TempfileManager.push():
            tmpdotfile = TempfileManager.create_tempfile(suffix=".dot")
            scenario_tree.save_to_dot(tmpdotfile)
            os.system("dot -Tpdf -o %s %s" % (options.output_file, tmpdotfile))
            print("Output Saved To: %s" % (options.output_file))
def generate_scenario_tree_image(options):
    with ScenarioTreeInstanceFactory(
            options.model_location, options.scenario_tree_location) as factory:

        scenario_tree = factory.generate_scenario_tree(
            downsample_fraction=options.scenario_tree_downsample_fraction,
            bundles=options.scenario_bundle_specification,
            random_bundles=options.create_random_bundles,
            random_seed=options.scenario_tree_random_seed,
            verbose=options.verbose)

        with TempfileManager.push():
            tmpdotfile = TempfileManager.create_tempfile(suffix=".dot")
            scenario_tree.save_to_dot(tmpdotfile)
            os.system('dot -Tpdf -o %s %s' % (options.output_file, tmpdotfile))
            print("Output Saved To: %s" % (options.output_file))
Exemple #16
0
    def _postsolve(self):

        if self._log_file is not None:
            OUTPUT = open(self._log_file, "w")
            OUTPUT.write("Solver command line: " + str(self._command.cmd) +
                         '\n')
            OUTPUT.write("\n")
            OUTPUT.write(self._log + '\n')
            OUTPUT.close()

        # JPW: The cleanup of the problem file probably shouldn't be here, but
        #   rather in the base OptSolver class. That would require movement of
        #   the keepfiles attribute and associated cleanup logic to the base
        #   class, which I didn't feel like doing at this present time. the
        #   base class remove_files method should clean up the problem file.

        if (self._log_file is not None) and \
           (not os.path.exists(self._log_file)):
            msg = "File '%s' not generated while executing %s"
            raise IOError(msg % (self._log_file, self.path))
        results = None

        if self._results_format is not None:
            results = self.process_output(self._rc)
            #
            # If keepfiles is true, then we pop the
            # TempfileManager context while telling it to
            # _not_ remove the files.
            #
            if not self._keepfiles:
                # in some cases, the solution filename is
                # not generated via the temp-file mechanism,
                # instead being automatically derived from
                # the input lp/nl filename. so, we may have
                # to clean it up manually.
                if (not self._soln_file is None) and \
                   os.path.exists(self._soln_file):
                    os.remove(self._soln_file)

        TempfileManager.pop(remove=not self._keepfiles)

        return results
Exemple #17
0
    def _postsolve(self):

        if self._log_file is not None:
            OUTPUT=open(self._log_file,"w")
            OUTPUT.write("Solver command line: "+str(self._command.cmd)+'\n')
            OUTPUT.write("\n")
            OUTPUT.write(self._log+'\n')
            OUTPUT.close()

        # JPW: The cleanup of the problem file probably shouldn't be here, but
        #   rather in the base OptSolver class. That would require movement of
        #   the keepfiles attribute and associated cleanup logic to the base
        #   class, which I didn't feel like doing at this present time. the
        #   base class remove_files method should clean up the problem file.

        if (self._log_file is not None) and \
           (not os.path.exists(self._log_file)):
            msg = "File '%s' not generated while executing %s"
            raise IOError(msg % (self._log_file, self.path))
        results = None

        if self._results_format is not None:
            results = self.process_output(self._rc)
            #
            # If keepfiles is true, then we pop the
            # TempfileManager context while telling it to
            # _not_ remove the files.
            #
            if not self._keepfiles:
                # in some cases, the solution filename is
                # not generated via the temp-file mechanism,
                # instead being automatically derived from
                # the input lp/nl filename. so, we may have
                # to clean it up manually.
                if (not self._soln_file is None) and \
                   os.path.exists(self._soln_file):
                    os.remove(self._soln_file)

        TempfileManager.pop(remove=not self._keepfiles)

        return results
Exemple #18
0
def run_command(command=None,
                parser=None,
                args=None,
                name='unknown',
                data=None,
                options=None):
    """
    Execute a function that processes command-line arguments and
    then calls a command-line driver.

    This function provides a generic facility for executing a command
    function is rather generic.  This function is segregated from
    the driver to enable profiling of the command-line execution.

    Required:
        command:    The name of a function that will be executed to perform process the command-line
                    options with a parser object.
        parser:     The parser object that is used by the command-line function.

    Optional:
        options:    If this is not None, then ignore the args option and use
                    this to specify command options.
        args:       Command-line arguments that are parsed.  If this value is `None`, then the
                    arguments in `sys.argv` are used to parse the command-line.
        name:       Specifying the name of the command-line (for error messages).
        data:       A container of labeled data.

    Returned:
        retval:     Return values from the command-line execution.
        errorcode:  0 if Pyomo ran successfully
    """
    #
    #
    # Parse command-line options
    #
    #
    retval = None
    errorcode = 0
    if options is None:
        try:
            if type(args) is argparse.Namespace:
                _options = args
            else:
                _options = parser.parse_args(args=args)
            # Replace the parser options object with a pyutilib.misc.Options object
            options = pyutilib.misc.Options()
            for key in dir(_options):
                if key[0] != '_':
                    val = getattr(_options, key)
                    if not isinstance(val, types.MethodType):
                        options[key] = val
        except SystemExit:
            # the parser throws a system exit if "-h" is specified - catch
            # it to exit gracefully.
            return Container(retval=retval, errorcode=errorcode)
    #
    # Configure loggers
    #
    configure_loggers(options=options)
    #
    # Setup I/O redirect to a file
    #
    logfile = options.runtime.logfile
    if not logfile is None:
        pyutilib.misc.setup_redirect(logfile)
    #
    # Call the main Pyomo runner with profiling
    #
    TempfileManager.push()
    pcount = options.runtime.profile_count
    if pcount > 0:
        if not pstats_available:
            if not logfile is None:
                pyutilib.misc.reset_redirect()
            msg = "Cannot use the 'profile' option.  The Python 'pstats' "    \
                  'package cannot be imported!'
            raise ValueError(msg)
        tfile = TempfileManager.create_tempfile(suffix=".profile")
        tmp = profile.runctx(
            command.__name__ + '(options=options,parser=parser)',
            command.__globals__, locals(), tfile)
        p = pstats.Stats(tfile).strip_dirs()
        p.sort_stats('time', 'cumulative')
        p = p.print_stats(pcount)
        p.print_callers(pcount)
        p.print_callees(pcount)
        p = p.sort_stats('cumulative', 'calls')
        p.print_stats(pcount)
        p.print_callers(pcount)
        p.print_callees(pcount)
        p = p.sort_stats('calls')
        p.print_stats(pcount)
        p.print_callers(pcount)
        p.print_callees(pcount)
        retval = tmp
    else:
        #
        # Call the main Pyomo runner without profiling
        #
        TempfileManager.push()
        try:
            retval = command(options=options, parser=parser)
        except SystemExit:
            err = sys.exc_info()[1]
            #
            # If debugging is enabled or the 'catch' option is specified, then
            # exit.  Otherwise, print an "Exiting..." message.
            #
            if __debug__ and (options.runtime.logging == 'debug'
                              or options.runtime.catch_errors):
                sys.exit(0)
            print('Exiting %s: %s' % (name, str(err)))
            errorcode = err.code
        except Exception:
            err = sys.exc_info()[1]
            #
            # If debugging is enabled or the 'catch' option is specified, then
            # pass the exception up the chain (to pyomo_excepthook)
            #
            if __debug__ and (options.runtime.logging == 'debug'
                              or options.runtime.catch_errors):
                if not logfile is None:
                    pyutilib.misc.reset_redirect()
                TempfileManager.pop(remove=not options.runtime.keep_files)
                raise

            if not options.model is None and not options.model.save_file is None:
                model = "model " + options.model.save_file
            else:
                model = "model"

            global filter_excepthook
            if filter_excepthook:
                action = "loading"
            else:
                action = "running"

            msg = "Unexpected exception while %s %s:\n" % (action, model)
            #
            # This handles the case where the error is propagated by a KeyError.
            # KeyError likes to pass raw strings that don't handle newlines
            # (they translate "\n" to "\\n"), as well as tacking on single
            # quotes at either end of the error message. This undoes all that.
            #
            errStr = str(err)
            if type(err) == KeyError and errStr != "None":
                errStr = str(err).replace(r"\n", "\n")[1:-1]

            logging.getLogger('pyomo.core').error(msg + errStr)
            errorcode = 1

    if not logfile is None:
        pyutilib.misc.reset_redirect()

    if options.runtime.disable_gc:
        gc.enable()
    TempfileManager.pop(remove=not options.runtime.keep_files)
    return Container(retval=retval, errorcode=errorcode)
Exemple #19
0
    def create_command_line(self, executable, problem_files):

        #
        # Define log file
        # The log file in CPLEX contains the solution trace, but the solver status can be found in the solution file.
        #
        if self._log_file is None:
            self._log_file = TempfileManager.\
                            create_tempfile(suffix = '.gurobi.log')

        #
        # Define solution file
        # As indicated above, contains (in XML) both the solution and solver status.
        #
        if self._soln_file is None:
            self._soln_file = TempfileManager.\
                              create_tempfile(suffix = '.gurobi.txt')

        #
        # Write the GUROBI execution script
        #

        problem_filename = self._problem_files[0]
        solution_filename = self._soln_file
        warmstart_filename = self._warm_start_file_name

        # translate the options into a normal python dictionary, from a
        # pyutilib SectionWrapper - the
        # gurobi_run function doesn't know about pyomo, so the translation
        # is necessary.
        options_dict = {}
        for key in self.options:
            options_dict[key] = self.options[key]

        # NOTE: the gurobi shell is independent of Pyomo python virtualized environment, so any
        #       imports - specifically that required to get GUROBI_RUN - must be handled explicitly.
        # NOTE: The gurobi plugin (GUROBI.py) and GUROBI_RUN.py live in the same directory.
        script = "import sys\n"
        script += "from gurobipy import *\n"
        script += "sys.path.append(%r)\n" % os.path.dirname(__file__)
        script += "from GUROBI_RUN import *\n"
        script += "gurobi_run("
        mipgap = float(self.options.mipgap) if \
                 self.options.mipgap is not None else \
                 None
        for x in (problem_filename, warmstart_filename, solution_filename,
                  None, options_dict, self._suffixes):
            script += "%r," % x
        script += ")\n"
        script += "quit()\n"

        # dump the script and warm-start file names for the
        # user if we're keeping files around.
        if self._keepfiles:
            script_fname = TempfileManager.create_tempfile(
                suffix='.gurobi.script')
            script_file = open(script_fname, 'w')
            script_file.write(script)
            script_file.close()

            print("Solver script file: '%s'" % script_fname)
            if self._warm_start_solve and \
               (self._warm_start_file_name is not None):
                print("Solver warm-start file: " + self._warm_start_file_name)

        #
        # Define command line
        #
        cmd = [executable]
        if self._timer:
            cmd.insert(0, self._timer)
        return Bunch(cmd=cmd, script=script, log_file=self._log_file, env=None)
Exemple #20
0
 def tearDownModule():
     TempfileManager.clear_tempfiles()
     TempfileManager.tempdir = None
     TempfileManager.unique_files()
Exemple #21
0
def launch_command(command,
                   options,
                   cmd_args=None,
                   cmd_kwds=None,
                   error_label="",
                   disable_gc=False,
                   profile_count=0,
                   log_level=logging.INFO,
                   traceback=False):
    # This is not the effective level, but the
    # level on the current logger. We want to
    # return the logger to its original state
    # before this function exits
    prev_log_level = logger.level
    logger.setLevel(log_level)

    if cmd_args is None:
        cmd_args = ()
    if cmd_kwds is None:
        cmd_kwds = {}

    #
    # Control the garbage collector - more critical than I would like
    # at the moment.
    #
    with PauseGC(disable_gc) as pgc:

        #
        # Run command - precise invocation depends on whether we want
        # profiling output, traceback, etc.
        #

        rc = 0

        if pstats_available and (profile_count > 0):
            #
            # Call the main routine with profiling.
            #
            try:
                tfile = TempfileManager.create_tempfile(suffix=".profile")
                tmp = profile.runctx('command(options, *cmd_args, **cmd_kwds)',
                                     globals(),
                                     locals(),
                                     tfile)
                p = pstats.Stats(tfile).strip_dirs()
                p.sort_stats('time', 'cumulative')
                p = p.print_stats(profile_count)
                p.print_callers(profile_count)
                p.print_callees(profile_count)
                p = p.sort_stats('cumulative','calls')
                p.print_stats(profile_count)
                p.print_callers(profile_count)
                p.print_callees(profile_count)
                p = p.sort_stats('calls')
                p.print_stats(profile_count)
                p.print_callers(profile_count)
                p.print_callees(profile_count)
                TempfileManager.clear_tempfiles()
                rc = tmp
            finally:
                logger.setLevel(prev_log_level)
        else:

            #
            # Call the main PH routine without profiling.
            #
            if traceback:
                try:
                    rc = command(options, *cmd_args, **cmd_kwds)
                finally:
                    logger.setLevel(prev_log_level)
            else:
                try:
                    try:
                        rc = command(options, *cmd_args, **cmd_kwds)
                    except ValueError:
                        sys.stderr.write(error_label+"VALUE ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except KeyError:
                        sys.stderr.write(error_label+"KEY ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except TypeError:
                        sys.stderr.write(error_label+"TYPE ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except NameError:
                        sys.stderr.write(error_label+"NAME ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except IOError:
                        sys.stderr.write(error_label+"IO ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except ConverterError:
                        sys.stderr.write(error_label+"CONVERTER ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except pyutilib.common.ApplicationError:
                        sys.stderr.write(error_label+"APPLICATION ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except RuntimeError:
                        sys.stderr.write(error_label+"RUN-TIME ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except:
                        sys.stderr.write(error_label+
                                         "Encountered unhandled exception:\n")
                        if len(sys.exc_info()) > 1:
                            sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        else:
                            traceback.print_exc(file=sys.stderr)
                        raise
                except:
                    sys.stderr.write("\n")
                    sys.stderr.write(
                        "To obtain further information regarding the "
                        "source of the exception, use the "
                        "--traceback option\n")
                    rc = 1

    #
    # TODO: Once we incorporate options registration into
    #       all of the PySP commands we will assume the
    #       options object is always a PySPConfigBlock
    #
    if isinstance(options, PySPConfigBlock):
        options.check_usage(error=False)

    logger.setLevel(prev_log_level)

    return rc
Exemple #22
0
    def _solve_impl(self,
                    sp,
                    keep_solver_files=False,
                    output_solver_log=False,
                    symbolic_solver_labels=False):

        if len(sp.scenario_tree.stages) > 2:
            raise ValueError("SD solver does not handle more "
                             "than 2 time-stages")

        if sp.objective_sense == maximize:
            raise ValueError("SD solver does not yet handle "
                             "maximization problems")

        TempfileManager.push()
        try:

            #
            # Setup the SD working directory
            #

            working_directory = TempfileManager.create_tempdir()
            config_filename = os.path.join(working_directory, "config.sd")
            sdinput_directory = os.path.join(working_directory, "sdinput",
                                             "pysp_model")
            sdoutput_directory = os.path.join(working_directory, "sdoutput",
                                              "pysp_model")
            logfile = os.path.join(working_directory, "sd.log")

            os.makedirs(sdinput_directory)
            assert os.path.exists(sdinput_directory)
            assert not os.path.exists(sdoutput_directory)
            self._write_config(config_filename)

            if self.get_option('single_replication'):
                solution_filename = os.path.join(
                    sdoutput_directory, "pysp_model.detailed_rep_soln.out")
            else:
                solution_filename = os.path.join(
                    sdoutput_directory, "pysp_model.detailed_soln.out")

            #
            # Create the SD input files
            #

            io_options = {'symbolic_solver_labels': symbolic_solver_labels}

            symbol_map = None
            if isinstance(sp, ImplicitSP):
                symbol_map = pyomo.pysp.smps.smpsutils.\
                             convert_implicit(
                                 sdinput_directory,
                                 "pysp_model",
                                 sp,
                                 core_format='mps',
                                 io_options=io_options)
            else:
                pyomo.pysp.smps.smpsutils.\
                    convert_explicit(
                        sdinput_directory,
                        "pysp_model",
                        sp,
                        core_format='mps',
                        io_options=io_options)

            #
            # Launch SD
            #

            if keep_solver_files:
                print("Solver working directory: '%s'" % (working_directory))
                print("Solver log file: '%s'" % (logfile))

            start = time.time()
            rc, log = pyutilib.subprocess.run(self.get_option("sd_executable"),
                                              cwd=working_directory,
                                              stdin="pysp_model",
                                              outfile=logfile,
                                              tee=output_solver_log)
            stop = time.time()
            assert os.path.exists(sdoutput_directory)

            #
            # Parse the SD solution
            #

            xhat, results = self._read_solution(solution_filename)

            results.solver_time = stop - start

            if symbol_map is not None:
                # load the first stage variable solution into
                # the reference model
                for symbol, varvalue in xhat.items():
                    symbol_map.bySymbol[symbol]().value = varvalue
            else:
                # TODO: this is a hack for the non-implicit SP case
                #       so that this solver can still be run using
                #       the explicit scenario intput representation
                results.xhat = xhat

        finally:

            #
            # cleanup
            #
            TempfileManager.pop(remove=not keep_solver_files)

        return results
Exemple #23
0
def launch_command(command,
                   options,
                   cmd_args=None,
                   cmd_kwds=None,
                   error_label="",
                   disable_gc=False,
                   profile_count=0,
                   log_level=logging.INFO,
                   traceback=False):
    # This is not the effective level, but the
    # level on the current logger. We want to
    # return the logger to its original state
    # before this function exits
    prev_log_level = logger.level
    logger.setLevel(log_level)

    if cmd_args is None:
        cmd_args = ()
    if cmd_kwds is None:
        cmd_kwds = {}

    #
    # Control the garbage collector - more critical than I would like
    # at the moment.
    #
    with PauseGC(disable_gc) as pgc:

        #
        # Run command - precise invocation depends on whether we want
        # profiling output, traceback, etc.
        #

        rc = 0

        if pstats_available and (profile_count > 0):
            #
            # Call the main routine with profiling.
            #
            try:
                tfile = TempfileManager.create_tempfile(suffix=".profile")
                tmp = profile.runctx('command(options, *cmd_args, **cmd_kwds)',
                                     globals(), locals(), tfile)
                p = pstats.Stats(tfile).strip_dirs()
                p.sort_stats('time', 'cumulative')
                p = p.print_stats(profile_count)
                p.print_callers(profile_count)
                p.print_callees(profile_count)
                p = p.sort_stats('cumulative', 'calls')
                p.print_stats(profile_count)
                p.print_callers(profile_count)
                p.print_callees(profile_count)
                p = p.sort_stats('calls')
                p.print_stats(profile_count)
                p.print_callers(profile_count)
                p.print_callees(profile_count)
                TempfileManager.clear_tempfiles()
                rc = tmp
            finally:
                logger.setLevel(prev_log_level)
        else:

            #
            # Call the main PH routine without profiling.
            #
            if traceback:
                try:
                    rc = command(options, *cmd_args, **cmd_kwds)
                finally:
                    logger.setLevel(prev_log_level)
            else:
                try:
                    try:
                        rc = command(options, *cmd_args, **cmd_kwds)
                    except ValueError:
                        sys.stderr.write(error_label + "VALUE ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        raise
                    except KeyError:
                        sys.stderr.write(error_label + "KEY ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        raise
                    except TypeError:
                        sys.stderr.write(error_label + "TYPE ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        raise
                    except NameError:
                        sys.stderr.write(error_label + "NAME ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        raise
                    except IOError:
                        sys.stderr.write(error_label + "IO ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        raise
                    except ConverterError:
                        sys.stderr.write(error_label + "CONVERTER ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        raise
                    except pyutilib.common.ApplicationError:
                        sys.stderr.write(error_label + "APPLICATION ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        raise
                    except RuntimeError:
                        sys.stderr.write(error_label + "RUN-TIME ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        raise
                    except:
                        sys.stderr.write(error_label +
                                         "Encountered unhandled exception:\n")
                        if len(sys.exc_info()) > 1:
                            sys.stderr.write(str(sys.exc_info()[1]) + "\n")
                        else:
                            traceback.print_exc(file=sys.stderr)
                        raise
                except:
                    sys.stderr.write("\n")
                    sys.stderr.write(
                        "To obtain further information regarding the "
                        "source of the exception, use the "
                        "--traceback option\n")
                    rc = 1

    #
    # TODO: Once we incorporate options registration into
    #       all of the PySP commands we will assume the
    #       options object is always a PySPConfigBlock
    #
    if isinstance(options, PySPConfigBlock):
        options.check_usage(error=False)

    logger.setLevel(prev_log_level)

    return rc
Exemple #24
0
    def create_command_line(self, executable, problem_files):
        #
        # Define the log file
        #
        if self._log_file is None:
            self._log_file = TempfileManager.create_tempfile(suffix=".cbc.log")

        #
        # Define the solution file
        #
        # the prefix of the problem filename is required because CBC has a specific
        # and automatic convention for generating the output solution filename.
        # the extracted prefix is the same name as the input filename, e.g., minus
        # the ".lp" extension.
        problem_filename_prefix = problem_files[0]
        if '.' in problem_filename_prefix:
            tmp = problem_filename_prefix.split('.')
            if len(tmp) > 2:
                problem_filename_prefix = '.'.join(tmp[:-1])
            else:
                problem_filename_prefix = tmp[0]
        if self._results_format is ResultsFormat.sol:
            self._soln_file = problem_filename_prefix + ".sol"
        else:
            self._soln_file = problem_filename_prefix + ".soln"

        #
        # Define the results file (if the sol external parser is used)
        #
        # results in CBC are split across the log file (solver statistics) and
        # the solution file (solutions!)
        if self._results_format is ResultsFormat.sol:
            self._results_file = self._soln_file

        def _check_and_escape_options(options):
            for key, val in iteritems(self.options):
                tmp_k = str(key)
                _bad = ' ' in tmp_k

                tmp_v = str(val)
                if ' ' in tmp_v:
                    if '"' in tmp_v:
                        if "'" in tmp_v:
                            _bad = True
                        else:
                            tmp_v = "'" + tmp_v + "'"
                    else:
                        tmp_v = '"' + tmp_v + '"'

                if _bad:
                    raise ValueError("Unable to properly escape solver option:"
                                     "\n\t%s=%s" % (key, val))
                yield (tmp_k, tmp_v)

        #
        # Define command line
        #
        cmd = [executable]
        if self._timer:
            cmd.insert(0, self._timer)
        if self._problem_format == ProblemFormat.nl:
            cmd.append(problem_files[0])
            cmd.append('-AMPL')

            if self._timelimit is not None and self._timelimit > 0.0:
                cmd.extend(['-sec', str(self._timelimit)])
                cmd.extend(['-timeMode', "elapsed"])
            if "debug" in self.options:
                cmd.extend(["-log", "5"])
            for key, val in _check_and_escape_options(self.options):
                if key == 'solver':
                    continue
                cmd.append(key + "=" + val)
            os.environ['cbc_options'] = "printingOptions=all"
            #cmd.extend(["-printingOptions=all",
            #"-stat"])
        else:
            if self._timelimit is not None and self._timelimit > 0.0:
                cmd.extend(['-sec', str(self._timelimit)])
                cmd.extend(['-timeMode', "elapsed"])
            if "debug" in self.options:
                cmd.extend(["-log", "5"])
            # these must go after options that take a value
            action_options = []
            for key, val in _check_and_escape_options(self.options):
                if val.strip() != '':
                    cmd.extend(['-' + key, val])
                else:
                    action_options.append('-' + key)
            cmd.extend(
                ["-printingOptions", "all", "-import", problem_files[0]])
            cmd.extend(action_options)
            if self._warm_start_solve:
                cmd.extend(["-mipstart", self._warm_start_file_name])
            cmd.extend(["-stat=1", "-solve", "-solu", self._soln_file])

        return Bunch(cmd=cmd, log_file=self._log_file, env=None)
Exemple #25
0
    def _postsolve(self):
        # the only suffixes that we extract from XPRESS are
        # constraint duals, constraint slacks, and variable
        # reduced-costs. scan through the solver suffix list
        # and throw an exception if the user has specified
        # any others.
        extract_duals = False
        extract_slacks = False
        extract_reduced_costs = False
        for suffix in self._suffixes:
            flag = False
            if re.match(suffix, "dual"):
                extract_duals = True
                flag = True
            if re.match(suffix, "slack"):
                extract_slacks = True
                flag = True
            if re.match(suffix, "rc"):
                extract_reduced_costs = True
                flag = True
            if not flag:
                raise RuntimeError(
                    "***The xpress_direct solver plugin cannot extract solution suffix="
                    + suffix)

        xprob = self._solver_model
        xp = self._xpress
        xprob_attrs = xprob.attributes

        ## XPRESS's status codes depend on this
        ## (number of integer vars > 0) or (number of special order sets > 0)
        is_mip = (xprob_attrs.mipents > 0) or (xprob_attrs.sets > 0)

        if is_mip:
            if extract_reduced_costs:
                logger.warning("Cannot get reduced costs for MIP.")
            if extract_duals:
                logger.warning("Cannot get duals for MIP.")
            extract_reduced_costs = False
            extract_duals = False

        self.results = SolverResults()
        soln = Solution()

        self.results.solver.name = self._name
        self.results.solver.wallclock_time = self._opt_time

        if is_mip:
            status = xprob_attrs.mipstatus
            mip_sols = xprob_attrs.mipsols
            if status == xp.mip_not_loaded:
                self.results.solver.status = SolverStatus.aborted
                self.results.solver.termination_message = "Model is not loaded; no solution information is available."
                self.results.solver.termination_condition = TerminationCondition.error
                soln.status = SolutionStatus.unknown
            #no MIP solution, first LP did not solve, second LP did, third search started but incomplete
            elif status == xp.mip_lp_not_optimal \
                    or status == xp.mip_lp_optimal \
                    or status == xp.mip_no_sol_found:
                self.results.solver.status = SolverStatus.aborted
                self.results.solver.termination_message = "Model is loaded, but no solution information is available."
                self.results.solver.termination_condition = TerminationCondition.error
                soln.status = SolutionStatus.unknown
            elif status == xp.mip_solution:  # some solution available
                self.results.solver.status = SolverStatus.warning
                self.results.solver.termination_message = "Unable to satisfy optimality tolerances; a sub-optimal " \
                                                          "solution is available."
                self.results.solver.termination_condition = TerminationCondition.other
                soln.status = SolutionStatus.feasible
            elif status == xp.mip_infeas:  # MIP proven infeasible
                self.results.solver.status = SolverStatus.warning
                self.results.solver.termination_message = "Model was proven to be infeasible"
                self.results.solver.termination_condition = TerminationCondition.infeasible
                soln.status = SolutionStatus.infeasible
            elif status == xp.mip_optimal:  # optimal
                self.results.solver.status = SolverStatus.ok
                self.results.solver.termination_message = "Model was solved to optimality (subject to tolerances), " \
                                                          "and an optimal solution is available."
                self.results.solver.termination_condition = TerminationCondition.optimal
                soln.status = SolutionStatus.optimal
            elif status == xp.mip_unbounded and mip_sols > 0:
                self.results.solver.status = SolverStatus.warning
                self.results.solver.termination_message = "LP relaxation was proven to be unbounded, " \
                                                          "but a solution is available."
                self.results.solver.termination_condition = TerminationCondition.unbounded
                soln.status = SolutionStatus.unbounded
            elif status == xp.mip_unbounded and mip_sols <= 0:
                self.results.solver.status = SolverStatus.warning
                self.results.solver.termination_message = "LP relaxation was proven to be unbounded."
                self.results.solver.termination_condition = TerminationCondition.unbounded
                soln.status = SolutionStatus.unbounded
            else:
                self.results.solver.status = SolverStatus.error
                self.results.solver.termination_message = \
                    ("Unhandled Xpress solve status "
                     "("+str(status)+")")
                self.results.solver.termination_condition = TerminationCondition.error
                soln.status = SolutionStatus.error
        else:  ## an LP, we'll check the lpstatus
            status = xprob_attrs.lpstatus
            if status == xp.lp_unstarted:
                self.results.solver.status = SolverStatus.aborted
                self.results.solver.termination_message = "Model is not loaded; no solution information is available."
                self.results.solver.termination_condition = TerminationCondition.error
                soln.status = SolutionStatus.unknown
            elif status == xp.lp_optimal:
                self.results.solver.status = SolverStatus.ok
                self.results.solver.termination_message = "Model was solved to optimality (subject to tolerances), " \
                                                          "and an optimal solution is available."
                self.results.solver.termination_condition = TerminationCondition.optimal
                soln.status = SolutionStatus.optimal
            elif status == xp.lp_infeas:
                self.results.solver.status = SolverStatus.warning
                self.results.solver.termination_message = "Model was proven to be infeasible"
                self.results.solver.termination_condition = TerminationCondition.infeasible
                soln.status = SolutionStatus.infeasible
            elif status == xp.lp_cutoff:
                self.results.solver.status = SolverStatus.ok
                self.results.solver.termination_message = "Optimal objective for model was proven to be worse than the " \
                                                          "cutoff value specified; a solution is available."
                self.results.solver.termination_condition = TerminationCondition.minFunctionValue
                soln.status = SolutionStatus.optimal
            elif status == xp.lp_unfinished:
                self.results.solver.status = SolverStatus.aborted
                self.results.solver.termination_message = "Optimization was terminated by the user."
                self.results.solver.termination_condition = TerminationCondition.error
                soln.status = SolutionStatus.error
            elif status == xp.lp_unbounded:
                self.results.solver.status = SolverStatus.warning
                self.results.solver.termination_message = "Model was proven to be unbounded."
                self.results.solver.termination_condition = TerminationCondition.unbounded
                soln.status = SolutionStatus.unbounded
            elif status == xp.lp_cutoff_in_dual:
                self.results.solver.status = SolverStatus.ok
                self.results.solver.termination_message = "Xpress reported the LP was cutoff in the dual."
                self.results.solver.termination_condition = TerminationCondition.minFunctionValue
                soln.status = SolutionStatus.optimal
            elif status == xp.lp_unsolved:
                self.results.solver.status = SolverStatus.error
                self.results.solver.termination_message = "Optimization was terminated due to unrecoverable numerical " \
                                                          "difficulties."
                self.results.solver.termination_condition = TerminationCondition.error
                soln.status = SolutionStatus.error
            elif status == xp.lp_nonconvex:
                self.results.solver.status = SolverStatus.error
                self.results.solver.termination_message = "Optimization was terminated because nonconvex quadratic data " \
                                                          "were found."
                self.results.solver.termination_condition = TerminationCondition.error
                soln.status = SolutionStatus.error
            else:
                self.results.solver.status = SolverStatus.error
                self.results.solver.termination_message = \
                    ("Unhandled Xpress solve status "
                     "("+str(status)+")")
                self.results.solver.termination_condition = TerminationCondition.error
                soln.status = SolutionStatus.error

        self.results.problem.name = xprob_attrs.matrixname

        if xprob_attrs.objsense == 1.0:
            self.results.problem.sense = minimize
        elif xprob_attrs.objsense == -1.0:
            self.results.problem.sense = maximize
        else:
            raise RuntimeError(
                'Unrecognized Xpress objective sense: {0}'.format(
                    xprob_attrs.objsense))

        self.results.problem.upper_bound = None
        self.results.problem.lower_bound = None
        if not is_mip:  #LP or continuous problem
            try:
                self.results.problem.upper_bound = xprob_attrs.lpobjval
                self.results.problem.lower_bound = xprob_attrs.lpobjval
            except (self._XpressException, AttributeError):
                pass
        elif xprob_attrs.objsense == 1.0:  # minimizing MIP
            try:
                self.results.problem.upper_bound = xprob_attrs.mipbestobjval
            except (self._XpressException, AttributeError):
                pass
            try:
                self.results.problem.lower_bound = xprob_attrs.bestbound
            except (self._XpressException, AttributeError):
                pass
        elif xprob_attrs.objsense == -1.0:  # maximizing MIP
            try:
                self.results.problem.upper_bound = xprob_attrs.bestbound
            except (self._XpressException, AttributeError):
                pass
            try:
                self.results.problem.lower_bound = xprob_attrs.mipbestobjval
            except (self._XpressException, AttributeError):
                pass
        else:
            raise RuntimeError(
                'Unrecognized xpress objective sense: {0}'.format(
                    xprob_attrs.objsense))

        try:
            soln.gap = self.results.problem.upper_bound - self.results.problem.lower_bound
        except TypeError:
            soln.gap = None

        self.results.problem.number_of_constraints = xprob_attrs.rows + xprob_attrs.sets + xprob_attrs.qconstraints
        self.results.problem.number_of_nonzeros = xprob_attrs.elems
        self.results.problem.number_of_variables = xprob_attrs.cols
        self.results.problem.number_of_integer_variables = xprob_attrs.mipents
        self.results.problem.number_of_continuous_variables = xprob_attrs.cols - xprob_attrs.mipents
        self.results.problem.number_of_objectives = 1
        self.results.problem.number_of_solutions = xprob_attrs.mipsols if is_mip else 1

        # if a solve was stopped by a limit, we still need to check to
        # see if there is a solution available - this may not always
        # be the case, both in LP and MIP contexts.
        if self._save_results:
            """
            This code in this if statement is only needed for backwards compatability. It is more efficient to set
            _save_results to False and use load_vars, load_duals, etc.
            """
            if xprob_attrs.lpstatus in \
                    [xp.lp_optimal, xp.lp_cutoff, xp.lp_cutoff_in_dual] or \
                    xprob_attrs.mipsols > 0:
                soln_variables = soln.variable
                soln_constraints = soln.constraint

                xpress_vars = list(self._solver_var_to_pyomo_var_map.keys())
                var_vals = xprob.getSolution(xpress_vars)
                for xpress_var, val in zip(xpress_vars, var_vals):
                    pyomo_var = self._solver_var_to_pyomo_var_map[xpress_var]
                    if self._referenced_variables[pyomo_var] > 0:
                        pyomo_var.stale = False
                        soln_variables[xpress_var.name] = {"Value": val}

                if extract_reduced_costs:
                    vals = xprob.getRCost(xpress_vars)
                    for xpress_var, val in zip(xpress_vars, vals):
                        pyomo_var = self._solver_var_to_pyomo_var_map[
                            xpress_var]
                        if self._referenced_variables[pyomo_var] > 0:
                            soln_variables[xpress_var.name]["Rc"] = val

                if extract_duals or extract_slacks:
                    xpress_cons = list(
                        self._solver_con_to_pyomo_con_map.keys())
                    for con in xpress_cons:
                        soln_constraints[con.name] = {}

                if extract_duals:
                    vals = xprob.getDual(xpress_cons)
                    for val, con in zip(vals, xpress_cons):
                        soln_constraints[con.name]["Dual"] = val

                if extract_slacks:
                    vals = xprob.getSlack(xpress_cons)
                    for con, val in zip(xpress_cons, vals):
                        if con in self._range_constraints:
                            ## for xpress, the slack on a range constraint
                            ## is based on the upper bound
                            lb = con.lb
                            ub = con.ub
                            ub_s = val
                            expr_val = ub - ub_s
                            lb_s = lb - expr_val
                            if abs(ub_s) > abs(lb_s):
                                soln_constraints[con.name]["Slack"] = ub_s
                            else:
                                soln_constraints[con.name]["Slack"] = lb_s
                        else:
                            soln_constraints[con.name]["Slack"] = val

        elif self._load_solutions:
            if xprob_attrs.lpstatus == xp.lp_optimal and \
                    ((not is_mip) or (xprob_attrs.mipsols > 0)):

                self._load_vars()

                if extract_reduced_costs:
                    self._load_rc()

                if extract_duals:
                    self._load_duals()

                if extract_slacks:
                    self._load_slacks()

        self.results.solution.insert(soln)

        # finally, clean any temporary files registered with the temp file
        # manager, created populated *directly* by this plugin.
        TempfileManager.pop(remove=not self._keepfiles)
        return DirectOrPersistentSolver._postsolve(self)
Exemple #26
0
def main(args=None):
    #
    # Top-level command that executes the extensive form writer.
    # This is segregated from run_ef_writer to enable profiling.
    #

    #
    # Import plugins
    #
    import pyomo.environ
    #
    # Parse command-line options.
    #
    try:
        options_parser = construct_smps_options_parser("runph [options]")
        (options, args) = options_parser.parse_args(args=args)
    except SystemExit as _exc:
        # the parser throws a system exit if "-h" is specified - catch
        # it to exit gracefully.
        return _exc.code

    #
    # Control the garbage collector - more critical than I would like
    # at the moment.
    #

    if options.disable_gc:
        gc.disable()
    else:
        gc.enable()

    #
    # Run PH - precise invocation depends on whether we want profiling
    # output.
    #

    # if an exception is triggered and traceback is enabled, 'ans'
    # won't have a value and the return statement from this function
    # will flag an error, masking the stack trace that you really want
    # to see.
    ans = None

    if pstats_available and options.profile > 0:
        #
        # Call the main routine with profiling.
        #
        tfile = TempfileManager.create_tempfile(suffix=".profile")
        tmp = profile.runctx('exec_pysp2smps(options)',globals(),locals(),tfile)
        p = pstats.Stats(tfile).strip_dirs()
        p.sort_stats('time', 'cumulative')
        p = p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        p = p.sort_stats('cumulative','calls')
        p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        p = p.sort_stats('calls')
        p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        TempfileManager.clear_tempfiles()
        ans = [tmp, None]
    else:
        #
        # Call the main routine without profiling.
        #

        if options.traceback:
            ans = exec_pysp2smps(options)
        else:
            try:
                try:
                    ans = exec_pysp2smps(options)
                except ValueError:
                    str = sys.exc_info()[1]
                    print("VALUE ERROR:")
                    print(str)
                    raise
                except KeyError:
                    str = sys.exc_info()[1]
                    print("KEY ERROR:")
                    print(str)
                    raise
                except TypeError:
                    str = sys.exc_info()[1]
                    print("TYPE ERROR:")
                    print(str)
                    raise
                except NameError:
                    str = sys.exc_info()[1]
                    print("NAME ERROR:")
                    print(str)
                    raise
                except IOError:
                    str = sys.exc_info()[1]
                    print("IO ERROR:")
                    print(str)
                    raise
                except pyutilib.common.ApplicationError:
                    str = sys.exc_info()[1]
                    print("APPLICATION ERROR:")
                    print(str)
                    raise
                except RuntimeError:
                    str = sys.exc_info()[1]
                    print("RUN-TIME ERROR:")
                    print(str)
                    raise
                except:
                    print("Encountered unhandled exception")
                    traceback.print_exc()
                    raise
            except:
                print("\n")
                print("To obtain further information regarding the "
                      "source of the exception, use the --traceback option")

    gc.enable()

    return ans
Exemple #27
0
    def create_command_line(self, executable, problem_files):

        #
        # Define log file
        # The log file in XPRESS contains the solution trace, but the solver status can be found in the solution file.
        #
        if self._log_file is None:
            self._log_file = TempfileManager.\
                            create_tempfile(suffix = '.xpress.log')

        #
        # Define solution file
        # As indicated above, contains (in XML) both the solution and solver status.
        #
        self._soln_file = TempfileManager.\
                          create_tempfile(suffix = '.xpress.wrtsol')

        #
        # Write the XPRESS execution script
        #
        script = ""

        script = "setlogfile %s\n" % (self._log_file, )

        if self._timelimit is not None and self._timelimit > 0.0:
            script += "maxtime=%s\n" % (self._timelimit, )

        if (self.options.mipgap is not None) and (self.options.mipgap > 0.0):
            mipgap = self.options.pop('mipgap')
            script += "miprelstop=%s\n" % (mipgap, )

        for option_name in self.options:
            script += "%s=%s\n" % (option_name, self.options[option_name])

        script += "readprob %s\n" % (problem_files[0], )

        # doesn't seem to be a global solve command for mip versus lp
        # solves
        if self.is_mip:
            script += "mipoptimize\n"
        else:
            script += "lpoptimize\n"

        # a quick explanation of the various flags used below:
        # p: outputs in full precision
        # n: output the name
        # t: output the type
        # a: output the activity (value)
        # c: outputs the costs for variables, slacks for constraints.
        # d: outputs the reduced costs for columns, duals for constraints
        script += "writesol %s -pnatcd\n" % (self._soln_file, )

        script += "quit\n"

        # dump the script and warm-start file names for the
        # user if we're keeping files around.
        if self._keepfiles:
            script_fname = TempfileManager.create_tempfile(
                suffix='.xpress.script')
            tmp = open(script_fname, 'w')
            tmp.write(script)
            tmp.close()

            print("Solver script file=" + script_fname)

        #
        # Define command line
        #
        cmd = [executable]
        if self._timer:
            cmd.insert(0, self._timer)
        return Bunch(cmd=cmd, script=script, log_file=self._log_file, env=None)
Exemple #28
0
def run_command(command=None, parser=None, args=None, name='unknown', data=None, options=None):
    """
    Execute a function that processes command-line arguments and
    then calls a command-line driver.

    This function provides a generic facility for executing a command
    function is rather generic.  This function is segregated from
    the driver to enable profiling of the command-line execution.

    Required:
        command:    The name of a function that will be executed to perform process the command-line
                    options with a parser object.
        parser:     The parser object that is used by the command-line function.

    Optional:
        options:    If this is not None, then ignore the args option and use
                    this to specify command options.
        args:       Command-line arguments that are parsed.  If this value is `None`, then the
                    arguments in `sys.argv` are used to parse the command-line.
        name:       Specifying the name of the command-line (for error messages).
        data:       A container of labeled data.

    Returned:
        retval:     Return values from the command-line execution.
        errorcode:  0 if Pyomo ran successfully
    """
    #
    #
    # Parse command-line options
    #
    #
    retval = None
    errorcode = 0
    if options is None:
        try:
            if type(args) is argparse.Namespace:
                _options = args
            else:
                _options = parser.parse_args(args=args)
            # Replace the parser options object with a pyutilib.misc.Options object
            options = pyutilib.misc.Options()
            for key in dir(_options):
                if key[0] != '_':
                    val = getattr(_options, key)
                    if not isinstance(val, types.MethodType):
                        options[key] = val
        except SystemExit:
            # the parser throws a system exit if "-h" is specified - catch
            # it to exit gracefully.
            return Container(retval=retval, errorcode=errorcode)
    #
    # Configure loggers
    #
    configure_loggers(options=options)
    #
    # Setup I/O redirect to a file
    #
    logfile = options.runtime.logfile
    if not logfile is None:
        pyutilib.misc.setup_redirect(logfile)
    #
    # Call the main Pyomo runner with profiling
    #
    TempfileManager.push()
    pcount = options.runtime.profile_count
    if pcount > 0:
        if not pstats_available:
            if not logfile is None:
                pyutilib.misc.reset_redirect()
            msg = "Cannot use the 'profile' option.  The Python 'pstats' "    \
                  'package cannot be imported!'
            raise ValueError(msg)
        tfile = TempfileManager.create_tempfile(suffix=".profile")
        tmp = profile.runctx(
          command.__name__ + '(options=options,parser=parser)', command.__globals__, locals(), tfile
        )
        p = pstats.Stats(tfile).strip_dirs()
        p.sort_stats('time', 'cumulative')
        p = p.print_stats(pcount)
        p.print_callers(pcount)
        p.print_callees(pcount)
        p = p.sort_stats('cumulative','calls')
        p.print_stats(pcount)
        p.print_callers(pcount)
        p.print_callees(pcount)
        p = p.sort_stats('calls')
        p.print_stats(pcount)
        p.print_callers(pcount)
        p.print_callees(pcount)
        retval = tmp
    else:
        #
        # Call the main Pyomo runner without profiling
        #
        TempfileManager.push()
        try:
            retval = command(options=options, parser=parser)
        except SystemExit:
            err = sys.exc_info()[1]
            #
            # If debugging is enabled or the 'catch' option is specified, then
            # exit.  Otherwise, print an "Exiting..." message.
            #
            if __debug__ and (options.runtime.logging == 'debug' or options.runtime.catch_errors):
                sys.exit(0)
            print('Exiting %s: %s' % (name, str(err)))
            errorcode = err.code
        except Exception:
            err = sys.exc_info()[1]
            #
            # If debugging is enabled or the 'catch' option is specified, then
            # pass the exception up the chain (to pyomo_excepthook)
            #
            if __debug__ and (options.runtime.logging == 'debug' or options.runtime.catch_errors):
                if not logfile is None:
                    pyutilib.misc.reset_redirect()
                TempfileManager.pop(remove=not options.runtime.keep_files)
                raise

            if not options.model is None and not options.model.save_file is None:
                model = "model " + options.model.save_file
            else:
                model = "model"

            global filter_excepthook
            if filter_excepthook:
                action = "loading"
            else:
                action = "running"

            msg = "Unexpected exception while %s %s:\n" % (action, model)
            #
            # This handles the case where the error is propagated by a KeyError.
            # KeyError likes to pass raw strings that don't handle newlines
            # (they translate "\n" to "\\n"), as well as tacking on single
            # quotes at either end of the error message. This undoes all that.
            #
            errStr = str(err)
            if type(err) == KeyError and errStr != "None":
                errStr = str(err).replace(r"\n","\n")[1:-1]

            logging.getLogger('pyomo.core').error(msg+errStr)
            errorcode = 1

    if not logfile is None:
        pyutilib.misc.reset_redirect()

    if options.runtime.disable_gc:
        gc.enable()
    TempfileManager.pop(remove=not options.runtime.keep_files)
    return Container(retval=retval, errorcode=errorcode)
Exemple #29
0
 def tearDown(self):
     TempfileManager.clear_tempfiles()
Exemple #30
0
 def setUp(self):
     self.mock_model = self.get_mock_model()
     self.mock_cplex_shell = self.get_mock_cplex_shell(self.mock_model)
     self.mock_cplex_shell._priorities_file_name = TempfileManager.create_tempfile(
         suffix=".cplex.ord")
Exemple #31
0
 def _presolve(self, *args, **kwds):
     super(GJHSolver, self)._presolve(*args, **kwds)
     self._gjh_file = self._soln_file[:-3] + 'gjh'
     TempfileManager.add_tempfile(self._gjh_file, exists=False)
Exemple #32
0
    def _postsolve(self):
        # the only suffixes that we extract from GUROBI are
        # constraint duals, constraint slacks, and variable
        # reduced-costs. scan through the solver suffix list
        # and throw an exception if the user has specified
        # any others.
        extract_duals = False
        extract_slacks = False
        extract_reduced_costs = False
        for suffix in self._suffixes:
            flag = False
            if re.match(suffix, "dual"):
                extract_duals = True
                flag = True
            if re.match(suffix, "slack"):
                extract_slacks = True
                flag = True
            if re.match(suffix, "rc"):
                extract_reduced_costs = True
                flag = True
            if not flag:
                raise RuntimeError("***The gurobi_direct solver plugin cannot extract solution suffix="+suffix)

        gprob = self._solver_model
        grb = self._gurobipy.GRB
        status = gprob.Status

        if gprob.getAttr(self._gurobipy.GRB.Attr.IsMIP):
            if extract_reduced_costs:
                logger.warning("Cannot get reduced costs for MIP.")
            if extract_duals:
                logger.warning("Cannot get duals for MIP.")
            extract_reduced_costs = False
            extract_duals = False

        self.results = SolverResults()
        soln = Solution()

        self.results.solver.name = self._name
        self.results.solver.wallclock_time = gprob.Runtime

        if status == grb.LOADED:  # problem is loaded, but no solution
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Model is loaded, but no solution information is available."
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.unknown
        elif status == grb.OPTIMAL:  # optimal
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message = "Model was solved to optimality (subject to tolerances), " \
                                                      "and an optimal solution is available."
            self.results.solver.termination_condition = TerminationCondition.optimal
            soln.status = SolutionStatus.optimal
        elif status == grb.INFEASIBLE:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message = "Model was proven to be infeasible"
            self.results.solver.termination_condition = TerminationCondition.infeasible
            soln.status = SolutionStatus.infeasible
        elif status == grb.INF_OR_UNBD:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message = "Problem proven to be infeasible or unbounded."
            self.results.solver.termination_condition = TerminationCondition.infeasibleOrUnbounded
            soln.status = SolutionStatus.unsure
        elif status == grb.UNBOUNDED:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message = "Model was proven to be unbounded."
            self.results.solver.termination_condition = TerminationCondition.unbounded
            soln.status = SolutionStatus.unbounded
        elif status == grb.CUTOFF:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimal objective for model was proven to be worse than the " \
                                                      "value specified in the Cutoff parameter. No solution " \
                                                      "information is available."
            self.results.solver.termination_condition = TerminationCondition.minFunctionValue
            soln.status = SolutionStatus.unknown
        elif status == grb.ITERATION_LIMIT:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization terminated because the total number of simplex " \
                                                      "iterations performed exceeded the value specified in the " \
                                                      "IterationLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.maxIterations
            soln.status = SolutionStatus.stoppedByLimit
        elif status == grb.NODE_LIMIT:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization terminated because the total number of " \
                                                      "branch-and-cut nodes explored exceeded the value specified " \
                                                      "in the NodeLimit parameter"
            self.results.solver.termination_condition = TerminationCondition.maxEvaluations
            soln.status = SolutionStatus.stoppedByLimit
        elif status == grb.TIME_LIMIT:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization terminated because the time expended exceeded " \
                                                      "the value specified in the TimeLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.maxTimeLimit
            soln.status = SolutionStatus.stoppedByLimit
        elif status == grb.SOLUTION_LIMIT:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization terminated because the number of solutions found " \
                                                      "reached the value specified in the SolutionLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.unknown
            soln.status = SolutionStatus.stoppedByLimit
        elif status == grb.INTERRUPTED:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization was terminated by the user."
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.error
        elif status == grb.NUMERIC:
            self.results.solver.status = SolverStatus.error
            self.results.solver.termination_message = "Optimization was terminated due to unrecoverable numerical " \
                                                      "difficulties."
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.error
        elif status == grb.SUBOPTIMAL:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message = "Unable to satisfy optimality tolerances; a sub-optimal " \
                                                      "solution is available."
            self.results.solver.termination_condition = TerminationCondition.other
            soln.status = SolutionStatus.feasible
        # note that USER_OBJ_LIMIT was added in Gurobi 7.0, so it may not be present
        elif (status is not None) and \
             (status == getattr(grb,'USER_OBJ_LIMIT',None)):
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "User specified an objective limit " \
                                                      "(a bound on either the best objective " \
                                                      "or the best bound), and that limit has " \
                                                      "been reached. Solution is available."
            self.results.solver.termination_condition = TerminationCondition.other
            soln.status = SolutionStatus.stoppedByLimit
        else:
            self.results.solver.status = SolverStatus.error
            self.results.solver.termination_message = \
                ("Unhandled Gurobi solve status "
                 "("+str(status)+")")
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.error

        self.results.problem.name = gprob.ModelName

        if gprob.ModelSense == 1:
            self.results.problem.sense = minimize
        elif gprob.ModelSense == -1:
            self.results.problem.sense = maximize
        else:
            raise RuntimeError('Unrecognized gurobi objective sense: {0}'.format(gprob.ModelSense))

        self.results.problem.upper_bound = None
        self.results.problem.lower_bound = None
        if (gprob.NumBinVars + gprob.NumIntVars) == 0:
            try:
                self.results.problem.upper_bound = gprob.ObjVal
                self.results.problem.lower_bound = gprob.ObjVal
            except (self._gurobipy.GurobiError, AttributeError):
                pass
        elif gprob.ModelSense == 1:  # minimizing
            try:
                self.results.problem.upper_bound = gprob.ObjVal
            except (self._gurobipy.GurobiError, AttributeError):
                pass
            try:
                self.results.problem.lower_bound = gprob.ObjBound
            except (self._gurobipy.GurobiError, AttributeError):
                pass
        elif gprob.ModelSense == -1:  # maximizing
            try:
                self.results.problem.upper_bound = gprob.ObjBound
            except (self._gurobipy.GurobiError, AttributeError):
                pass
            try:
                self.results.problem.lower_bound = gprob.ObjVal
            except (self._gurobipy.GurobiError, AttributeError):
                pass
        else:
            raise RuntimeError('Unrecognized gurobi objective sense: {0}'.format(gprob.ModelSense))

        try:
            soln.gap = self.results.problem.upper_bound - self.results.problem.lower_bound
        except TypeError:
            soln.gap = None

        self.results.problem.number_of_constraints = gprob.NumConstrs + gprob.NumQConstrs + gprob.NumSOS
        self.results.problem.number_of_nonzeros = gprob.NumNZs
        self.results.problem.number_of_variables = gprob.NumVars
        self.results.problem.number_of_binary_variables = gprob.NumBinVars
        self.results.problem.number_of_integer_variables = gprob.NumIntVars
        self.results.problem.number_of_continuous_variables = gprob.NumVars - gprob.NumIntVars - gprob.NumBinVars
        self.results.problem.number_of_objectives = 1
        self.results.problem.number_of_solutions = gprob.SolCount

        # if a solve was stopped by a limit, we still need to check to
        # see if there is a solution available - this may not always
        # be the case, both in LP and MIP contexts.
        if self._save_results:
            """
            This code in this if statement is only needed for backwards compatability. It is more efficient to set
            _save_results to False and use load_vars, load_duals, etc.
            """
            if gprob.SolCount > 0:
                soln_variables = soln.variable
                soln_constraints = soln.constraint

                gurobi_vars = self._solver_model.getVars()
                gurobi_vars = list(set(gurobi_vars).intersection(set(self._pyomo_var_to_solver_var_map.values())))
                var_vals = self._solver_model.getAttr("X", gurobi_vars)
                names = self._solver_model.getAttr("VarName", gurobi_vars)
                for gurobi_var, val, name in zip(gurobi_vars, var_vals, names):
                    pyomo_var = self._solver_var_to_pyomo_var_map[gurobi_var]
                    if self._referenced_variables[pyomo_var] > 0:
                        pyomo_var.stale = False
                        soln_variables[name] = {"Value": val}

                if extract_reduced_costs:
                    vals = self._solver_model.getAttr("Rc", gurobi_vars)
                    for gurobi_var, val, name in zip(gurobi_vars, vals, names):
                        pyomo_var = self._solver_var_to_pyomo_var_map[gurobi_var]
                        if self._referenced_variables[pyomo_var] > 0:
                            soln_variables[name]["Rc"] = val

                if extract_duals or extract_slacks:
                    gurobi_cons = self._solver_model.getConstrs()
                    con_names = self._solver_model.getAttr("ConstrName", gurobi_cons)
                    for name in con_names:
                        soln_constraints[name] = {}
                    if self._version_major >= 5:
                        gurobi_q_cons = self._solver_model.getQConstrs()
                        q_con_names = self._solver_model.getAttr("QCName", gurobi_q_cons)
                        for name in q_con_names:
                            soln_constraints[name] = {}

                if extract_duals:
                    vals = self._solver_model.getAttr("Pi", gurobi_cons)
                    for val, name in zip(vals, con_names):
                        soln_constraints[name]["Dual"] = val
                    if self._version_major >= 5:
                        q_vals = self._solver_model.getAttr("QCPi", gurobi_q_cons)
                        for val, name in zip(q_vals, q_con_names):
                            soln_constraints[name]["Dual"] = val

                if extract_slacks:
                    gurobi_range_con_vars = set(self._solver_model.getVars()) - set(self._pyomo_var_to_solver_var_map.values())
                    vals = self._solver_model.getAttr("Slack", gurobi_cons)
                    for gurobi_con, val, name in zip(gurobi_cons, vals, con_names):
                        pyomo_con = self._solver_con_to_pyomo_con_map[gurobi_con]
                        if pyomo_con in self._range_constraints:
                            lin_expr = self._solver_model.getRow(gurobi_con)
                            for i in reversed(range(lin_expr.size())):
                                v = lin_expr.getVar(i)
                                if v in gurobi_range_con_vars:
                                    Us_ = v.X
                                    Ls_ = v.UB - v.X
                                    if Us_ > Ls_:
                                        soln_constraints[name]["Slack"] = Us_
                                    else:
                                        soln_constraints[name]["Slack"] = -Ls_
                                    break
                        else:
                            soln_constraints[name]["Slack"] = val
                    if self._version_major >= 5:
                        q_vals = self._solver_model.getAttr("QCSlack", gurobi_q_cons)
                        for val, name in zip(q_vals, q_con_names):
                            soln_constraints[name]["Slack"] = val
        elif self._load_solutions:
            if gprob.SolCount > 0:

                self._load_vars()

                if extract_reduced_costs:
                    self._load_rc()

                if extract_duals:
                    self._load_duals()

                if extract_slacks:
                    self._load_slacks()

        self.results.solution.insert(soln)

        # finally, clean any temporary files registered with the temp file
        # manager, created populated *directly* by this plugin.
        TempfileManager.pop(remove=not self._keepfiles)

        return DirectOrPersistentSolver._postsolve(self)
Exemple #33
0
 def _presolve(self, *args, **kwds):
     super(GJHSolver, self)._presolve(*args, **kwds)
     self._gjh_file = self._soln_file[:-3]+'gjh'
     TempfileManager.add_tempfile(self._gjh_file, exists=False)
Exemple #34
0
 def tearDown(self):
     TempfileManager.clear_tempfiles()
     ReaderFactory.unregister('rtest3')
     ReaderFactory.unregister('stest3')
     ReaderFactory.unregister('wtest3')
Exemple #35
0
    def _postsolve(self):
        # the only suffixes that we extract from CPLEX are
        # constraint duals, constraint slacks, and variable
        # reduced-costs. scan through the solver suffix list
        # and throw an exception if the user has specified
        # any others.
        extract_duals = False
        extract_slacks = False
        extract_reduced_costs = False
        for suffix in self._suffixes:
            flag = False
            if re.match(suffix, "dual"):
                extract_duals = True
                flag = True
            if re.match(suffix, "slack"):
                extract_slacks = True
                flag = True
            if re.match(suffix, "rc"):
                extract_reduced_costs = True
                flag = True
            if not flag:
                raise RuntimeError("***The cplex_direct solver plugin cannot extract solution suffix="+suffix)

        cpxprob = self._solver_model
        status = cpxprob.solution.get_status()

        if cpxprob.get_problem_type() in [cpxprob.problem_type.MILP,
                                          cpxprob.problem_type.MIQP,
                                          cpxprob.problem_type.MIQCP]:
            if extract_reduced_costs:
                logger.warning("Cannot get reduced costs for MIP.")
            if extract_duals:
                logger.warning("Cannot get duals for MIP.")
            extract_reduced_costs = False
            extract_duals = False

        self.results = SolverResults()
        soln = Solution()

        self.results.solver.name = ("CPLEX {0}".format(cpxprob.get_version()))
        self.results.solver.wallclock_time = self._wallclock_time

        if status in [1, 101, 102]:
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_condition = TerminationCondition.optimal
            soln.status = SolutionStatus.optimal
        elif status in [2, 40, 118, 133, 134]:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_condition = TerminationCondition.unbounded
            soln.status = SolutionStatus.unbounded
        elif status in [4, 119, 134]:
            # Note: status of 4 means infeasible or unbounded
            #       and 119 means MIP infeasible or unbounded
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_condition = \
                TerminationCondition.infeasibleOrUnbounded
            soln.status = SolutionStatus.unsure
        elif status in [3, 103]:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_condition = TerminationCondition.infeasible
            soln.status = SolutionStatus.infeasible
        elif status in [10]:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_condition = TerminationCondition.maxIterations
            soln.status = SolutionStatus.stoppedByLimit
        elif status in [11, 25, 107, 131]:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_condition = TerminationCondition.maxTimeLimit
            soln.status = SolutionStatus.stoppedByLimit
        else:
            self.results.solver.status = SolverStatus.error
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.error

        if cpxprob.objective.get_sense() == cpxprob.objective.sense.minimize:
            self.results.problem.sense = minimize
        elif cpxprob.objective.get_sense() == cpxprob.objective.sense.maximize:
            self.results.problem.sense = maximize
        else:
            raise RuntimeError('Unrecognized cplex objective sense: {0}'.\
                               format(cpxprob.objective.get_sense()))

        self.results.problem.upper_bound = None
        self.results.problem.lower_bound = None
        if (cpxprob.variables.get_num_binary() + cpxprob.variables.get_num_integer()) == 0:
            try:
                self.results.problem.upper_bound = cpxprob.solution.get_objective_value()
                self.results.problem.lower_bound = cpxprob.solution.get_objective_value()
            except self._cplex.exceptions.CplexError:
                pass
        elif cpxprob.objective.get_sense() == cpxprob.objective.sense.minimize:
            try:
                self.results.problem.upper_bound = cpxprob.solution.get_objective_value()
            except self._cplex.exceptions.CplexError:
                pass
            try:
                self.results.problem.lower_bound = cpxprob.solution.MIP.get_best_objective()
            except self._cplex.exceptions.CplexError:
                pass
        elif cpxprob.objective.get_sense() == cpxprob.objective.sense.maximize:
            try:
                self.results.problem.upper_bound = cpxprob.solution.MIP.get_best_objective()
            except self._cplex.exceptions.CplexError:
                pass
            try:
                self.results.problem.lower_bound = cpxprob.solution.get_objective_value()
            except self._cplex.exceptions.CplexError:
                pass
        else:
            raise RuntimeError('Unrecognized cplex objective sense: {0}'.\
                               format(cpxprob.objective.get_sense()))

        try:
            soln.gap = self.results.problem.upper_bound - self.results.problem.lower_bound
        except TypeError:
            soln.gap = None

        self.results.problem.name = cpxprob.get_problem_name()
        assert cpxprob.indicator_constraints.get_num() == 0
        self.results.problem.number_of_constraints = \
            (cpxprob.linear_constraints.get_num() +
             cpxprob.quadratic_constraints.get_num() +
             cpxprob.SOS.get_num())
        self.results.problem.number_of_nonzeros = None
        self.results.problem.number_of_variables = cpxprob.variables.get_num()
        self.results.problem.number_of_binary_variables = cpxprob.variables.get_num_binary()
        self.results.problem.number_of_integer_variables = cpxprob.variables.get_num_integer()
        assert cpxprob.variables.get_num_semiinteger() == 0
        assert cpxprob.variables.get_num_semicontinuous() == 0
        self.results.problem.number_of_continuous_variables = \
            (cpxprob.variables.get_num() -
             cpxprob.variables.get_num_binary() -
             cpxprob.variables.get_num_integer())
        self.results.problem.number_of_objectives = 1

        # only try to get objective and variable values if a solution exists
        if self._save_results:
            """
            This code in this if statement is only needed for backwards compatability. It is more efficient to set
            _save_results to False and use load_vars, load_duals, etc.
            """
            if cpxprob.solution.get_solution_type() > 0:
                soln_variables = soln.variable
                soln_constraints = soln.constraint

                var_names = self._solver_model.variables.get_names()
                var_names = list(set(var_names).intersection(set(self._pyomo_var_to_solver_var_map.values())))
                var_vals = self._solver_model.solution.get_values(var_names)
                for i, name in enumerate(var_names):
                    pyomo_var = self._solver_var_to_pyomo_var_map[name]
                    if self._referenced_variables[pyomo_var] > 0:
                        pyomo_var.stale = False
                        soln_variables[name] = {"Value":var_vals[i]}

                if extract_reduced_costs:
                    reduced_costs = self._solver_model.solution.get_reduced_costs(var_names)
                    for i, name in enumerate(var_names):
                        pyomo_var = self._solver_var_to_pyomo_var_map[name]
                        if self._referenced_variables[pyomo_var] > 0:
                            soln_variables[name]["Rc"] = reduced_costs[i]

                if extract_slacks:
                    for con_name in self._solver_model.linear_constraints.get_names():
                        soln_constraints[con_name] = {}
                    for con_name in self._solver_model.quadratic_constraints.get_names():
                        soln_constraints[con_name] = {}
                elif extract_duals:
                    # CPLEX PYTHON API DOES NOT SUPPORT QUADRATIC DUAL COLLECTION
                    for con_name in self._solver_model.linear_constraints.get_names():
                        soln_constraints[con_name] = {}

                if extract_duals:
                    dual_values = self._solver_model.solution.get_dual_values()
                    for i, con_name in enumerate(self._solver_model.linear_constraints.get_names()):
                        soln_constraints[con_name]["Dual"] = dual_values[i]

                if extract_slacks:
                    linear_slacks = self._solver_model.solution.get_linear_slacks()
                    qudratic_slacks = self._solver_model.solution.get_quadratic_slacks()
                    for i, con_name in enumerate(self._solver_model.linear_constraints.get_names()):
                        pyomo_con = self._solver_con_to_pyomo_con_map[con_name]
                        if pyomo_con in self._range_constraints:
                            R_ = self._solver_model.linear_constraints.get_range_values(con_name)
                            if R_ == 0:
                                soln_constraints[con_name]["Slack"] = linear_slacks[i]
                            else:
                                Ls_ = linear_slacks[i]
                                Us_ = R_ - Ls_
                                if abs(Us_) > abs(Ls_):
                                    soln_constraints[con_name]["Slack"] = Us_
                                else:
                                    soln_constraints[con_name]["Slack"] = -Ls_
                        else:
                            soln_constraints[con_name]["Slack"] = linear_slacks[i]
                    for i, con_name in enumerate(self._solver_model.quadratic_constraints.get_names()):
                        soln_constraints[con_name]["Slack"] = qudratic_slacks[i]
        elif self._load_solutions:
            if cpxprob.solution.get_solution_type() > 0:
                self._load_vars()

                if extract_reduced_costs:
                    self._load_rc()

                if extract_duals:
                    self._load_duals()

                if extract_slacks:
                    self._load_slacks()

        self.results.solution.insert(soln)

        # finally, clean any temporary files registered with the temp file
        # manager, created populated *directly* by this plugin.
        TempfileManager.pop(remove=not self._keepfiles)

        return DirectOrPersistentSolver._postsolve(self)
Exemple #36
0
    def _solve_impl(self,
                    sp,
                    keep_solver_files=False,
                    output_solver_log=False,
                    symbolic_solver_labels=False):

        if len(sp.scenario_tree.stages) > 2:
            raise ValueError("SD solver does not handle more "
                             "than 2 time-stages")

        if sp.objective_sense == maximize:
            raise ValueError("SD solver does not yet handle "
                             "maximization problems")

        TempfileManager.push()
        try:

            #
            # Setup the SD working directory
            #

            working_directory = TempfileManager.create_tempdir()
            config_filename = os.path.join(working_directory,
                                           "config.sd")
            sdinput_directory = os.path.join(working_directory,
                                             "sdinput",
                                             "pysp_model")
            sdoutput_directory = os.path.join(working_directory,
                                              "sdoutput",
                                              "pysp_model")
            logfile = os.path.join(working_directory, "sd.log")

            os.makedirs(sdinput_directory)
            assert os.path.exists(sdinput_directory)
            assert not os.path.exists(sdoutput_directory)
            self._write_config(config_filename)

            if self.get_option('single_replication'):
                solution_filename = os.path.join(
                    sdoutput_directory,
                    "pysp_model.detailed_rep_soln.out")
            else:
                solution_filename = os.path.join(
                    sdoutput_directory,
                    "pysp_model.detailed_soln.out")

            #
            # Create the SD input files
            #

            io_options = {'symbolic_solver_labels':
                          symbolic_solver_labels}

            symbol_map = None
            if isinstance(sp, ImplicitSP):
                symbol_map = pyomo.pysp.smps.smpsutils.\
                             convert_implicit(
                                 sdinput_directory,
                                 "pysp_model",
                                 sp,
                                 core_format='mps',
                                 io_options=io_options)
            else:
                pyomo.pysp.smps.smpsutils.\
                    convert_explicit(
                        sdinput_directory,
                        "pysp_model",
                        sp,
                        core_format='mps',
                        io_options=io_options)

            #
            # Launch SD
            #

            if keep_solver_files:
                print("Solver working directory: '%s'"
                      % (working_directory))
                print("Solver log file: '%s'"
                      % (logfile))

            start = time.time()
            rc, log = pyutilib.subprocess.run(
                self.get_option("sd_executable"),
                cwd=working_directory,
                stdin="pysp_model",
                outfile=logfile,
                tee=output_solver_log)
            stop = time.time()
            assert os.path.exists(sdoutput_directory)

            #
            # Parse the SD solution
            #

            xhat, results = self._read_solution(solution_filename)

            results.solver_time = stop - start

            if symbol_map is not None:
                # load the first stage variable solution into
                # the reference model
                for symbol, varvalue in xhat.items():
                    symbol_map.bySymbol[symbol]().value = varvalue
            else:
                # TODO: this is a hack for the non-implicit SP case
                #       so that this solver can still be run using
                #       the explicit scenario intput representation
                results.xhat = xhat

        finally:

            #
            # cleanup
            #
            TempfileManager.pop(
                remove=not keep_solver_files)

        return results
Exemple #37
0
def launch_command(command,
                   options,
                   cmd_args=None,
                   cmd_kwds=None,
                   error_label="",
                   disable_gc=False,
                   profile_count=0,
                   traceback=False):
    if cmd_args is None:
        cmd_args = ()
    if cmd_kwds is None:
        cmd_kwds = {}

    #
    # Control the garbage collector - more critical than I would like
    # at the moment.
    #
    with PauseGC(disable_gc) as pgc:

        #
        # Run command - precise invocation depends on whether we want
        # profiling output, traceback, etc.
        #

        rc = 0

        if pstats_available and (profile_count > 0):
            #
            # Call the main routine with profiling.
            #
            tfile = TempfileManager.create_tempfile(suffix=".profile")
            tmp = profile.runctx('command(options, *cmd_args, **cmd_kwds)',
                                 globals(),
                                 locals(),
                                 tfile)
            p = pstats.Stats(tfile).strip_dirs()
            p.sort_stats('time', 'cumulative')
            p = p.print_stats(profile_count)
            p.print_callers(profile_count)
            p.print_callees(profile_count)
            p = p.sort_stats('cumulative','calls')
            p.print_stats(profile_count)
            p.print_callers(profile_count)
            p.print_callees(profile_count)
            p = p.sort_stats('calls')
            p.print_stats(profile_count)
            p.print_callers(profile_count)
            p.print_callees(profile_count)
            TempfileManager.clear_tempfiles()
            rc = tmp
        else:

            #
            # Call the main PH routine without profiling.
            #
            if traceback:
                rc = command(options, *cmd_args, **cmd_kwds)
            else:
                try:
                    try:
                        rc = command(options, *cmd_args, **cmd_kwds)
                    except ValueError:
                        sys.stderr.write(error_label+"VALUE ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except KeyError:
                        sys.stderr.write(error_label+"KEY ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except TypeError:
                        sys.stderr.write(error_label+"TYPE ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except NameError:
                        sys.stderr.write(error_label+"NAME ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except IOError:
                        sys.stderr.write(error_label+"IO ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except ConverterError:
                        sys.stderr.write(error_label+"CONVERTER ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except pyutilib.common.ApplicationError:
                        sys.stderr.write(error_label+"APPLICATION ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except RuntimeError:
                        sys.stderr.write(error_label+"RUN-TIME ERROR:\n")
                        sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        raise
                    except:
                        sys.stderr.write(error_label+
                                         "Encountered unhandled exception:\n")
                        if len(sys.exc_info()) > 1:
                            sys.stderr.write(str(sys.exc_info()[1])+"\n")
                        else:
                            traceback.print_exc(file=sys.stderr)
                        raise
                except:
                    sys.stderr.write("\n")
                    sys.stderr.write(
                        "To obtain further information regarding the "
                        "source of the exception, use the "
                        "--traceback option\n")
                    rc = 1

    #
    # TODO: Once we incorporate options registration into
    #       all of the PySP commands we will assume the
    #       options object is always a PySPConfigBlock
    #
    if isinstance(options, PySPConfigBlock):
        ignored_options = dict((_c._name, _c.value(False))
                              for _c in options.unused_user_values())
        if len(ignored_options):
            print("")
            print("*** WARNING: The following options were "
                  "explicitly set but never accessed during "
                  "execution of this command:")
            for name in ignored_options:
                print(" - %s: %s" % (name, ignored_options[name]))
            print("*** If you believe this is a bug, please report it "
                  "to the PySP developers.")
            print("")

    return rc
Exemple #38
0
    def _postsolve(self):
        # the only suffixes that we extract from GUROBI are
        # constraint duals, constraint slacks, and variable
        # reduced-costs. scan through the solver suffix list
        # and throw an exception if the user has specified
        # any others.
        extract_duals = False
        extract_slacks = False
        extract_reduced_costs = False
        for suffix in self._suffixes:
            flag = False
            if re.match(suffix, "dual"):
                extract_duals = True
                flag = True
            if re.match(suffix, "slack"):
                extract_slacks = True
                flag = True
            if re.match(suffix, "rc"):
                extract_reduced_costs = True
                flag = True
            if not flag:
                raise RuntimeError("***The gurobi_direct solver plugin cannot extract solution suffix="+suffix)

        gprob = self._solver_model
        grb = self._gurobipy.GRB
        status = gprob.Status

        if gprob.getAttr(self._gurobipy.GRB.Attr.IsMIP):
            if extract_reduced_costs:
                logger.warning("Cannot get reduced costs for MIP.")
            if extract_duals:
                logger.warning("Cannot get duals for MIP.")
            extract_reduced_costs = False
            extract_duals = False

        self.results = SolverResults()
        soln = Solution()

        self.results.solver.name = self._name
        self.results.solver.wallclock_time = gprob.Runtime

        if status == grb.LOADED:  # problem is loaded, but no solution
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Model is loaded, but no solution information is available."
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.unknown
        elif status == grb.OPTIMAL:  # optimal
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message = "Model was solved to optimality (subject to tolerances), " \
                                                      "and an optimal solution is available."
            self.results.solver.termination_condition = TerminationCondition.optimal
            soln.status = SolutionStatus.optimal
        elif status == grb.INFEASIBLE:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message = "Model was proven to be infeasible"
            self.results.solver.termination_condition = TerminationCondition.infeasible
            soln.status = SolutionStatus.infeasible
        elif status == grb.INF_OR_UNBD:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message = "Problem proven to be infeasible or unbounded."
            self.results.solver.termination_condition = TerminationCondition.infeasibleOrUnbounded
            soln.status = SolutionStatus.unsure
        elif status == grb.UNBOUNDED:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message = "Model was proven to be unbounded."
            self.results.solver.termination_condition = TerminationCondition.unbounded
            soln.status = SolutionStatus.unbounded
        elif status == grb.CUTOFF:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimal objective for model was proven to be worse than the " \
                                                      "value specified in the Cutoff parameter. No solution " \
                                                      "information is available."
            self.results.solver.termination_condition = TerminationCondition.minFunctionValue
            soln.status = SolutionStatus.unknown
        elif status == grb.ITERATION_LIMIT:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization terminated because the total number of simplex " \
                                                      "iterations performed exceeded the value specified in the " \
                                                      "IterationLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.maxIterations
            soln.status = SolutionStatus.stoppedByLimit
        elif status == grb.NODE_LIMIT:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization terminated because the total number of " \
                                                      "branch-and-cut nodes explored exceeded the value specified " \
                                                      "in the NodeLimit parameter"
            self.results.solver.termination_condition = TerminationCondition.maxEvaluations
            soln.status = SolutionStatus.stoppedByLimit
        elif status == grb.TIME_LIMIT:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization terminated because the time expended exceeded " \
                                                      "the value specified in the TimeLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.maxTimeLimit
            soln.status = SolutionStatus.stoppedByLimit
        elif status == grb.SOLUTION_LIMIT:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization terminated because the number of solutions found " \
                                                      "reached the value specified in the SolutionLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.unknown
            soln.status = SolutionStatus.stoppedByLimit
        elif status == grb.INTERRUPTED:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "Optimization was terminated by the user."
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.error
        elif status == grb.NUMERIC:
            self.results.solver.status = SolverStatus.error
            self.results.solver.termination_message = "Optimization was terminated due to unrecoverable numerical " \
                                                      "difficulties."
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.error
        elif status == grb.SUBOPTIMAL:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message = "Unable to satisfy optimality tolerances; a sub-optimal " \
                                                      "solution is available."
            self.results.solver.termination_condition = TerminationCondition.other
            soln.status = SolutionStatus.feasible
        # note that USER_OBJ_LIMIT was added in Gurobi 7.0, so it may not be present
        elif (status is not None) and \
             (status == getattr(grb,'USER_OBJ_LIMIT',None)):
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_message = "User specified an objective limit " \
                                                      "(a bound on either the best objective " \
                                                      "or the best bound), and that limit has " \
                                                      "been reached. Solution is available."
            self.results.solver.termination_condition = TerminationCondition.other
            soln.status = SolutionStatus.stoppedByLimit
        else:
            self.results.solver.status = SolverStatus.error
            self.results.solver.termination_message = \
                ("Unhandled Gurobi solve status "
                 "("+str(status)+")")
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.error

        self.results.problem.name = gprob.ModelName

        if gprob.ModelSense == 1:
            self.results.problem.sense = minimize
        elif gprob.ModelSense == -1:
            self.results.problem.sense = maximize
        else:
            raise RuntimeError('Unrecognized gurobi objective sense: {0}'.format(gprob.ModelSense))

        self.results.problem.upper_bound = None
        self.results.problem.lower_bound = None
        if (gprob.NumBinVars + gprob.NumIntVars) == 0:
            try:
                self.results.problem.upper_bound = gprob.ObjVal
                self.results.problem.lower_bound = gprob.ObjVal
            except (self._gurobipy.GurobiError, AttributeError):
                pass
        elif gprob.ModelSense == 1:  # minimizing
            try:
                self.results.problem.upper_bound = gprob.ObjVal
            except (self._gurobipy.GurobiError, AttributeError):
                pass
            try:
                self.results.problem.lower_bound = gprob.ObjBound
            except (self._gurobipy.GurobiError, AttributeError):
                pass
        elif gprob.ModelSense == -1:  # maximizing
            try:
                self.results.problem.upper_bound = gprob.ObjBound
            except (self._gurobipy.GurobiError, AttributeError):
                pass
            try:
                self.results.problem.lower_bound = gprob.ObjVal
            except (self._gurobipy.GurobiError, AttributeError):
                pass
        else:
            raise RuntimeError('Unrecognized gurobi objective sense: {0}'.format(gprob.ModelSense))

        try:
            soln.gap = self.results.problem.upper_bound - self.results.problem.lower_bound
        except TypeError:
            soln.gap = None

        self.results.problem.number_of_constraints = gprob.NumConstrs + gprob.NumQConstrs + gprob.NumSOS
        self.results.problem.number_of_nonzeros = gprob.NumNZs
        self.results.problem.number_of_variables = gprob.NumVars
        self.results.problem.number_of_binary_variables = gprob.NumBinVars
        self.results.problem.number_of_integer_variables = gprob.NumIntVars
        self.results.problem.number_of_continuous_variables = gprob.NumVars - gprob.NumIntVars - gprob.NumBinVars
        self.results.problem.number_of_objectives = 1
        self.results.problem.number_of_solutions = gprob.SolCount

        # if a solve was stopped by a limit, we still need to check to
        # see if there is a solution available - this may not always
        # be the case, both in LP and MIP contexts.
        if self._save_results:
            """
            This code in this if statement is only needed for backwards compatability. It is more efficient to set
            _save_results to False and use load_vars, load_duals, etc.
            """
            if gprob.SolCount > 0:
                soln_variables = soln.variable
                soln_constraints = soln.constraint

                gurobi_vars = self._solver_model.getVars()
                gurobi_vars = list(set(gurobi_vars).intersection(set(self._pyomo_var_to_solver_var_map.values())))
                var_vals = self._solver_model.getAttr("X", gurobi_vars)
                names = self._solver_model.getAttr("VarName", gurobi_vars)
                for gurobi_var, val, name in zip(gurobi_vars, var_vals, names):
                    pyomo_var = self._solver_var_to_pyomo_var_map[gurobi_var]
                    if self._referenced_variables[pyomo_var] > 0:
                        pyomo_var.stale = False
                        soln_variables[name] = {"Value": val}

                if extract_reduced_costs:
                    vals = self._solver_model.getAttr("Rc", gurobi_vars)
                    for gurobi_var, val, name in zip(gurobi_vars, vals, names):
                        pyomo_var = self._solver_var_to_pyomo_var_map[gurobi_var]
                        if self._referenced_variables[pyomo_var] > 0:
                            soln_variables[name]["Rc"] = val

                if extract_duals or extract_slacks:
                    gurobi_cons = self._solver_model.getConstrs()
                    con_names = self._solver_model.getAttr("ConstrName", gurobi_cons)
                    for name in con_names:
                        soln_constraints[name] = {}
                    if self._version_major >= 5:
                        gurobi_q_cons = self._solver_model.getQConstrs()
                        q_con_names = self._solver_model.getAttr("QCName", gurobi_q_cons)
                        for name in q_con_names:
                            soln_constraints[name] = {}

                if extract_duals:
                    vals = self._solver_model.getAttr("Pi", gurobi_cons)
                    for val, name in zip(vals, con_names):
                        soln_constraints[name]["Dual"] = val
                    if self._version_major >= 5:
                        q_vals = self._solver_model.getAttr("QCPi", gurobi_q_cons)
                        for val, name in zip(q_vals, q_con_names):
                            soln_constraints[name]["Dual"] = val

                if extract_slacks:
                    gurobi_range_con_vars = set(self._solver_model.getVars()) - set(self._pyomo_var_to_solver_var_map.values())
                    vals = self._solver_model.getAttr("Slack", gurobi_cons)
                    for gurobi_con, val, name in zip(gurobi_cons, vals, con_names):
                        pyomo_con = self._solver_con_to_pyomo_con_map[gurobi_con]
                        if pyomo_con in self._range_constraints:
                            lin_expr = self._solver_model.getRow(gurobi_con)
                            for i in reversed(range(lin_expr.size())):
                                v = lin_expr.getVar(i)
                                if v in gurobi_range_con_vars:
                                    Us_ = v.X
                                    Ls_ = v.UB - v.X
                                    if Us_ > Ls_:
                                        soln_constraints[name]["Slack"] = Us_
                                    else:
                                        soln_constraints[name]["Slack"] = -Ls_
                                    break
                        else:
                            soln_constraints[name]["Slack"] = val
                    if self._version_major >= 5:
                        q_vals = self._solver_model.getAttr("QCSlack", gurobi_q_cons)
                        for val, name in zip(q_vals, q_con_names):
                            soln_constraints[name]["Slack"] = val
        elif self._load_solutions:
            if gprob.SolCount > 0:

                self._load_vars()

                if extract_reduced_costs:
                    self._load_rc()

                if extract_duals:
                    self._load_duals()

                if extract_slacks:
                    self._load_slacks()

        self.results.solution.insert(soln)

        # finally, clean any temporary files registered with the temp file
        # manager, created populated *directly* by this plugin.
        TempfileManager.pop(remove=not self._keepfiles)

        return DirectOrPersistentSolver._postsolve(self)
Exemple #39
0
 def tearDown(self):
     global tmpdir
     TempfileManager.clear_tempfiles()
     TempfileManager.unique_files()
     os.chdir(tmpdir)
Exemple #40
0
    def _postsolve(self):
        # the only suffixes that we extract from CPLEX are
        # constraint duals, constraint slacks, and variable
        # reduced-costs. scan through the solver suffix list
        # and throw an exception if the user has specified
        # any others.
        extract_duals = False
        extract_slacks = False
        extract_reduced_costs = False
        for suffix in self._suffixes:
            flag = False
            if re.match(suffix, "dual"):
                extract_duals = True
                flag = True
            if re.match(suffix, "slack"):
                extract_slacks = True
                flag = True
            if re.match(suffix, "rc"):
                extract_reduced_costs = True
                flag = True
            if not flag:
                raise RuntimeError("***The cplex_direct solver plugin cannot extract solution suffix="+suffix)

        cpxprob = self._solver_model
        status = cpxprob.solution.get_status()
        rtn_codes = cpxprob.solution.status

        if cpxprob.get_problem_type() in [cpxprob.problem_type.MILP,
                                          cpxprob.problem_type.MIQP,
                                          cpxprob.problem_type.MIQCP]:
            if extract_reduced_costs:
                logger.warning("Cannot get reduced costs for MIP.")
            if extract_duals:
                logger.warning("Cannot get duals for MIP.")
            extract_reduced_costs = False
            extract_duals = False

        self.results = SolverResults()
        soln = Solution()

        self.results.solver.name = ("CPLEX {0}".format(cpxprob.get_version()))
        self.results.solver.wallclock_time = self._wallclock_time
        self.results.solver.deterministic_time = self._deterministic_time

        if status in {
            rtn_codes.optimal,
            rtn_codes.MIP_optimal,
            rtn_codes.optimal_tolerance,
        }:
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_condition = TerminationCondition.optimal
            soln.status = SolutionStatus.optimal
        elif status in {
            rtn_codes.unbounded,
            40,
            rtn_codes.MIP_unbounded,
            rtn_codes.relaxation_unbounded,
            134,
        }:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_condition = TerminationCondition.unbounded
            soln.status = SolutionStatus.unbounded
        elif status in {
            rtn_codes.infeasible_or_unbounded,
            rtn_codes.MIP_infeasible_or_unbounded,
            134,
        }:
            # Note: status of 4 means infeasible or unbounded
            #       and 119 means MIP infeasible or unbounded
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_condition = \
                TerminationCondition.infeasibleOrUnbounded
            soln.status = SolutionStatus.unsure
        elif status in {rtn_codes.infeasible, rtn_codes.MIP_infeasible}:
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_condition = TerminationCondition.infeasible
            soln.status = SolutionStatus.infeasible
        elif status in {rtn_codes.abort_iteration_limit}:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_condition = TerminationCondition.maxIterations
            soln.status = SolutionStatus.stoppedByLimit
        elif status in {
            rtn_codes.solution_limit,
            rtn_codes.node_limit_feasible,
            rtn_codes.mem_limit_feasible
        }:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_condition = TerminationCondition.unknown
            soln.status = SolutionStatus.stoppedByLimit
        elif status in {
            rtn_codes.abort_time_limit,
            rtn_codes.abort_dettime_limit,
            rtn_codes.MIP_time_limit_feasible,
            rtn_codes.MIP_dettime_limit_feasible,
        }:
            self.results.solver.status = SolverStatus.aborted
            self.results.solver.termination_condition = TerminationCondition.maxTimeLimit
            soln.status = SolutionStatus.stoppedByLimit
        elif status in {
            rtn_codes.MIP_time_limit_infeasible,
            rtn_codes.MIP_dettime_limit_infeasible,
            rtn_codes.node_limit_infeasible,
            rtn_codes.mem_limit_infeasible,
            rtn_codes.MIP_abort_infeasible,
        } or self._error_code == self._cplex.exceptions.error_codes.CPXERR_NO_SOLN:
            # CPLEX doesn't have a solution status for `noSolution` so we assume this from the combination of
            # maxTimeLimit + infeasible (instead of a generic `TerminationCondition.error`).
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_condition = TerminationCondition.noSolution
            soln.status = SolutionStatus.unknown
        else:
            self.results.solver.status = SolverStatus.error
            self.results.solver.termination_condition = TerminationCondition.error
            soln.status = SolutionStatus.error

        self.results.solver.return_code = self._error_code
        self.results.solver.termination_message = cpxprob.solution.get_status_string(status)

        if cpxprob.objective.get_sense() == cpxprob.objective.sense.minimize:
            self.results.problem.sense = minimize
        elif cpxprob.objective.get_sense() == cpxprob.objective.sense.maximize:
            self.results.problem.sense = maximize
        else:
            raise RuntimeError('Unrecognized cplex objective sense: {0}'.\
                               format(cpxprob.objective.get_sense()))

        self.results.problem.upper_bound = None
        self.results.problem.lower_bound = None
        if cpxprob.solution.get_solution_type() != cpxprob.solution.type.none:
            if (cpxprob.variables.get_num_binary() + cpxprob.variables.get_num_integer()) == 0:
                self.results.problem.upper_bound = cpxprob.solution.get_objective_value()
                self.results.problem.lower_bound = cpxprob.solution.get_objective_value()
            elif cpxprob.objective.get_sense() == cpxprob.objective.sense.minimize:
                self.results.problem.upper_bound = cpxprob.solution.get_objective_value()
                self.results.problem.lower_bound = cpxprob.solution.MIP.get_best_objective()
            else:
                assert cpxprob.objective.get_sense() == cpxprob.objective.sense.maximize
                self.results.problem.upper_bound = cpxprob.solution.MIP.get_best_objective()
                self.results.problem.lower_bound = cpxprob.solution.get_objective_value()

        try:
            soln.gap = self.results.problem.upper_bound - self.results.problem.lower_bound
        except TypeError:
            soln.gap = None

        self.results.problem.name = cpxprob.get_problem_name()
        assert cpxprob.indicator_constraints.get_num() == 0
        self.results.problem.number_of_constraints = \
            (cpxprob.linear_constraints.get_num() +
             cpxprob.quadratic_constraints.get_num() +
             cpxprob.SOS.get_num())
        self.results.problem.number_of_nonzeros = None
        self.results.problem.number_of_variables = cpxprob.variables.get_num()
        self.results.problem.number_of_binary_variables = cpxprob.variables.get_num_binary()
        self.results.problem.number_of_integer_variables = cpxprob.variables.get_num_integer()
        assert cpxprob.variables.get_num_semiinteger() == 0
        assert cpxprob.variables.get_num_semicontinuous() == 0
        self.results.problem.number_of_continuous_variables = \
            (cpxprob.variables.get_num() -
             cpxprob.variables.get_num_binary() -
             cpxprob.variables.get_num_integer())
        self.results.problem.number_of_objectives = 1

        # only try to get objective and variable values if a solution exists
        if self._save_results:
            """
            This code in this if statement is only needed for backwards compatability. It is more efficient to set
            _save_results to False and use load_vars, load_duals, etc.
            """
            if cpxprob.solution.get_solution_type() > 0:
                soln_variables = soln.variable
                soln_constraints = soln.constraint

                var_names = self._solver_model.variables.get_names()
                var_names = list(set(var_names).intersection(set(self._pyomo_var_to_solver_var_map.values())))
                var_vals = self._solver_model.solution.get_values(var_names)
                for i, name in enumerate(var_names):
                    pyomo_var = self._solver_var_to_pyomo_var_map[name]
                    if self._referenced_variables[pyomo_var] > 0:
                        pyomo_var.stale = False
                        soln_variables[name] = {"Value":var_vals[i]}

                if extract_reduced_costs:
                    reduced_costs = self._solver_model.solution.get_reduced_costs(var_names)
                    for i, name in enumerate(var_names):
                        pyomo_var = self._solver_var_to_pyomo_var_map[name]
                        if self._referenced_variables[pyomo_var] > 0:
                            soln_variables[name]["Rc"] = reduced_costs[i]

                if extract_slacks:
                    for con_name in self._solver_model.linear_constraints.get_names():
                        soln_constraints[con_name] = {}
                    for con_name in self._solver_model.quadratic_constraints.get_names():
                        soln_constraints[con_name] = {}
                elif extract_duals:
                    # CPLEX PYTHON API DOES NOT SUPPORT QUADRATIC DUAL COLLECTION
                    for con_name in self._solver_model.linear_constraints.get_names():
                        soln_constraints[con_name] = {}

                if extract_duals:
                    dual_values = self._solver_model.solution.get_dual_values()
                    for i, con_name in enumerate(self._solver_model.linear_constraints.get_names()):
                        soln_constraints[con_name]["Dual"] = dual_values[i]

                if extract_slacks:
                    linear_slacks = self._solver_model.solution.get_linear_slacks()
                    qudratic_slacks = self._solver_model.solution.get_quadratic_slacks()
                    for i, con_name in enumerate(self._solver_model.linear_constraints.get_names()):
                        pyomo_con = self._solver_con_to_pyomo_con_map[con_name]
                        if pyomo_con in self._range_constraints:
                            R_ = self._solver_model.linear_constraints.get_range_values(con_name)
                            if R_ == 0:
                                soln_constraints[con_name]["Slack"] = linear_slacks[i]
                            else:
                                Ls_ = linear_slacks[i]
                                Us_ = R_ - Ls_
                                if abs(Us_) > abs(Ls_):
                                    soln_constraints[con_name]["Slack"] = Us_
                                else:
                                    soln_constraints[con_name]["Slack"] = -Ls_
                        else:
                            soln_constraints[con_name]["Slack"] = linear_slacks[i]
                    for i, con_name in enumerate(self._solver_model.quadratic_constraints.get_names()):
                        soln_constraints[con_name]["Slack"] = qudratic_slacks[i]
        elif self._load_solutions:
            if cpxprob.solution.get_solution_type() > 0:
                self._load_vars()

                if extract_reduced_costs:
                    self._load_rc()

                if extract_duals:
                    self._load_duals()

                if extract_slacks:
                    self._load_slacks()

        self.results.solution.insert(soln)

        # finally, clean any temporary files registered with the temp file
        # manager, created populated *directly* by this plugin.
        TempfileManager.pop(remove=not self._keepfiles)

        return DirectOrPersistentSolver._postsolve(self)
Exemple #41
0
def main(args=None):
    #
    # Top-level command that executes the extensive form writer.
    # This is segregated from run_ef_writer to enable profiling.
    #

    #
    # Import plugins
    #
    import pyomo.environ
    #
    # Parse command-line options.
    #
    try:
        options_parser = construct_smps_options_parser("runph [options]")
        (options, args) = options_parser.parse_args(args=args)
    except SystemExit as _exc:
        # the parser throws a system exit if "-h" is specified - catch
        # it to exit gracefully.
        return _exc.code

    #
    # Control the garbage collector - more critical than I would like
    # at the moment.
    #

    if options.disable_gc:
        gc.disable()
    else:
        gc.enable()

    #
    # Run PH - precise invocation depends on whether we want profiling
    # output.
    #

    # if an exception is triggered and traceback is enabled, 'ans'
    # won't have a value and the return statement from this function
    # will flag an error, masking the stack trace that you really want
    # to see.
    ans = None

    if pstats_available and options.profile > 0:
        #
        # Call the main routine with profiling.
        #
        tfile = TempfileManager.create_tempfile(suffix=".profile")
        tmp = profile.runctx('exec_pysp2smps(options)', globals(), locals(),
                             tfile)
        p = pstats.Stats(tfile).strip_dirs()
        p.sort_stats('time', 'cumulative')
        p = p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        p = p.sort_stats('cumulative', 'calls')
        p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        p = p.sort_stats('calls')
        p.print_stats(options.profile)
        p.print_callers(options.profile)
        p.print_callees(options.profile)
        TempfileManager.clear_tempfiles()
        ans = [tmp, None]
    else:
        #
        # Call the main routine without profiling.
        #

        if options.traceback:
            ans = exec_pysp2smps(options)
        else:
            try:
                try:
                    ans = exec_pysp2smps(options)
                except ValueError:
                    str = sys.exc_info()[1]
                    print("VALUE ERROR:")
                    print(str)
                    raise
                except KeyError:
                    str = sys.exc_info()[1]
                    print("KEY ERROR:")
                    print(str)
                    raise
                except TypeError:
                    str = sys.exc_info()[1]
                    print("TYPE ERROR:")
                    print(str)
                    raise
                except NameError:
                    str = sys.exc_info()[1]
                    print("NAME ERROR:")
                    print(str)
                    raise
                except IOError:
                    str = sys.exc_info()[1]
                    print("IO ERROR:")
                    print(str)
                    raise
                except pyutilib.common.ApplicationError:
                    str = sys.exc_info()[1]
                    print("APPLICATION ERROR:")
                    print(str)
                    raise
                except RuntimeError:
                    str = sys.exc_info()[1]
                    print("RUN-TIME ERROR:")
                    print(str)
                    raise
                except:
                    print("Encountered unhandled exception")
                    traceback.print_exc()
                    raise
            except:
                print("\n")
                print("To obtain further information regarding the "
                      "source of the exception, use the --traceback option")

    gc.enable()

    return ans
Exemple #42
0
    def _postsolve(self):

        extract_duals = False
        extract_slacks = False
        extract_reduced_costs = False
        for suffix in self._suffixes:
            flag = False
            if re.match(suffix, "dual"):
                extract_duals = True
                flag = True
            if re.match(suffix, "slack"):
                extract_slacks = True
                flag = True
            if re.match(suffix, "rc"):
                extract_reduced_costs = True
                flag = True
            if not flag:
                raise RuntimeError(
                    "***The mosek solver plugin cannot extract solution suffix="
                    + suffix)

        msk_task = self._solver_model
        msk = self._mosek

        itr_soltypes = [msk.problemtype.qo, msk.problemtype.qcqo]

        if (msk_task.getnumintvar() >= 1):
            self._whichsol = msk.soltype.itg
            if extract_reduced_costs:
                logger.warning("Cannot get reduced costs for MIP.")
            if extract_duals:
                logger.warning("Cannot get duals for MIP.")
            extract_reduced_costs = False
            extract_duals = False
        elif (msk_task.getprobtype() in itr_soltypes):
            self._whichsol = msk.soltype.itr

        whichsol = self._whichsol
        sol_status = msk_task.getsolsta(whichsol)
        pro_status = msk_task.getprosta(whichsol)

        self.results = SolverResults()
        soln = Solution()

        self.results.solver.name = self._name
        self.results.solver.wallclock_time = msk_task.getdouinf(
            msk.dinfitem.optimizer_time)

        SOLSTA_MAP = {
            msk.solsta.unknown: 'unknown',
            msk.solsta.optimal: 'optimal',
            msk.solsta.prim_and_dual_feas: 'pd_feas',
            msk.solsta.prim_feas: 'p_feas',
            msk.solsta.dual_feas: 'd_feas',
            msk.solsta.prim_infeas_cer: 'p_infeas',
            msk.solsta.dual_infeas_cer: 'd_infeas',
            msk.solsta.prim_illposed_cer: 'p_illposed',
            msk.solsta.dual_illposed_cer: 'd_illposed',
            msk.solsta.integer_optimal: 'optimal'
        }
        PROSTA_MAP = {
            msk.prosta.unknown: 'unknown',
            msk.prosta.prim_and_dual_feas: 'pd_feas',
            msk.prosta.prim_feas: 'p_feas',
            msk.prosta.dual_feas: 'd_feas',
            msk.prosta.prim_infeas: 'p_infeas',
            msk.prosta.dual_infeas: 'd_infeas',
            msk.prosta.prim_and_dual_feas: 'pd_infeas',
            msk.prosta.ill_posed: 'illposed',
            msk.prosta.prim_infeas_or_unbounded: 'p_inf_unb'
        }

        if self._version_major < 9:
            SOLSTA_OLD = {
                msk.solsta.near_optimal: 'optimal',
                msk.solsta.near_integer_optimal: 'optimal',
                msk.solsta.near_prim_feas: 'p_feas',
                msk.solsta.near_dual_feas: 'd_feas',
                msk.solsta.near_prim_and_dual_feas: 'pd_feas',
                msk.solsta.near_prim_infeas_cer: 'p_infeas',
                msk.solsta.near_dual_infeas_cer: 'd_infeas'
            }
            PROSTA_OLD = {
                msk.prosta.near_prim_and_dual_feas: 'pd_feas',
                msk.prosta.near_prim_feas: 'p_feas',
                msk.prosta.near_dual_feas: 'd_feas'
            }
            SOLSTA_MAP.update(SOLSTA_OLD)
            PROSTA_MAP.update(PROSTA_OLD)

        if self._termcode == msk.rescode.ok:
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message = ""

        elif self._termcode == msk.rescode.trm_max_iterations:
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message = "Optimization terminated because the total number " \
                "iterations performed exceeded the value specified in the " \
                "IterationLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.maxIterations
            soln.status = SolutionStatus.stoppedByLimit

        elif self._termcode == msk.rescode.trm_max_time:
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message = "Optimization terminated because the time expended exceeded " \
                "the value specified in the TimeLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.maxTimeLimit
            soln.status = SolutionStatus.stoppedByLimit

        elif self._termcode == msk.rescode.trm_user_callback:
            self.results.solver.status = SolverStatus.Aborted
            self.results.solver.termination_message = "Optimization terminated because of the user callback "
            self.results.solver.termination_condition = TerminationCondition.userInterrupt
            soln.status = SolutionStatus.unknown

        elif self._termcode in [
                msk.rescode.trm_mio_num_relaxs,
                msk.rescode.trm_mio_num_branches,
                msk.rescode.trm_num_max_num_int_solutions
        ]:
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message = "Optimization terminated because maximum number of relaxations" \
                " / branches / integer solutions exceeded " \
                "the value specified in the TimeLimit parameter."
            self.results.solver.termination_condition = TerminationCondition.maxEvaluations
            soln.status = SolutionStatus.stoppedByLimit

        else:
            self.results.solver.termination_message = " Optimization terminated %s response code." \
                "Check Mosek response code documentation for further explanation." % self._termcode
            self.results.solver.termination_condition = TerminationCondition.unknown

        if SOLSTA_MAP[sol_status] == 'unknown':
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message += " Unknown solution status."
            self.results.solver.Message = self.results.solver.termination_message
            self.results.solver.termination_condition = TerminationCondition.unknown
            soln.status = SolutionStatus.unknown

        if PROSTA_MAP[pro_status] == 'd_infeas':
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message += " Problem proven to be dual infeasible"
            self.results.solver.Message = self.results.solver.termination_message
            self.results.solver.termination_condition = TerminationCondition.unbounded
            soln.status = SolutionStatus.unbounded

        elif PROSTA_MAP[pro_status] == 'p_infeas':
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message += " Problem proven to be primal infeasible."
            self.results.solver.Message = self.results.solver.termination_message
            self.results.solver.termination_condition = TerminationCondition.infeasible
            soln.status = SolutionStatus.infeasible

        elif PROSTA_MAP[pro_status] == 'pd_infeas':
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message += " Problem proven to be primal and dual infeasible."
            self.results.solver.Message = self.results.solver.termination_message
            self.results.solver.termination_condition = TerminationCondition.infeasible
            soln.status = SolutionStatus.infeasible

        elif PROSTA_MAP[pro_status] == 'p_inf_unb':
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message += " Problem proven to be infeasible or unbounded."
            self.results.solver.Message = self.results.solver.termination_message
            self.results.solver.termination_condition = TerminationCondition.infeasibleOrUnbounded
            soln.status = SolutionStatus.unsure

        if SOLSTA_MAP[sol_status] == 'optimal':
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message += " Model was solved to optimality, " \
                "and an optimal solution is available."
            self.results.solver.termination_condition = TerminationCondition.optimal
            soln.status = SolutionStatus.optimal

        elif SOLSTA_MAP[sol_status] == 'pd_feas':
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message += " The solution is both primal and dual feasible"
            self.results.solver.termination_condition = TerminationCondition.feasible
            soln.status = SolutionStatus.feasible

        elif SOLSTA_MAP[sol_status] == 'p_feas':
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message += " Primal feasible solution is available."
            self.results.solver.termination_condition = TerminationCondition.feasible
            soln.status = SolutionStatus.feasible

        elif SOLSTA_MAP[sol_status] == 'd_feas':
            self.results.solver.status = SolverStatus.ok
            self.results.solver.termination_message += " Dual feasible solution is available."
            self.results.solver.termination_condition = TerminationCondition.feasible
            soln.status = SolutionStatus.feasible

        elif SOLSTA_MAP[sol_status] == 'd_infeas':
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message += " The solution is dual infeasible."
            self.results.solver.Message = self.results.solver.termination_message
            self.results.solver.termination_condition = TerminationCondition.unbounded
            soln.status = SolutionStatus.infeasible

        elif SOLSTA_MAP[sol_status] == 'p_infeas':
            self.results.solver.status = SolverStatus.warning
            self.results.solver.termination_message += " The solution is primal infeasible."
            self.results.solver.Message = self.results.solver.termination_message
            self.results.solver.termination_condition = TerminationCondition.infeasible
            soln.status = SolutionStatus.infeasible

        self.results.problem.name = msk_task.gettaskname()

        if msk_task.getobjsense() == msk.objsense.minimize:
            self.results.problem.sense = minimize
        elif msk_task.getobjsense() == msk.objsense.maximize:
            self.results.problem.sense = maximize
        else:
            raise RuntimeError(
                'Unrecognized Mosek objective sense: {0}'.format(
                    msk_task.getobjname()))

        self.results.problem.upper_bound = None
        self.results.problem.lower_bound = None

        if msk_task.getnumintvar() == 0:
            try:
                if msk_task.getobjsense() == msk.objsense.minimize:
                    self.results.problem.upper_bound = msk_task.getprimalobj(
                        whichsol)
                    self.results.problem.lower_bound = msk_task.getdualobj(
                        whichsol)
                elif msk_task.getobjsense() == msk.objsense.maximize:
                    self.results.problem.upper_bound = msk_task.getprimalobj(
                        whichsol)
                    self.results.problem.lower_bound = msk_task.getdualobj(
                        whichsol)

            except (msk.MosekException, AttributeError):
                pass
        elif msk_task.getobjsense() == msk.objsense.minimize:  # minimizing
            try:
                self.results.problem.upper_bound = msk_task.getprimalobj(
                    whichsol)
            except (msk.MosekException, AttributeError):
                pass
            try:
                self.results.problem.lower_bound = msk_task.getdouinf(
                    msk.dinfitem.mio_obj_bound)
            except (msk.MosekException, AttributeError):
                pass
        elif msk_task.getobjsense() == msk.objsense.maximize:  # maximizing
            try:
                self.results.problem.upper_bound = msk_task.getdouinf(
                    msk.dinfitem.mio_obj_bound)
            except (msk.MosekException, AttributeError):
                pass
            try:
                self.results.problem.lower_bound = msk_task.getprimalobj(
                    whichsol)
            except (msk.MosekException, AttributeError):
                pass
        else:
            raise RuntimeError(
                'Unrecognized Mosek objective sense: {0}'.format(
                    msk_task.getobjsense()))

        try:
            soln.gap = self.results.problem.upper_bound - self.results.problem.lower_bound
        except TypeError:
            soln.gap = None

        self.results.problem.number_of_constraints = msk_task.getnumcon()
        self.results.problem.number_of_nonzeros = msk_task.getnumanz()
        self.results.problem.number_of_variables = msk_task.getnumvar()
        self.results.problem.number_of_integer_variables = msk_task.getnumintvar(
        )
        self.results.problem.number_of_continuous_variables = msk_task.getnumvar() - \
            msk_task.getnumintvar()
        self.results.problem.number_of_objectives = 1
        self.results.problem.number_of_solutions = 1

        # if a solve was stopped by a limit, we still need to check to
        # see if there is a solution available - this may not always
        # be the case, both in LP and MIP contexts.
        if self._save_results:
            """
            This code in this if statement is only needed for backwards compatability. It is more efficient to set
            _save_results to False and use load_vars, load_duals, etc.
            """
            if self.results.problem.number_of_solutions > 0:
                soln_variables = soln.variable
                soln_constraints = soln.constraint

                mosek_vars = list(range(msk_task.getnumvar()))
                mosek_vars = list(
                    set(mosek_vars).intersection(
                        set(self._pyomo_var_to_solver_var_map.values())))
                var_vals = [0.0] * len(mosek_vars)
                self._solver_model.getxx(whichsol, var_vals)
                names = []
                for i in mosek_vars:
                    names.append(msk_task.getvarname(i))

                for mosek_var, val, name in zip(mosek_vars, var_vals, names):
                    pyomo_var = self._solver_var_to_pyomo_var_map[mosek_var]
                    if self._referenced_variables[pyomo_var] > 0:
                        pyomo_var.stale = False
                        soln_variables[name] = {"Value": val}

                if extract_reduced_costs:
                    vals = [0.0] * len(mosek_vars)
                    msk_task.getreducedcosts(whichsol, 0, len(mosek_vars),
                                             vals)
                    for mosek_var, val, name in zip(mosek_vars, vals, names):
                        pyomo_var = self._solver_var_to_pyomo_var_map[
                            mosek_var]
                        if self._referenced_variables[pyomo_var] > 0:
                            soln_variables[name]["Rc"] = val

                if extract_duals or extract_slacks:
                    mosek_cons = list(range(msk_task.getnumcon()))
                    con_names = []
                    for con in mosek_cons:
                        con_names.append(msk_task.getconname(con))
                    for name in con_names:
                        soln_constraints[name] = {}

                if extract_duals:
                    vals = [0.0] * msk_task.getnumcon()
                    msk_task.gety(whichsol, vals)
                    for val, name in zip(vals, con_names):
                        soln_constraints[name]["Dual"] = val

                if extract_slacks:

                    Ax = [0] * len(mosek_cons)
                    msk_task.getxc(self._whichsol, Ax)
                    for con, name in zip(mosek_cons, con_names):
                        Us = Ls = 0

                        bk, lb, ub = msk_task.getconbound(con)

                        if bk in [
                                msk.boundkey.fx, msk.boundkey.ra,
                                msk.boundkey.up
                        ]:
                            Us = ub - Ax[con]
                        if bk in [
                                msk.boundkey.fx, msk.boundkey.ra,
                                msk.boundkey.lo
                        ]:
                            Ls = Ax[con] - lb

                        if Us > Ls:
                            soln_constraints[name]["Slack"] = Us
                        else:
                            soln_constraints[name]["Slack"] = -Ls

        elif self._load_solutions:
            if self.results.problem.number_of_solutions > 0:

                self._load_vars()

                if extract_reduced_costs:
                    self._load_rc()

                if extract_duals:
                    self._load_duals()

                if extract_slacks:
                    self._load_slacks()

        self.results.solution.insert(soln)

        # finally, clean any temporary files registered with the temp file
        # manager, created populated *directly* by this plugin.
        TempfileManager.pop(remove=not self._keepfiles)

        return DirectOrPersistentSolver._postsolve(self)