예제 #1
0
파일: solvers.py 프로젝트: qtothec/pyomo
def initialize(**kwds):
    obj = Options(**kwds)
    #
    # Set obj.available
    #
    opt = None
    try:
        opt = SolverFactory(obj.name, solver_io=obj.io)
    except:
        pass
    if opt is None or isinstance(opt, UnknownSolver):
        obj.available = False
    elif (obj.name == "gurobi") and (not GUROBISHELL.license_is_valid()):
        obj.available = False
    elif (obj.name == "baron") and (not BARONSHELL.license_is_valid()):
        obj.available = False
    else:
        obj.available = (opt.available(exception_flag=False)) and (
            (not hasattr(opt, "executable")) or (opt.executable() is not None)
        )
    #
    # Check capabilities
    #
    if obj.available:
        for _c in obj.capabilities:
            if not _c in opt._capabilities:
                raise ValueError("Solver %s does not support capability %s!" % (obj.name, _c))
        #
        # Get version
        #
        obj.version = opt.version()
    return obj
예제 #2
0
파일: solvers.py 프로젝트: wannasmile/pyomo
def initialize(**kwds):
    obj = Options(**kwds)
    #
    # Set obj.available
    #
    opt = None
    try:
        opt = SolverFactory(obj.name, solver_io=obj.io)
    except:
        pass
    if opt is None or isinstance(opt, UnknownSolver):
        obj.available = False
    elif (obj.name == "gurobi") and \
       (not GUROBISHELL.license_is_valid()):
        obj.available = False
    elif (obj.name == "baron") and \
       (not BARONSHELL.license_is_valid()):
        obj.available = False
    else:
        obj.available = \
            (opt.available(exception_flag=False)) and \
            ((not hasattr(opt,'executable')) or \
            (opt.executable() is not None))
    #
    # Check capabilities
    #
    if obj.available:
        for _c in obj.capabilities:
            if not _c in opt._capabilities:
                raise ValueError("Solver %s does not support capability %s!" % (obj.name, _c))
        #
        # Get version
        #
        obj.version = opt.version()
    return obj
예제 #3
0
def get_solvers():
    """Return the solvers avaiable on the system."""
    from logging import getLogger

    logger = getLogger('pyomo.solvers')
    logger_status = logger.disabled
    logger.disabled = True  # no need for warnings: it's what we're testing!

    available_solvers = set()
    try:
        services = SF.services()  # pyutilib version <= 5.6.3
    except RuntimeError as e:
        services = SF  # pyutilib version >= 5.6.4

    for sname in services:
        # initial underscore ('_'): Pyomo's method to mark non-public plugins
        if '_' == sname[0]: continue

        solver = SF(sname)

        try:
            if not solver: continue
        except ApplicationError as e:
            continue

        if 'os' == sname: continue  # Workaround current bug in Coopr
        if not solver.available(exception_flag=False): continue
        available_solvers.add(sname)

    logger.disabled = logger_status  # put back the way it was.

    if available_solvers:
        if 'cplex' in available_solvers:
            default_solver = 'cplex'
        elif 'gurobi' in available_solvers:
            default_solver = 'gurobi'
        elif 'cbc' in available_solvers:
            default_solver = 'cbc'
        elif 'glpk' in available_solvers:
            default_solver = 'glpk'
        else:
            default_solver = iter(available_solvers).next()
    else:
        default_solver = 'NONE'
        SE.write(
            '\nNOTICE: Pyomo did not find any suitable solvers.  Temoa will '
            'not be able to solve any models.  If you need help, ask on the '
            'Temoa Project forum: http://temoaproject.org/\n\n')

    return (available_solvers, default_solver)
예제 #4
0
파일: nlp_solve.py 프로젝트: vova292/pyomo
def solve_linear_subproblem(mip_model, solve_data, config):
    GDPopt = mip_model.GDPopt_utils

    initialize_subproblem(mip_model, solve_data)

    # Callback immediately before solving NLP subproblem
    config.call_before_subproblem_solve(mip_model, solve_data)

    mip_solver = SolverFactory(config.mip_solver)
    if not mip_solver.available():
        raise RuntimeError("MIP solver %s is not available." %
                           config.mip_solver)
    with SuppressInfeasibleWarning():
        mip_args = dict(config.mip_solver_args)
        elapsed = get_main_elapsed_time(solve_data.timing)
        remaining = max(config.time_limit - elapsed, 1)
        if config.mip_solver == 'gams':
            mip_args['add_options'] = mip_args.get('add_options', [])
            mip_args['add_options'].append('option reslim=%s;' % remaining)
        elif config.mip_solver == 'multisolve':
            mip_args['time_limit'] = min(
                mip_args.get('time_limit', float('inf')), remaining)
        results = mip_solver.solve(mip_model, **mip_args)

    subprob_result = SubproblemResult()
    subprob_result.feasible = True
    subprob_result.var_values = list(v.value for v in GDPopt.variable_list)
    subprob_result.pyomo_results = results
    subprob_result.dual_values = list(
        mip_model.dual.get(c, None) for c in GDPopt.constraint_list)

    subprob_terminate_cond = results.solver.termination_condition
    if subprob_terminate_cond is tc.optimal:
        pass
    elif subprob_terminate_cond is tc.infeasible:
        config.logger.info('MIP subproblem was infeasible.')
        subprob_result.feasible = False
    else:
        raise ValueError('GDPopt unable to handle MIP subproblem termination '
                         'condition of %s. Results: %s' %
                         (subprob_terminate_cond, results))

    # Call the NLP post-solve callback
    config.call_after_subproblem_solve(mip_model, solve_data)

    # if feasible, call the NLP post-feasible callback
    if subprob_result.feasible:
        config.call_after_subproblem_feasible(mip_model, solve_data)

    return subprob_result
예제 #5
0
def initialize(**kwds):
    obj = Options(**kwds)
    #
    # Set the limits for the solver's "demo" (unlicensed) mode:
    #   ( nVars, nCons, nNonZeros )
    obj.demo_limits = (None, None, None)
    if (obj.name == "baron") and \
       (not BARONSHELL.license_is_valid()):
        obj.demo_limits = (10, 10, 50)
    #
    #
    # Set obj.available
    #
    opt = None
    try:
        opt = SolverFactory(obj.name, solver_io=obj.io)
    except:
        pass
    if opt is None or isinstance(opt, UnknownSolver):
        obj.available = False
    elif (obj.name == "gurobi") and \
       (not GUROBISHELL.license_is_valid()):
        obj.available = False
    elif (obj.name == "mosek") and \
       (not MosekDirect.license_is_valid()):
        obj.available = False
    else:
        obj.available = \
            (opt.available(exception_flag=False)) and \
            ((not hasattr(opt,'executable')) or \
            (opt.executable() is not None))
    #
    # Check capabilities, even if the solver is not available
    #
    if not (opt is None or isinstance(opt, UnknownSolver)):
        for _c in obj.capabilities:
            if not _c in opt._capabilities:
                raise ValueError("Solver %s does not support capability %s!" %
                                 (obj.name, _c))
    #
    # Get version
    #
    if obj.available:
        obj.version = opt.version()
    return obj
