Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preliminary implementation of outer approximation and partial surrogate cuts in Pyomo #166

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
70b597e
Making the AlphaNumericTextLabeler name more descriptive
jsiirola May 25, 2017
68ec8b9
More comprehensive character substitutions for text labels
jsiirola May 25, 2017
a55bc3e
Switch to using guess_format instead of a hard-coded if tree.
jsiirola May 25, 2017
2a0c5c6
Allow consumers to override ComponentData.to_string()
jsiirola May 25, 2017
2dc9599
Initial implementation of a GAMS model writer.
jsiirola May 25, 2017
3054e31
Fixes to format detection logic changes in a55bc3e
jsiirola May 26, 2017
e919cc6
Merge pull request #154 from Pyomo/IDAES-premerge
jsiirola Jun 6, 2017
dd37f90
Merge remote-tracking branch 'upstream/master' into dev
qtothec Jun 7, 2017
be2d8f1
Merge remote-tracking branch 'upstream/master' into dev
qtothec Jun 9, 2017
db7b142
Merge remote-tracking branch 'upstream/gams-writer' into dev
qtothec Jun 9, 2017
75c9f0c
Initial work on MINDT solver
qtothec Jun 12, 2017
5ef962b
Minimum viable implementation of MINDT solver
qtothec Jun 12, 2017
939cd36
Merge remote-tracking branch 'upstream/master' into dev
qtothec Jun 12, 2017
be41459
minor documentation
qtothec Jun 12, 2017
da9cbd5
Merge branch 'mindt' into dev
qtothec Jun 12, 2017
2694ce2
Bugfix to add penalty terms to objective for master problem
qtothec Jun 12, 2017
7070daa
Merge branch 'mindt' into dev
qtothec Jun 12, 2017
2cc59b8
Documentation and code organization. Also added ability to pass optio…
qtothec Jun 13, 2017
6588810
organizing code. adding in hooks for basic callbacks. implement secon…
qtothec Jun 14, 2017
047b4f1
Cosmetic rearrangements
qtothec Jun 14, 2017
07095eb
Fix global name not defined in _get_linear_collector
qtothec Jun 15, 2017
f32aa6a
Merge branch 'canonical_fix' into dev
qtothec Jun 15, 2017
ebcc17a
Add in handling for NumericConstant in _get_linear_collector
qtothec Jun 15, 2017
779011a
Merge branch 'canonical_fix_numconst' into dev
qtothec Jun 15, 2017
90ae046
Preliminary implementation of PSC. Need to test it.
qtothec Jun 15, 2017
cea8d80
Add handling to detect miscategorization of infeasible problems as un…
qtothec Jun 16, 2017
9e2c25d
Merge branch 'gurobi_unbounded_fix' into dev
qtothec Jun 16, 2017
824b11d
Bugfix to PSC and DoNothing
qtothec Jun 16, 2017
261fddf
small documentation changes
qtothec Jun 16, 2017
8fafcce
Preliminary implementation of GBD, untested
qtothec Jun 18, 2017
1a05196
Revert "Merge branch 'gurobi_unbounded_fix' into dev"
qtothec Jun 18, 2017
c3f6fad
Merge branch 'inf_or_unb_enum' into dev
qtothec Jun 20, 2017
0c5eeee
Preliminary implementation of GBD (questionable), bunch of documentat…
qtothec Jun 20, 2017
42e5e5d
Preliminary implementation of hybrid PSC. Some small bugfixes.
qtothec Jun 21, 2017
ddbca19
Change number of iterations of no lower bound progress before switch …
qtothec Jun 22, 2017
2e9129c
Small bugfix on initialization method. Adding tests.
qtothec Jun 23, 2017
e0cb4ff
Merge remote-tracking branch 'upstream/master' into mindt
qtothec Aug 1, 2017
3b68f6d
Bugfix because John changed how the pyomo.environ import works
qtothec Aug 1, 2017
14de864
Update author field
qtothec Aug 21, 2017
90dd62c
Renaming mindt to mindtpy
qtothec Sep 14, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion pyomo/core/base/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,8 @@ class ComponentData(_ComponentBase):
__pickle_slots__ = ('_component',)
__slots__ = __pickle_slots__ + ('__weakref__',)