예제 #6
0
def initialize(**kwds):
    obj = Bunch(**kwds)
    #
    # Set obj.available
    #
    try:
        opt = SolverFactory(obj.name, solver_io=obj.io)
    except:
        opt = None

    if opt is None or isinstance(opt, UnknownSolver):
        obj.available = False
    elif not opt.available(exception_flag=False):
        obj.available = False
    elif hasattr(opt, 'executable') and opt.executable() is None:
        obj.available = False
    elif not opt.license_is_valid() \
         and obj.name not in licensed_solvers_with_demo_mode:
        obj.available = False
    else:
        obj.available = True
    #
    # Set the limits for the solver's "demo" (unlicensed) mode:
    #   ( nVars, nCons, nNonZeros )
    obj.demo_limits = (None, None, None)
    if obj.available:
        if obj.name == "baron" and not opt.license_is_valid():
            obj.demo_limits = (10, 10, 50)
    #
    # Check capabilities, even if the solver is not available
    #
    if not (opt is None or isinstance(opt, UnknownSolver)):
        for _c in obj.capabilities:
            if not _c in opt._capabilities:
                raise ValueError("Solver %s does not support capability %s!" %
                                 (obj.name, _c))
    #
    # Get version
    #
    if obj.available:
        obj.version = opt.version()
    return obj
예제 #7
0
def solve_linear_subproblem(mip_model, solve_data, config):
    GDPopt = mip_model.GDPopt_utils

    initialize_subproblem(mip_model, solve_data)

    # Callback immediately before solving NLP subproblem
    config.call_before_subproblem_solve(mip_model, solve_data)

    mip_solver = SolverFactory(config.mip_solver)
    if not mip_solver.available():
        raise RuntimeError("MIP solver %s is not available." %
                           config.mip_solver)
    with SuppressInfeasibleWarning():
        results = mip_solver.solve(mip_model, **config.mip_solver_args)

    subprob_result = SubproblemResult()
    subprob_result.feasible = True
    subprob_result.var_values = list(v.value for v in GDPopt.variable_list)
    subprob_result.pyomo_results = results
    subprob_result.dual_values = list(
        mip_model.dual.get(c, None) for c in GDPopt.constraint_list)

    subprob_terminate_cond = results.solver.termination_condition
    if subprob_terminate_cond is tc.optimal:
        pass
    elif subprob_terminate_cond is tc.infeasible:
        config.logger.info('MIP subproblem was infeasible.')
        subprob_result.feasible = False
    else:
        raise ValueError('GDPopt unable to handle MIP subproblem termination '
                         'condition of %s. Results: %s' %
                         (subprob_terminate_cond, results))

    # Call the NLP post-solve callback
    config.call_after_subproblem_solve(mip_model, solve_data)

    # if feasible, call the NLP post-feasible callback
    if subprob_result.feasible:
        config.call_after_subproblem_feasible(mip_model, solve_data)

    return subprob_result
예제 #8
0
def solve_MINLP(model, solve_data, config):
    """Solve the MINLP subproblem."""
    config.logger.info(
        "Solving MINLP subproblem for fixed logical realizations.")

    GDPopt = model.GDPopt_utils

    initialize_subproblem(model, solve_data)

    # Callback immediately before solving MINLP subproblem
    config.call_before_subproblem_solve(model, solve_data)

    minlp_solver = SolverFactory(config.minlp_solver)
    if not minlp_solver.available():
        raise RuntimeError("MINLP solver %s is not available." %
                           config.minlp_solver)
    with SuppressInfeasibleWarning():
        results = minlp_solver.solve(model, **config.minlp_solver_args)

    subprob_result = SubproblemResult()
    subprob_result.feasible = True
    subprob_result.var_values = list(v.value for v in GDPopt.variable_list)
    subprob_result.pyomo_results = results
    subprob_result.dual_values = list(
        model.dual.get(c, None) for c in GDPopt.constraint_list)

    term_cond = results.solver.termination_condition
    if any(term_cond == cond
           for cond in (tc.optimal, tc.locallyOptimal, tc.feasible)):
        pass
    elif term_cond == tc.infeasible:
        config.logger.info('MINLP subproblem was infeasible.')
        subprob_result.feasible = False
    elif term_cond == tc.maxIterations:
        # TODO try something else? Reinitialize with different initial
        # value?
        config.logger.info(
            'MINLP subproblem failed to converge within iteration limit.')
        if is_feasible(model, config):
            config.logger.info(
                'MINLP solution is still feasible. '
                'Using potentially suboptimal feasible solution.')
        else:
            subprob_result.feasible = False
    elif term_cond == tc.intermediateNonInteger:
        config.logger.info(
            "MINLP solver could not find feasible integer solution: %s" %
            results.solver.message)
        subprob_result.feasible = False
    else:
        raise ValueError(
            'GDPopt unable to handle MINLP subproblem termination '
            'condition of %s. Results: %s' % (term_cond, results))

    # Call the subproblem post-solve callback
    config.call_after_subproblem_solve(model, solve_data)

    # if feasible, call the subproblem post-feasible callback
    if subprob_result.feasible:
        config.call_after_subproblem_feasible(model, solve_data)

    return subprob_result
예제 #9
0
파일: nlp_solve.py 프로젝트: CanLi1/pyomo
def solve_NLP(nlp_model, solve_data, config):
    """Solve the NLP subproblem."""
    config.logger.info('Solving nonlinear subproblem for '
                       'fixed binaries and logical realizations.')

    # Error checking for unfixed discrete variables
    unfixed_discrete_vars = detect_unfixed_discrete_vars(nlp_model)
    assert len(unfixed_discrete_vars) == 0, \
        "Unfixed discrete variables exist on the NLP subproblem: {0}".format(
        list(v.name for v in unfixed_discrete_vars))

    GDPopt = nlp_model.GDPopt_utils

    if config.subproblem_presolve:
        preprocess_subproblem(nlp_model, config)

    initialize_subproblem(nlp_model, solve_data)

    # Callback immediately before solving NLP subproblem
    config.call_before_subproblem_solve(nlp_model, solve_data)

    nlp_solver = SolverFactory(config.nlp_solver)
    if not nlp_solver.available():
        raise RuntimeError("NLP solver %s is not available." %
                           config.nlp_solver)
    with SuppressInfeasibleWarning():
        results = nlp_solver.solve(nlp_model, **config.nlp_solver_args)

    nlp_result = SubproblemResult()
    nlp_result.feasible = True
    nlp_result.var_values = list(v.value for v in GDPopt.variable_list)
    nlp_result.pyomo_results = results
    nlp_result.dual_values = list(
        nlp_model.dual.get(c, None) for c in GDPopt.constraint_list)

    subprob_terminate_cond = results.solver.termination_condition
    if (subprob_terminate_cond is tc.optimal
            or subprob_terminate_cond is tc.locallyOptimal
            or subprob_terminate_cond is tc.feasible):
        pass
    elif subprob_terminate_cond is tc.infeasible:
        config.logger.info('NLP subproblem was infeasible.')
        nlp_result.feasible = False
    elif subprob_terminate_cond is tc.maxIterations:
        # TODO try something else? Reinitialize with different initial
        # value?
        config.logger.info(
            'NLP subproblem failed to converge within iteration limit.')
        if is_feasible(nlp_model, config):
            config.logger.info(
                'NLP solution is still feasible. '
                'Using potentially suboptimal feasible solution.')
        else:
            nlp_result.feasible = False
    elif subprob_terminate_cond is tc.internalSolverError:
        # Possible that IPOPT had a restoration failure
        config.logger.info("NLP solver had an internal failure: %s" %
                           results.solver.message)
        nlp_result.feasible = False
    else:
        raise ValueError('GDPopt unable to handle NLP subproblem termination '
                         'condition of %s. Results: %s' %
                         (subprob_terminate_cond, results))

    # Call the NLP post-solve callback
    config.call_after_subproblem_solve(nlp_model, solve_data)

    # if feasible, call the NLP post-feasible callback
    if nlp_result.feasible:
        config.call_after_subproblem_feasible(nlp_model, solve_data)

    return nlp_result
예제 #10
0
파일: sens.py 프로젝트: tangwei2020/pyomo
def sipopt(instance,
           paramSubList,
           perturbList,
           cloneModel=True,
           streamSoln=False,
           keepfiles=False):
    """This function accepts a Pyomo ConcreteModel, a list of parameters, along
    with their corresponding perterbation list. The model is then converted
    into the design structure required to call sipopt to get an approximation
    perturbed solution with updated bounds on the decision variable. 
    
    Parameters
    ----------
    instance: ConcreteModel
        pyomo model object

    paramSubList: list
        list of mutable parameters

    perturbList: list
        list of perturbed parameter values

    cloneModel: bool, optional
        indicator to clone the model. If set to False, the original
        model will be altered

    streamSoln: bool, optional
        indicator to stream IPOPT solution

    keepfiles: bool, optional
        preserve solver interface files
    
    Returns
    -------
    model: ConcreteModel
        The model modified for use with sipopt.  The returned model has
        three :class:`Suffix` members defined:

        - ``model.sol_state_1``: the approximated results at the
          perturbation point
        - ``model.sol_state_1_z_L``: the updated lower bound
        - ``model.sol_state_1_z_U``: the updated upper bound

    Raises
    ------
    ValueError
        perturbList argument is expecting a List of Params
    ValueError
        length(paramSubList) must equal length(perturbList)
    ValueError
        paramSubList will not map to perturbList

    """

    #Verify User Inputs
    if len(paramSubList) != len(perturbList):
        raise ValueError("Length of paramSubList argument does not equal "
                         "length of perturbList")

    for pp in paramSubList:
        if pp.ctype is not Param:
            raise ValueError(
                "paramSubList argument is expecting a list of Params")

    for pp in paramSubList:
        if not pp._mutable:
            raise ValueError("parameters within paramSubList must be mutable")

    for pp in perturbList:
        if pp.ctype is not Param:
            raise ValueError(
                "perturbList argument is expecting a list of Params")
    #Add model block to compartmentalize all sipopt data
    b = Block()
    block_name = unique_component_name(instance, '_sipopt_data')
    instance.add_component(block_name, b)

    #Based on user input clone model or use orignal model for anlaysis
    if cloneModel:
        b.tmp_lists = (paramSubList, perturbList)
        m = instance.clone()
        instance.del_component(block_name)
        b = getattr(m, block_name)
        paramSubList, perturbList = b.tmp_lists
        del b.tmp_lists
    else:
        m = instance

    #Generate component maps for associating Variables to perturbations
    varSubList = []
    for parameter in paramSubList:
        tempName = unique_component_name(b, parameter.local_name)
        b.add_component(tempName, Var(parameter.index_set()))
        myVar = b.component(tempName)
        varSubList.append(myVar)

    #Note: substitutions are not currently compatible with
    #      ComponentMap [ECSA 2018/11/23], this relates to Issue #755
    paramCompMap = ComponentMap(zip(paramSubList, varSubList))
    variableSubMap = {}
    #variableSubMap = ComponentMap()
    paramPerturbMap = ComponentMap(zip(paramSubList, perturbList))
    perturbSubMap = {}
    #perturbSubMap = ComponentMap()

    paramDataList = []
    for parameter in paramSubList:
        # Loop over each ParamData in the Param Component
        #
        # Note: Sets are unordered in Pyomo.  For this to be
        # deterministic, we need to sort the index (otherwise, the
        # ordering of things in the paramDataList may change).  We use
        # sorted_robust to guard against mixed-type Sets in Python 3.x
        for kk in sorted_robust(parameter):
            variableSubMap[id(parameter[kk])] = paramCompMap[parameter][kk]
            perturbSubMap[id(parameter[kk])] = paramPerturbMap[parameter][kk]
            paramDataList.append(parameter[kk])

    #clone Objective, add to Block, and update any Expressions
    for cc in list(
            m.component_data_objects(Objective, active=True,
                                     descend_into=True)):
        tempName = unique_component_name(m, cc.local_name)
        b.add_component(
            tempName,
            Objective(expr=ExpressionReplacementVisitor(
                substitute=variableSubMap,
                remove_named_expressions=True).dfs_postorder_stack(cc.expr)))
        cc.deactivate()

    #clone Constraints, add to Block, and update any Expressions
    b.constList = ConstraintList()
    for cc in list(
            m.component_data_objects(Constraint,
                                     active=True,
                                     descend_into=True)):
        if cc.equality:
            b.constList.add(expr=ExpressionReplacementVisitor(
                substitute=variableSubMap,
                remove_named_expressions=True).dfs_postorder_stack(cc.expr))
        else:
            try:
                b.constList.add(expr=ExpresssionReplacementVisitor(
                    substitute=variableSubMap, remove_named_expressions=True).
                                dfs_postorder_stack(cc.expr))
            except:
                # Params in either the upper or lower bounds of a ranged
                # inequaltiy will result in an invalid expression (you cannot
                # have variables in the bounds of a constraint).  If we hit that
                # problem, we will break up the ranged inequality into separate
                # constraints

                # Note that the test for lower / upper == None is probably not
                # necessary, as the only way we should get here (especially if
                # we are more careful about the exception that we catch) is if
                # this is a ranged inequality and we are attempting to insert a
                # variable into either the lower or upper bound.
                if cc.lower is not None:
                    b.constList.add(expr=ExpressionReplacementVisitor(
                        substitute=variableSubMap,
                        remove_named_expressions=True).dfs_postorder_stack(
                            cc.lower) <= ExpressionReplacementVisitor(
                                substitute=variableSubMap,
                                remove_named_expressions=True).
                                    dfs_postorder_stack(cc.body))
                #if cc.lower is not None:
                #    b.constList.add(expr=0<=ExpressionReplacementVisitor(
                #        substitute=variableSubMap,
                #        remove_named_expressions=True).dfs_postorder_stack(
                #            cc.lower) - ExpressionReplacementVisitor(
                #                substitute=variableSubMap,
                #                remove_named_expressions=
                #                  True).dfs_postorder_stack(cc.body)
                #                )
                if cc.upper is not None:
                    b.constList.add(expr=ExpressionReplacementVisitor(
                        substitute=variableSubMap,
                        remove_named_expressions=True).dfs_postorder_stack(
                            cc.upper) >= ExpressionReplacementVisitor(
                                substitute=variableSubMap,
                                remove_named_expressions=True).
                                    dfs_postorder_stack(cc.body))
        cc.deactivate()

    #paramData to varData constraint list
    b.paramConst = ConstraintList()
    for ii in paramDataList:
        jj = variableSubMap[id(ii)]
        b.paramConst.add(ii == jj)

    #Create the ipopt_sens (aka sIPOPT) solver plugin using the ASL interface
    opt = SolverFactory('ipopt_sens', solver_io='nl')

    if not opt.available(False):
        raise ImportError('ipopt_sens is not available')

    #Declare Suffixes
    m.sens_state_0 = Suffix(direction=Suffix.EXPORT)
    m.sens_state_1 = Suffix(direction=Suffix.EXPORT)
    m.sens_state_value_1 = Suffix(direction=Suffix.EXPORT)
    m.sens_init_constr = Suffix(direction=Suffix.EXPORT)

    m.sens_sol_state_1 = Suffix(direction=Suffix.IMPORT)
    m.sens_sol_state_1_z_L = Suffix(direction=Suffix.IMPORT)
    m.sens_sol_state_1_z_U = Suffix(direction=Suffix.IMPORT)

    #set sIPOPT data
    opt.options['run_sens'] = 'yes'

    # for reasons that are not entirely clear,
    #     ipopt_sens requires the indices to start at 1
    kk = 1
    for ii in paramDataList:
        m.sens_state_0[variableSubMap[id(ii)]] = kk
        m.sens_state_1[variableSubMap[id(ii)]] = kk
        m.sens_state_value_1[variableSubMap[id(ii)]] = \
                                                   value(perturbSubMap[id(ii)])
        m.sens_init_constr[b.paramConst[kk]] = kk
        kk += 1

    #Send the model to the ipopt_sens and collect the solution
    results = opt.solve(m, keepfiles=keepfiles, tee=streamSoln)

    return m