labeler = []

def __init__(self, owner):
#
# ComponentData objects are typically *private* objects for
Expand Down Expand Up @@ -685,7 +687,10 @@ def to_string(self, ostream=None, verbose=None, precedence=0):
"""Write the component name and index to a buffer"""
if ostream is None:
ostream = sys.stdout
ostream.write(self.__str__())
if not ComponentData.labeler:
ostream.write(self.__str__())
else:
ostream.write(ComponentData.labeler[-1](self))

def getname(self, fully_qualified=False, name_buffer=None):
"""Return a string with the component name and index"""
Expand Down
66 changes: 51 additions & 15 deletions pyomo/core/base/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
# ___________________________________________________________________________

__all__ = ['CounterLabeler', 'NumericLabeler', 'CNameLabeler', 'TextLabeler',
'AlphaNumTextLabeler','NameLabeler', 'CuidLabeler']
'AlphaNumericTextLabeler','NameLabeler', 'CuidLabeler']

import six
if six.PY3:
_string = str
_translate = str.translate
else:
import string as _string
import string
_translate = string.translate

from pyomo.core.base.component import ComponentUID

# This module provides some basic functionality for generating labels
Expand All @@ -24,30 +26,64 @@
# optimization input file formats, e.g., CPLEX LP files. The purpose of
# this module is to provide a simple remap function, that will satisfy
# broadly problematic symbols. if solver-specific remaps are required,
# they should be handled either in the corresponding solver plugin.

# NOTE: Simple single-character substitutions should be handled by adding
# to the translation table constructed below - first argument is the
# "from" characters, second argument is the "to" characters.
cpxlp_translation_table = _string.maketrans("[]{} -#$%&*+.,/;<=>?@^!~':",
"()()______________________")
# they should be handled in the corresponding solver plugin.

class _CharMapper(object):
def __init__(self, preserve, translate, other):
"""
Arguments::
preserve: a string of characters to preserve
translate: a dict or key/value list of characters to translate
other: the character to return for all characters not in
preserve or translate
"""
self.table = dict(
(k if isinstance(k, int) else ord(k), v)
for k,v in six.iteritems(dict(translate)) )
for c in preserve:
_c = ord(c)
if _c in self.table and self.table[_c] != c:
raise RuntimeError("Duplicate character '%s' appears in both "
"translate table and preserve list" % (c,))
self.table[_c] = c
self.other = other

def __getitem__(self, c):
# Most of the time c should be known. For the rare cases we
# encounter a new character, remember it by adding a new entry
# into the translation table and return the default character
try:
return self.table[c]
except:
self.table[c] = self.other
return self.other

def make_table(self):
return ''.join(self[i] for i in range(256))

_alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ'
_digit = '1234567890'
_cpxlp_translation_table = _CharMapper( preserve=_alpha+_digit+'()_',
translate = zip('[]{}', '()()'),
other='_' ).make_table()
def cpxlp_label_from_name(name):

if name is None:
raise RuntimeError("Illegal name=None supplied to "
"cpxlp_label_from_name function")

return _string.translate(name, cpxlp_translation_table)
return _translate(name, _cpxlp_translation_table)

alphanum_translation_table = _string.maketrans("()[]{} -#$%&*+.,/;<=>?@^!~':",
"____________________________")
_alphanum_translation_table = _CharMapper( preserve=_alpha+_digit+'_',
translate = {},
other='_' ).make_table()
def alphanum_label_from_name(name):

if name is None:
raise RuntimeError("Illegal name=None supplied to "
"alphanum_label_from_name function")

return _string.translate(name, alphanum_translation_table)
return _translate(name, _alphanum_translation_table)

class CuidLabeler(object):

Expand Down Expand Up @@ -95,7 +131,7 @@ def __init__(self):
def __call__(self, obj):
return cpxlp_label_from_name(obj.getname(True, self.name_buffer))

class AlphaNumTextLabeler(object):
class AlphaNumericTextLabeler(object):
def __init__(self):
self.name_buffer = {}

Expand Down
14 changes: 9 additions & 5 deletions pyomo/opt/base/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
# pyomo.opt.colin.OptProblem (this can wrap a COLIN shell
# command, or provide a runtime optimization problem)
# bar - A Baron input file
# gams - A GAMS input file
#
ProblemFormat = Enum('colin', 'pyomo', 'cpxlp', 'nl', 'mps', 'mod', 'lpxlp', 'osil', 'colin_optproblem', 'FuncDesigner','bar')
ProblemFormat = Enum('colin', 'pyomo', 'cpxlp', 'nl', 'mps', 'mod', 'lpxlp', 'osil', 'colin_optproblem', 'FuncDesigner','bar','gams')

#
# osrl - osrl XML file defined by the COIN-OR OS project: Result
Expand All @@ -52,6 +53,9 @@ def guess_format(filename):
formats['mod']=ProblemFormat.mod
formats['lp']=ProblemFormat.cpxlp
formats['osil']=ProblemFormat.osil
formats['gms']=ProblemFormat.gams
formats['gams']=ProblemFormat.gams

formats['sol']=ResultsFormat.sol
formats['osrl']=ResultsFormat.osrl
formats['soln']=ResultsFormat.soln
Expand All @@ -60,7 +64,7 @@ def guess_format(filename):
formats['jsn']=ResultsFormat.json
formats['json']=ResultsFormat.json
formats['results']=ResultsFormat.yaml
for fmt in formats:
if filename.endswith('.'+fmt):
return formats[fmt]
return None
if filename:
return formats.get(filename.split('.')[-1].strip(), None)
else:
return None
12 changes: 8 additions & 4 deletions pyomo/repn/canonical_repn.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#
# Pyomo: Python Optimization Modeling Objects
# Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and
# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
# Under the terms of Contract DE-NA0003525 with National Technology and
# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
Expand All @@ -26,14 +26,17 @@
SimpleExpression,
Expression)
from pyomo.core.base.objective import (_GeneralObjectiveData,
SimpleObjective)
SimpleObjective,
_ObjectiveData)
from pyomo.core.base.connector import (_ConnectorData,
SimpleConnector,
Connector)
from pyomo.core.base.var import (SimpleVar,
Var,
_GeneralVarData,
_VarData)
from pyomo.core.kernel.component_objective import IObjective
from pyomo.core.base.numvalue import NumericConstant

from pyomo.core.base import expr_pyomo4
from pyomo.core.base import expr_coopr3
Expand Down Expand Up @@ -751,6 +754,7 @@ def _collect_identity(exp, idMap, multiplier, coef, varmap, compute_values):
param.SimpleParam : _collect_linear_const,
param.Param : _collect_linear_const,
parameter : _collect_linear_const,
NumericConstant : _collect_linear_const,
_GeneralVarData : _collect_linear_var,
SimpleVar : _collect_linear_var,
Var : _collect_linear_var,
Expand All @@ -773,7 +777,7 @@ def _get_linear_collector(exp, idMap, multiplier,
if isinstance(exp, (_VarData, IVariable)):
_collect_linear_var(exp, idMap, multiplier,
coef, varmap, compute_values)
elif isinstance(exp, (param._ParamData, IParameter)):
elif isinstance(exp, (param._ParamData, IParameter, NumericConstant)):
_collect_linear_const(exp, idMap, multiplier,
coef, varmap, compute_values)
elif isinstance(exp, (_ExpressionData, IIdentityExpression)):
Expand Down
1 change: 1 addition & 0 deletions pyomo/repn/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ def load():
import pyomo.repn.plugins.ampl
import pyomo.repn.plugins.baron_writer
import pyomo.repn.plugins.mps
import pyomo.repn.plugins.gams_writer

Loading