예제 #11
0
파일: test_GAMS.py 프로젝트: zypher22/pyomo
#  rights in this software.
#  This software is distributed under the 3-clause BSD License.
#  ___________________________________________________________________________

from pyomo.environ import ConcreteModel, Var, Objective, Constraint, maximize, Expression, log10
from pyomo.opt import SolverFactory, TerminationCondition

from pyomo.solvers.plugins.solvers.GAMS import (GAMSShell, GAMSDirect,
                                                gdxcc_available)
import pyutilib.th as unittest
from pyutilib.misc import capture_output
import os, shutil
from tempfile import mkdtemp

opt_py = SolverFactory('gams', solver_io='python')
gamspy_available = opt_py.available(exception_flag=False)
if gamspy_available:
    from gams.workspace import GamsExceptionExecution

opt_gms = SolverFactory('gams', solver_io='gms')
gamsgms_available = opt_gms.available(exception_flag=False)


class GAMSTests(unittest.TestCase):
    @unittest.skipIf(not gamspy_available,
                     "The 'gams' python bindings are not available")
    def test_check_expr_eval_py(self):
        with SolverFactory("gams", solver_io="python") as opt:

            m = ConcreteModel()
            m.x = Var()
예제 #12
0
def get_dfds_dcds(model, theta_names, tee=False, solver_options=None):
    """This function calculates gradient vector of the objective function 
       and constraints with respect to the variables and parameters.

    e.g) min f:  p1*x1+ p2*(x2^2) + p1*p2
         s.t  c1: x1 + x2 = p1
              c2: x2 + x3 = p2
              0 <= x1, x2, x3 <= 10
              p1 = 10
              p2 = 5
    - Variables = (x1, x2, x3, p1, p2)
    - Fix p1 and p2 with estimated values

    The following terms are used to define the output dimensions:
    Ncon   = number of constraints
    Nvar   = number of variables (Nx + Ntheta)
    Nx     = number of decision (primal) variables
    Ntheta = number of uncertain parameters.

    Parameters
    ----------
    model: Pyomo ConcreteModel
        model should include an objective function
    theta_names: list of strings
        List of Var names
    tee: bool, optional
        Indicates that ef solver output should be teed
    solver_options: dict, optional
        Provides options to the solver (also the name of an attribute)

    Returns
    -------
    gradient_f: numpy.ndarray
        Length Nvar array. A gradient vector of the objective function
        with respect to the (decision variables, parameters) at the optimal
        solution
    gradient_c: scipy.sparse.csr.csr_matrix
        Ncon by Nvar size sparse matrix. A Jacobian matrix of the
        constraints with respect to the (decision variables, parameters)
        at the optimal solution. Each row contains [column number,
        row number, and value], column order follows variable order in col
        and index starts from 1. Note that it follows k_aug.
        If no constraint exists, return []
    col: list
        Size Nvar list of variable names
    row: list
        Size Ncon+1 list of constraints and objective function names.
        The final element is the objective function name.
    line_dic: dict
        column numbers of the theta_names in the model. Index starts from 1

    Raises
    ------
    RuntimeError
        When ipopt or k_aug or dotsens is not available
    Exception
        When ipopt fails 
    """
    # Create the solver plugin using the ASL interface
    ipopt = SolverFactory('ipopt', solver_io='nl')
    if solver_options is not None:
        ipopt.options = solver_options
    k_aug = SolverFactory('k_aug', solver_io='nl')
    if not ipopt.available(False):
        raise RuntimeError('ipopt is not available')
    if not k_aug.available(False):
        raise RuntimeError('k_aug is not available')

    # Declare Suffixes
    _add_sensitivity_suffixes(model)

    # K_AUG SUFFIXES
    model.dof_v = Suffix(direction=Suffix.EXPORT)  #: SUFFIX FOR K_AUG
    model.rh_name = Suffix(
        direction=Suffix.IMPORT)  #: SUFFIX FOR K_AUG AS WELL
    k_aug.options["print_kkt"] = ""

    results = ipopt.solve(model, tee=tee)

    # Raise exception if ipopt fails
    if (results.solver.status == SolverStatus.warning):
        raise Exception(results.solver.Message)

    for o in model.component_objects(Objective, active=True):
        f_mean = value(o)
    model.ipopt_zL_in.update(model.ipopt_zL_out)
    model.ipopt_zU_in.update(model.ipopt_zU_out)

    # run k_aug
    k_aug_interface = K_augInterface(k_aug=k_aug)
    k_aug_interface.k_aug(model, tee=tee)  #: always call k_aug AFTER ipopt.

    nl_data = {}
    with InTempDir():
        base_fname = "col_row"
        nl_file = ".".join((base_fname, "nl"))
        row_file = ".".join((base_fname, "row"))
        col_file = ".".join((base_fname, "col"))
        model.write(nl_file, io_options={"symbolic_solver_labels": True})
        for fname in [nl_file, row_file, col_file]:
            with open(fname, "r") as fp:
                nl_data[fname] = fp.read()

    col = nl_data[col_file].strip("\n").split("\n")
    row = nl_data[row_file].strip("\n").split("\n")

    # get the column numbers of "parameters"
    line_dic = {name: col.index(name) for name in theta_names}

    grad_f_file = os.path.join("GJH", "gradient_f_print.txt")
    grad_f_string = k_aug_interface.data[grad_f_file]
    gradient_f = np.fromstring(grad_f_string, sep="\n\t")
    col = [
        i for i in col
        if SensitivityInterface.get_default_block_name() not in i
    ]

    grad_c_file = os.path.join("GJH", "A_print.txt")
    grad_c_string = k_aug_interface.data[grad_c_file]
    gradient_c = np.fromstring(grad_c_string, sep="\n\t")

    # Jacobian file is in "COO format," i.e. an nnz-by-3 array.
    # Reshape to a numpy array that matches this format.
    gradient_c = gradient_c.reshape((-1, 3))

    num_constraints = len(row) - 1  # Objective is included as a row
    if num_constraints > 0:
        row_idx = gradient_c[:, 1] - 1
        col_idx = gradient_c[:, 0] - 1
        data = gradient_c[:, 2]
        gradient_c = scipy.sparse.csr_matrix((data, (row_idx, col_idx)),
                                             shape=(num_constraints, len(col)))
    else:
        gradient_c = np.array([])

    return gradient_f, gradient_c, col, row, line_dic
예제 #13
0
파일: nlp_solve.py 프로젝트: xfLee/pyomo
def solve_NLP(nlp_model, solve_data, config):
    """Solve the NLP subproblem."""
    config.logger.info('Solving nonlinear subproblem for '
                       'fixed binaries and logical realizations.')
    unfixed_discrete_vars = detect_unfixed_discrete_vars(nlp_model)
    if unfixed_discrete_vars:
        discrete_var_names = list(v.name for v in unfixed_discrete_vars)
        config.logger.warning(
            "Unfixed discrete variables exist on the NLP subproblem: %s" %
            (discrete_var_names, ))

    GDPopt = nlp_model.GDPopt_utils

    preprocessing_transformations = [
        # Propagate variable bounds
        'contrib.propagate_eq_var_bounds',
        # Detect fixed variables
        'contrib.detect_fixed_vars',
        # Propagate fixed variables
        'contrib.propagate_fixed_vars',
        # Remove zero terms in linear expressions
        'contrib.remove_zero_terms',
        # Remove terms in equal to zero summations
        'contrib.propagate_zero_sum',
        # Transform bound constraints
        'contrib.constraints_to_var_bounds',
        # Detect fixed variables
        'contrib.detect_fixed_vars',
        # Remove terms in equal to zero summations
        'contrib.propagate_zero_sum',
        # Remove trivial constraints
        'contrib.deactivate_trivial_constraints'
    ]
    for xfrm in preprocessing_transformations:
        TransformationFactory(xfrm).apply_to(nlp_model)

    initialize_NLP(nlp_model, solve_data)

    # Callback immediately before solving NLP subproblem
    config.call_before_subproblem_solve(nlp_model, solve_data)

    nlp_solver = SolverFactory(config.nlp_solver)
    if not nlp_solver.available():
        raise RuntimeError("NLP solver %s is not available." %
                           config.nlp_solver)
    with SuppressInfeasibleWarning():
        results = nlp_solver.solve(nlp_model, **config.nlp_solver_args)

    nlp_result = SubproblemResult()
    nlp_result.feasible = True
    nlp_result.var_values = list(v.value for v in GDPopt.working_var_list)
    nlp_result.pyomo_results = results
    nlp_result.dual_values = list(
        nlp_model.dual.get(c, None) for c in GDPopt.working_constraints_list)

    subprob_terminate_cond = results.solver.termination_condition
    if subprob_terminate_cond is tc.optimal:
        pass
    elif subprob_terminate_cond is tc.infeasible:
        config.logger.info('NLP subproblem was locally infeasible.')
        nlp_result.feasible = False
    elif subprob_terminate_cond is tc.maxIterations:
        # TODO try something else? Reinitialize with different initial
        # value?
        config.logger.info(
            'NLP subproblem failed to converge within iteration limit.')
        if is_feasible(nlp_model, config):
            config.logger.info(
                'NLP solution is still feasible. '
                'Using potentially suboptimal feasible solution.')
        else:
            nlp_result.feasible = False
    elif subprob_terminate_cond is tc.internalSolverError:
        # Possible that IPOPT had a restoration failture
        config.logger.info("NLP solver had an internal failure: %s" %
                           results.solver.message)
        nlp_result.feasible = False
    else:
        raise ValueError('GDPopt unable to handle NLP subproblem termination '
                         'condition of %s. Results: %s' %
                         (subprob_terminate_cond, results))

    # Call the NLP post-solve callback
    config.call_after_subproblem_solve(nlp_model, solve_data)

    # if feasible, call the NLP post-feasible callback
    if nlp_result.feasible:
        config.call_after_subproblem_feasible(nlp_model, solve_data)

    return nlp_result
예제 #14
0
파일: nlp_solve.py 프로젝트: Pyomo/pyomo
def solve_NLP(nlp_model, solve_data, config):
    """Solve the NLP subproblem."""
    config.logger.info(
        'Solving nonlinear subproblem for '
        'fixed binaries and logical realizations.')

    # Error checking for unfixed discrete variables
    unfixed_discrete_vars = detect_unfixed_discrete_vars(nlp_model)
    assert len(unfixed_discrete_vars) == 0, \
        "Unfixed discrete variables exist on the NLP subproblem: {0}".format(
        list(v.name for v in unfixed_discrete_vars))

    GDPopt = nlp_model.GDPopt_utils

    if config.subproblem_presolve:
        preprocess_subproblem(nlp_model, config)

    initialize_subproblem(nlp_model, solve_data)

    # Callback immediately before solving NLP subproblem
    config.call_before_subproblem_solve(nlp_model, solve_data)

    nlp_solver = SolverFactory(config.nlp_solver)
    if not nlp_solver.available():
        raise RuntimeError("NLP solver %s is not available." %
                           config.nlp_solver)
    with SuppressInfeasibleWarning():
        results = nlp_solver.solve(nlp_model, **config.nlp_solver_args)

    nlp_result = SubproblemResult()
    nlp_result.feasible = True
    nlp_result.var_values = list(v.value for v in GDPopt.variable_list)
    nlp_result.pyomo_results = results
    nlp_result.dual_values = list(
        nlp_model.dual.get(c, None)
        for c in GDPopt.constraint_list)

    subprob_terminate_cond = results.solver.termination_condition
    if (subprob_terminate_cond is tc.optimal or
            subprob_terminate_cond is tc.locallyOptimal or
            subprob_terminate_cond is tc.feasible):
        pass
    elif subprob_terminate_cond is tc.infeasible:
        config.logger.info('NLP subproblem was infeasible.')
        nlp_result.feasible = False
    elif subprob_terminate_cond is tc.maxIterations:
        # TODO try something else? Reinitialize with different initial
        # value?
        config.logger.info(
            'NLP subproblem failed to converge within iteration limit.')
        if is_feasible(nlp_model, config):
            config.logger.info(
                'NLP solution is still feasible. '
                'Using potentially suboptimal feasible solution.')
        else:
            nlp_result.feasible = False
    elif subprob_terminate_cond is tc.internalSolverError:
        # Possible that IPOPT had a restoration failure
        config.logger.info(
            "NLP solver had an internal failure: %s" % results.solver.message)
        nlp_result.feasible = False
    else:
        raise ValueError(
            'GDPopt unable to handle NLP subproblem termination '
            'condition of %s. Results: %s'
            % (subprob_terminate_cond, results))

    # Call the NLP post-solve callback
    config.call_after_subproblem_solve(nlp_model, solve_data)

    # if feasible, call the NLP post-feasible callback
    if nlp_result.feasible:
        config.call_after_subproblem_feasible(nlp_model, solve_data)

    return nlp_result
예제 #15
0
def solve_NLP(nlp_model, solve_data, config):
    """Solve the NLP subproblem."""
    config.logger.info('Solving nonlinear subproblem for '
                       'fixed binaries and logical realizations.')

    # Error checking for unfixed discrete variables
    unfixed_discrete_vars = detect_unfixed_discrete_vars(nlp_model)
    assert len(unfixed_discrete_vars) == 0, \
        "Unfixed discrete variables exist on the NLP subproblem: {0}".format(
        list(v.name for v in unfixed_discrete_vars))

    GDPopt = nlp_model.GDPopt_utils

    initialize_subproblem(nlp_model, solve_data)

    # Callback immediately before solving NLP subproblem
    config.call_before_subproblem_solve(nlp_model, solve_data)

    nlp_solver = SolverFactory(config.nlp_solver)
    if not nlp_solver.available():
        raise RuntimeError("NLP solver %s is not available." %
                           config.nlp_solver)
    with SuppressInfeasibleWarning():
        try:
            results = nlp_solver.solve(nlp_model, **config.nlp_solver_args)
        except ValueError as err:
            if 'Cannot load SolverResults object with bad status: error' in str(
                    err):
                results = SolverResults()
                results.solver.termination_condition = tc.error
                results.solver.message = str(err)
            else:
                raise

    nlp_result = SubproblemResult()
    nlp_result.feasible = True
    nlp_result.var_values = list(v.value for v in GDPopt.variable_list)
    nlp_result.pyomo_results = results
    nlp_result.dual_values = list(
        nlp_model.dual.get(c, None) for c in GDPopt.constraint_list)

    term_cond = results.solver.termination_condition
    if any(term_cond == cond
           for cond in (tc.optimal, tc.locallyOptimal, tc.feasible)):
        pass
    elif term_cond == tc.infeasible:
        config.logger.info('NLP subproblem was infeasible.')
        nlp_result.feasible = False
    elif term_cond == tc.maxIterations:
        # TODO try something else? Reinitialize with different initial
        # value?
        config.logger.info(
            'NLP subproblem failed to converge within iteration limit.')
        if is_feasible(nlp_model, config):
            config.logger.info(
                'NLP solution is still feasible. '
                'Using potentially suboptimal feasible solution.')
        else:
            nlp_result.feasible = False
    elif term_cond == tc.internalSolverError:
        # Possible that IPOPT had a restoration failure
        config.logger.info("NLP solver had an internal failure: %s" %
                           results.solver.message)
        nlp_result.feasible = False
    elif (term_cond == tc.other
          and "Too few degrees of freedom" in str(results.solver.message)):
        # Possible IPOPT degrees of freedom error
        config.logger.info("IPOPT has too few degrees of freedom: %s" %
                           results.solver.message)
        nlp_result.feasible = False
    elif term_cond == tc.other:
        config.logger.info(
            "NLP solver had a termination condition of 'other': %s" %
            results.solver.message)
        nlp_result.feasible = False
    elif term_cond == tc.error:
        config.logger.info(
            "NLP solver had a termination condition of 'error': %s" %
            results.solver.message)
        nlp_result.feasible = False
    elif term_cond == tc.maxTimeLimit:
        config.logger.info(
            "NLP solver ran out of time. Assuming infeasible for now.")
        nlp_result.feasible = False
    else:
        raise ValueError('GDPopt unable to handle NLP subproblem termination '
                         'condition of %s. Results: %s' % (term_cond, results))

    # Call the NLP post-solve callback
    config.call_after_subproblem_solve(nlp_model, solve_data)

    # if feasible, call the NLP post-feasible callback
    if nlp_result.feasible:
        config.call_after_subproblem_feasible(nlp_model, solve_data)

    return nlp_result
예제 #16
0
파일: sens.py 프로젝트: Pyomo/pyomo
def sipopt(instance,paramSubList,perturbList,cloneModel=True,
					     streamSoln=False,
					     keepfiles=False):
    """
    This function accepts a Pyomo ConcreteModel, a list of parameters, along
    with their corresponding perterbation list. The model is then converted
    into the design structure required to call sipopt to get an approximation
    perturbed solution with updated bounds on the decision variable. 
    
    Arguments:
        instance     : ConcreteModel: Expectation No Exceptions
            pyomo model object

        paramSubList : Param         
            list of mutable parameters
            Exception : "paramSubList argument is expecting a List of Params"	    

        perturbList  : Param	    
            list of perturbed parameter values
            Exception : "perturbList argument is expecting a List of Params"

            length(paramSubList) must equal length(perturbList)
            Exception : "paramSubList will not map to perturbList"  


        cloneModel   : boolean      : default=True	    
            indicator to clone the model
                -if set to False, the original model will be altered

        streamSoln   : boolean      : default=False	    
            indicator to stream IPOPT solution

        keepfiles    : boolean	    : default=False 
            indicator to print intermediate file names
    
    Returns:
        m		  : ConcreteModel
            converted model for sipopt

        m.sol_state_1     : Suffix	  
            approximated results at perturbation

        m.sol_state_1_z_L : Suffix        
            updated lower bound

        m.sol_state_1_z_U : Suffix        
            updated upper bound
    """

    #Verify User Inputs    
    if len(paramSubList)!=len(perturbList):
        raise ValueError("Length of paramSubList argument does not equal "
                        "length of perturbList")

    for pp in paramSubList:
        if pp.type() is not Param:
            raise ValueError("paramSubList argument is expecting a list of Params")

    for pp in paramSubList:
        if not pp._mutable:
            raise ValueError("parameters within paramSubList must be mutable")  

        
    for pp in perturbList:
        if pp.type() is not Param:
            raise ValueError("perturbList argument is expecting a list of Params")
    #Add model block to compartmentalize all sipopt data
    b=Block()
    block_name = unique_component_name(instance, '_sipopt_data')
    instance.add_component(block_name, b)

    #Based on user input clone model or use orignal model for anlaysis
    if cloneModel:
        b.tmp_lists = (paramSubList, perturbList)
        m = instance.clone()
        instance.del_component(block_name)
        b = getattr(m, block_name)
        paramSubList, perturbList = b.tmp_lists
        del b.tmp_lists
    else:
        m = instance
    
    #Generate component maps for associating Variables to perturbations
    varSubList = []
    for parameter in paramSubList:
        tempName = unique_component_name(b,parameter.local_name)
        b.add_component(tempName,Var(parameter.index_set()))
        myVar = b.component(tempName)
        varSubList.append(myVar)
 
    #Note: substitutions are not currently compatible with 
    #      ComponentMap [ECSA 2018/11/23], this relates to Issue #755
    paramCompMap = ComponentMap(zip(paramSubList, varSubList))
    variableSubMap = {}
    #variableSubMap = ComponentMap()
    paramPerturbMap = ComponentMap(zip(paramSubList,perturbList))
    perturbSubMap = {}
    #perturbSubMap = ComponentMap()
   
    paramDataList = [] 
    for parameter in paramSubList:
        # Loop over each ParamData in the Param Component
        #
        # Note: Sets are unordered in Pyomo.  For this to be
        # deterministic, we need to sort the index (otherwise, the
        # ordering of things in the paramDataList may change).  We use
        # sorted_robust to guard against mixed-type Sets in Python 3.x
        for kk in sorted_robust(parameter):
            variableSubMap[id(parameter[kk])]=paramCompMap[parameter][kk]
            perturbSubMap[id(parameter[kk])]=paramPerturbMap[parameter][kk]
            paramDataList.append(parameter[kk])

    #clone Objective, add to Block, and update any Expressions
    for cc in list(m.component_data_objects(Objective,
                                            active=True,
                                            descend_into=True)):
        tempName=unique_component_name(m,cc.local_name)    
        b.add_component(tempName,
                  Objective(expr=ExpressionReplacementVisitor(
                  substitute=variableSubMap,
                  remove_named_expressions=True).dfs_postorder_stack(cc.expr)))
        cc.deactivate()
    
    #clone Constraints, add to Block, and update any Expressions
    b.constList = ConstraintList()
    for cc in list(m.component_data_objects(Constraint, 
                                   active=True,
                                   descend_into=True)):
        if cc.equality:
            b.constList.add(expr= ExpressionReplacementVisitor(
                    substitute=variableSubMap,
                    remove_named_expressions=True).dfs_postorder_stack(cc.expr))
        else:
            try:
                b.constList.add(expr=ExpresssionReplacementVisitor(
                    substitute=variableSubMap,
                    remove_named_expressions=True).dfs_postorder_stack(cc.expr))
            except:
                # Params in either the upper or lower bounds of a ranged 
                # inequaltiy will result in an invalid expression (you cannot 
                # have variables in the bounds of a constraint).  If we hit that
                # problem, we will break up the ranged inequality into separate
                # constraints

                # Note that the test for lower / upper == None is probably not
                # necessary, as the only way we should get here (especially if
                # we are more careful about the exception that we catch) is if
                # this is a ranged inequality and we are attempting to insert a
                # variable into either the lower or upper bound.
                if cc.lower is not None:
                    b.constList.add(expr=ExpressionReplacementVisitor(
                        substitute=variableSubMap,
                        remove_named_expressions=True).dfs_postorder_stack(
                            cc.lower) <= ExpressionReplacementVisitor(
                                substitute=variableSubMap,
                                remove_named_expressions=
                                  True).dfs_postorder_stack(cc.body)
                                )
                #if cc.lower is not None:
                #    b.constList.add(expr=0<=ExpressionReplacementVisitor(
                #        substitute=variableSubMap,
                #        remove_named_expressions=True).dfs_postorder_stack(
                #            cc.lower) - ExpressionReplacementVisitor(
                #                substitute=variableSubMap,
                #                remove_named_expressions=
                #                  True).dfs_postorder_stack(cc.body)
                #                )
                if cc.upper is not None:
                    b.constList.add(expr=ExpressionReplacementVisitor(
                        substitute=variableSubMap,
                        remove_named_expressions=True).dfs_postorder_stack(
                            cc.upper) >= ExpressionReplacementVisitor(
                                substitute=variableSubMap,
                                remove_named_expressions=
                                  True).dfs_postorder_stack(cc.body)
                                )
        cc.deactivate()

    #paramData to varData constraint list
    b.paramConst = ConstraintList()
    for ii in paramDataList:
        jj=variableSubMap[id(ii)]
        b.paramConst.add(ii==jj)

    
    #Create the ipopt_sens (aka sIPOPT) solver plugin using the ASL interface
    opt = SolverFactory('ipopt_sens', solver_io='nl')

    if not opt.available(False):
        raise ImportError('ipopt_sens is not available')
    
    #Declare Suffixes
    m.sens_state_0 = Suffix(direction=Suffix.EXPORT)
    m.sens_state_1 = Suffix(direction=Suffix.EXPORT)
    m.sens_state_value_1 = Suffix(direction=Suffix.EXPORT)
    m.sens_init_constr = Suffix(direction=Suffix.EXPORT)
    
    m.sens_sol_state_1 = Suffix(direction=Suffix.IMPORT)
    m.sens_sol_state_1_z_L = Suffix(direction=Suffix.IMPORT)
    m.sens_sol_state_1_z_U = Suffix(direction=Suffix.IMPORT)

    #set sIPOPT data
    opt.options['run_sens'] = 'yes'
    
    # for reasons that are not entirely clear, 
    #     ipopt_sens requires the indices to start at 1
    kk=1
    for ii in paramDataList:
        m.sens_state_0[variableSubMap[id(ii)]] = kk
        m.sens_state_1[variableSubMap[id(ii)]] = kk
        m.sens_state_value_1[variableSubMap[id(ii)]] = \
                                                   value(perturbSubMap[id(ii)])
        m.sens_init_constr[b.paramConst[kk]] = kk
        kk += 1    
    
    
    #Send the model to the ipopt_sens and collect the solution
    results = opt.solve(m, keepfiles=keepfiles, tee=streamSoln)

    return m
예제 #17
0
파일: mip_solve.py 프로젝트: pazochoa/pyomo
def solve_linear_GDP(linear_GDP_model, solve_data, config):
    m = linear_GDP_model
    GDPopt = m.GDPopt_utils
    # Transform disjunctions
    TransformationFactory('gdp.bigm').apply_to(m)

    preprocessing_transformations = [
        # Propagate variable bounds
        'contrib.propagate_eq_var_bounds',
        # Detect fixed variables
        'contrib.detect_fixed_vars',
        # Propagate fixed variables
        'contrib.propagate_fixed_vars',
        # Remove zero terms in linear expressions
        'contrib.remove_zero_terms',
        # Remove terms in equal to zero summations
        'contrib.propagate_zero_sum',
        # Transform bound constraints
        'contrib.constraints_to_var_bounds',
        # Detect fixed variables
        'contrib.detect_fixed_vars',
        # Remove terms in equal to zero summations
        'contrib.propagate_zero_sum',
        # Remove trivial constraints
        'contrib.deactivate_trivial_constraints'
    ]
    for xfrm in preprocessing_transformations:
        TransformationFactory(xfrm).apply_to(m)

    # Deactivate extraneous IMPORT/EXPORT suffixes
    getattr(m, 'ipopt_zL_out', _DoNothing()).deactivate()
    getattr(m, 'ipopt_zU_out', _DoNothing()).deactivate()

    # Load solutions is false because otherwise an annoying error message
    # appears for infeasible models.
    mip_solver = SolverFactory(config.mip)
    if not mip_solver.available():
        raise RuntimeError("MIP solver %s is not available." % config.mip)
    results = mip_solver.solve(m, load_solutions=False, **config.mip_options)
    terminate_cond = results.solver.termination_condition
    if terminate_cond is tc.infeasibleOrUnbounded:
        # Linear solvers will sometimes tell me that it's infeasible or
        # unbounded during presolve, but fails to distinguish. We need to
        # resolve with a solver option flag on.
        tmp_options = deepcopy(config.mip_options)
        # TODO This solver option is specific to Gurobi.
        tmp_options['DualReductions'] = 0
        results = mip_solver.solve(m, load_solutions=False, **tmp_options)
        terminate_cond = results.solver.termination_condition

    if terminate_cond is tc.optimal:
        m.solutions.load_from(results)
        return True, list(v.value for v in GDPopt.working_var_list)
    elif terminate_cond is tc.infeasible:
        config.logger.info(
            'Linear GDP is infeasible. '
            'Problem may have no more feasible discrete configurations.')
        return False
    elif terminate_cond is tc.maxTimeLimit:
        # TODO check that status is actually ok and everything is feasible
        config.logger.info(
            'Unable to optimize linear GDP problem within time limit. '
            'Using current solver feasible solution.')
        results.solver.status = SolverStatus.ok
        m.solutions.load_from(results)
        return True, list(v.value for v in GDPopt.working_var_list)
    elif (terminate_cond is tc.other
          and results.solution.status is SolutionStatus.feasible):
        # load the solution and suppress the warning message by setting
        # solver status to ok.
        config.logger.info('Linear GDP solver reported feasible solution, '
                           'but not guaranteed to be optimal.')
        results.solver.status = SolverStatus.ok
        m.solutions.load_from(results)
        return True, list(v.value for v in GDPopt.working_var_list)
    else:
        raise ValueError('GDPopt unable to handle linear GDP '
                         'termination condition '
                         'of %s. Solver message: %s' %
                         (terminate_cond, results.solver.message))
예제 #18
0
파일: sens.py 프로젝트: jmorgan29/idaes-pse
def get_dfds_dcds(model, theta_names, tee=False, solver_options=None):
    """This function calculates gradient vector of the objective function
       and constraints with respect to the variables in theta_names.

    e.g) min f:  p1*x1+ p2*(x2^2) + p1*p2
         s.t  c1: x1 + x2 = p1
              c2: x2 + x3 = p2
              0 <= x1, x2, x3 <= 10
              p1 = 10
              p2 = 5
    - Variables = (x1, x2, x3, p1, p2)
    - Fix p1 and p2 with estimated values

    The following terms are used to define the output dimensions:
    Ncon   = number of constraints
    Nvar   = number of variables (Nx + Ntheta)
    Nx     = the numer of decision (primal) variables
    Ntheta = number of uncertain parameters.

    Parameters
    ----------
    model: Pyomo ConcreteModel
        model should includes an objective function
    theta_names: list of strings
        List of Var names
    tee: bool, optional
        Indicates that ef solver output should be teed
    solver_options: dict, optional
        Provides options to the solver (also the name of an attribute)

    Returns
    -------
    gradient_f: numpy.ndarray
        Length Nvar array. A gradient vector of the objective function
        with respect to the (decision variables, parameters)
        at the optimal solution
    gradient_c: scipy.sparse.csr.csr_matrix
        Ncon by Nvar size sparse matrix. A Jacobian matrix of the constraints
        with respect to the (decision variables, parameters) at the optimal
        solution. Each row contains [column number, row number, and value],
        colum order follows variable order in col and index starts from 1.
        Note that it follows k_aug. If no constraint exists, return []
    col: list
        Size Nvar. list of variable names
    row: list
        Size Ncon+1. List of constraints and objective function names
        The final element is the objective function name.
    line_dic: dict
        column numbers of the theta_names in the model. Index starts from 1

    Raises
    ------
    RuntimeError
        When ipopt or kaug or dotsens is not available
    Exception
        When ipopt fails
    """
    #Create the solver plugin using the ASL interface
    ipopt = SolverFactory('ipopt', solver_io='nl')
    if solver_options is not None:
        ipopt.options = solver_options
    kaug = SolverFactory('k_aug', solver_io='nl')
    dotsens = SolverFactory('dot_sens', solver_io='nl')
    if not ipopt.available(False):
        raise RuntimeError('ipopt is not available')
    if not kaug.available(False):
        raise RuntimeError('k_aug is not available')
    if not dotsens.available(False):
        raise RuntimeError('dotsens is not available')

    # Declare Suffixes
    _add_sensitivity_suffixes(model)

    # K_AUG SUFFIXES
    model.dof_v = Suffix(direction=Suffix.EXPORT)  #: SUFFIX FOR K_AUG
    model.rh_name = Suffix(
        direction=Suffix.IMPORT)  #: SUFFIX FOR K_AUG AS WELL
    kaug.options["print_kkt"] = ""
    results = ipopt.solve(model, tee=tee)

    # Raise Exception if ipopt fails
    if (results.solver.status == SolverStatus.warning):
        raise Exception(results.solver.Message)

    for o in model.component_objects(Objective, active=True):
        f_mean = value(o)
    model.ipopt_zL_in.update(model.ipopt_zL_out)
    model.ipopt_zU_in.update(model.ipopt_zU_out)
    #: run k_aug
    kaug.solve(model, tee=tee)  #: always call k_aug AFTER ipopt.
    model.write('col_row.nl',
                format='nl',
                io_options={'symbolic_solver_labels': True})
    # get the column numbers of theta
    line_dic = {}
    try:
        for v in theta_names:
            line_dic[v] = line_num('col_row.col', v)
        # load gradient of the objective function
        gradient_f = np.loadtxt("./GJH/gradient_f_print.txt")
        with open("col_row.col", "r") as myfile:
            col = myfile.read().splitlines()
        col = [
            i for i in col
            if SensitivityInterface.get_default_block_name() not in i
        ]
        with open("col_row.row", "r") as myfile:
            row = myfile.read().splitlines()
    except Exception as e:
        print('File not found.')
        raise e
    # load gradient of all constraints (sparse)
    # If no constraint exists, return []
    num_constraints = len(
        list(
            model.component_data_objects(Constraint,
                                         active=True,
                                         descend_into=True)))
    if num_constraints > 0:
        try:
            # load text file from kaug
            gradient_c = np.loadtxt("./GJH/A_print.txt")
            # This is a sparse matrix
            # gradient_c[:,0] are column index
            # gradient_c[:,1] are data index
            # gradient_c[:,1] are the matrix values
        except Exception as e:
            print('kaug file ./GJH/A_print.txt not found.')

        # Subtract 1 from row and column indices to convert from
        # start at 1 (kaug) to start at 0 (numpy)
        row_idx = gradient_c[:, 1] - 1
        col_idx = gradient_c[:, 0] - 1
        data = gradient_c[:, 2]
        gradient_c = sparse.csr_matrix((data, (row_idx, col_idx)),
                                       shape=(len(row) - 1, len(col)))
    else:
        gradient_c = np.array([])
    # remove all generated files

    shutil.move("col_row.nl", "./GJH/")
    shutil.move("col_row.col", "./GJH/")
    shutil.move("col_row.row", "./GJH/")
    shutil.rmtree('GJH', ignore_errors=True)

    return gradient_f, gradient_c, col, row, line_dic
예제 #19
0
파일: nlp_solve.py 프로젝트: Pyomo/pyomo
def solve_MINLP(model, solve_data, config):
    """Solve the MINLP subproblem."""
    config.logger.info(
        "Solving MINLP subproblem for fixed logical realizations."
    )

    GDPopt = model.GDPopt_utils

    if config.subproblem_presolve:
        preprocess_subproblem(model, config)

    initialize_subproblem(model, solve_data)

    # Callback immediately before solving NLP subproblem
    config.call_before_subproblem_solve(model, solve_data)

    minlp_solver = SolverFactory(config.minlp_solver)
    if not minlp_solver.available():
        raise RuntimeError("MINLP solver %s is not available." %
                           config.minlp_solver)
    with SuppressInfeasibleWarning():
        results = minlp_solver.solve(model, **config.minlp_solver_args)

    subprob_result = SubproblemResult()
    subprob_result.feasible = True
    subprob_result.var_values = list(v.value for v in GDPopt.variable_list)
    subprob_result.pyomo_results = results
    subprob_result.dual_values = list(
        model.dual.get(c, None)
        for c in GDPopt.constraint_list)

    subprob_terminate_cond = results.solver.termination_condition
    if (subprob_terminate_cond is tc.optimal or
            subprob_terminate_cond is tc.locallyOptimal or
            subprob_terminate_cond is tc.feasible):
        pass
    elif subprob_terminate_cond is tc.infeasible:
        config.logger.info('MINLP subproblem was infeasible.')
        subprob_result.feasible = False
    elif subprob_terminate_cond is tc.maxIterations:
        # TODO try something else? Reinitialize with different initial
        # value?
        config.logger.info(
            'MINLP subproblem failed to converge within iteration limit.')
        if is_feasible(model, config):
            config.logger.info(
                'MINLP solution is still feasible. '
                'Using potentially suboptimal feasible solution.')
        else:
            subprob_result.feasible = False
    elif subprob_terminate_cond is tc.intermediateNonInteger:
        config.logger.info(
            "MINLP solver could not find feasible integer solution: %s" % results.solver.message)
        subprob_result.feasible = False
    else:
        raise ValueError(
            'GDPopt unable to handle MINLP subproblem termination '
            'condition of %s. Results: %s'
            % (subprob_terminate_cond, results))

    # Call the subproblem post-solve callback
    config.call_after_subproblem_solve(model, solve_data)

    # if feasible, call the subproblem post-feasible callback
    if subprob_result.feasible:
        config.call_after_subproblem_feasible(model, solve_data)

    return subprob_result