forked from Pyomo/pyomo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
159 changed files
with
2,076 additions
and
1,915 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
doc/OnlineDocs/contributed_packages/pynumero/backward_compatibility.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Backward Compatibility | ||
====================== | ||
|
||
While PyNumero is a third-party contribution to Pyomo, we intend to maintain | ||
the stability of its core functionality. The core functionality of PyNumero | ||
consists of: | ||
|
||
1. The ``NLP`` API and ``PyomoNLP`` implementation of this API | ||
2. HSL and MUMPS linear solver interfaces | ||
3. ``BlockVector`` and ``BlockMatrix`` classes | ||
4. CyIpopt and SciPy solver interfaces | ||
|
||
Other parts of PyNumero, such as ``ExternalGreyBoxBlock`` and | ||
``ImplicitFunctionSolver``, are experimental and subject to change without notice. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
pyomo.common.enums | ||
================== | ||
|
||
.. automodule:: pyomo.common.enums | ||
:members: | ||
:member-order: bysource |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,7 +55,7 @@ Model unknown | |
None | ||
value | ||
x[Q] + 2*x[R] | ||
1 | ||
minimize | ||
6.5 | ||
Model unknown | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
# ___________________________________________________________________________ | ||
# | ||
# Pyomo: Python Optimization Modeling Objects | ||
# Copyright (c) 2008-2024 | ||
# National Technology and Engineering Solutions of Sandia, LLC | ||
# Under the terms of Contract DE-NA0003525 with National Technology and | ||
# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain | ||
# rights in this software. | ||
# This software is distributed under the 3-clause BSD License. | ||
# ___________________________________________________________________________ | ||
|
||
"""This module provides standard :py:class:`enum.Enum` definitions used in | ||
Pyomo, along with additional utilities for working with custom Enums | ||
Utilities: | ||
.. autosummary:: | ||
ExtendedEnumType | ||
Standard Enums: | ||
.. autosummary:: | ||
ObjectiveSense | ||
""" | ||
|
||
import enum | ||
import itertools | ||
import sys | ||
|
||
if sys.version_info[:2] < (3, 11): | ||
_EnumType = enum.EnumMeta | ||
else: | ||
_EnumType = enum.EnumType | ||
|
||
|
||
class ExtendedEnumType(_EnumType): | ||
"""Metaclass for creating an :py:class:`enum.Enum` that extends another Enum | ||
In general, :py:class:`enum.Enum` classes are not extensible: that is, | ||
they are frozen when defined and cannot be the base class of another | ||
Enum. This Metaclass provides a workaround for creating a new Enum | ||
that extends an existing enum. Members in the base Enum are all | ||
present as members on the extended enum. | ||
Example | ||
------- | ||
.. testcode:: | ||
:hide: | ||
import enum | ||
from pyomo.common.enums import ExtendedEnumType | ||
.. testcode:: | ||
class ObjectiveSense(enum.IntEnum): | ||
minimize = 1 | ||
maximize = -1 | ||
class ProblemSense(enum.IntEnum, metaclass=ExtendedEnumType): | ||
__base_enum__ = ObjectiveSense | ||
unknown = 0 | ||
.. doctest:: | ||
>>> list(ProblemSense) | ||
[<ProblemSense.unknown: 0>, <ObjectiveSense.minimize: 1>, <ObjectiveSense.maximize: -1>] | ||
>>> ProblemSense.unknown | ||
<ProblemSense.unknown: 0> | ||
>>> ProblemSense.maximize | ||
<ObjectiveSense.maximize: -1> | ||
>>> ProblemSense(0) | ||
<ProblemSense.unknown: 0> | ||
>>> ProblemSense(1) | ||
<ObjectiveSense.minimize: 1> | ||
>>> ProblemSense('unknown') | ||
<ProblemSense.unknown: 0> | ||
>>> ProblemSense('maximize') | ||
<ObjectiveSense.maximize: -1> | ||
>>> hasattr(ProblemSense, 'minimize') | ||
True | ||
>>> ProblemSense.minimize is ObjectiveSense.minimize | ||
True | ||
>>> ProblemSense.minimize in ProblemSense | ||
True | ||
""" | ||
|
||
def __getattr__(cls, attr): | ||
try: | ||
return getattr(cls.__base_enum__, attr) | ||
except: | ||
return super().__getattr__(attr) | ||
|
||
def __iter__(cls): | ||
# The members of this Enum are the base enum members joined with | ||
# the local members | ||
return itertools.chain(super().__iter__(), cls.__base_enum__.__iter__()) | ||
|
||
def __contains__(cls, member): | ||
# This enum "contains" both its local members and the members in | ||
# the __base_enum__ (necessary for good auto-enum[sphinx] docs) | ||
return super().__contains__(member) or member in cls.__base_enum__ | ||
|
||
def __instancecheck__(cls, instance): | ||
if cls.__subclasscheck__(type(instance)): | ||
return True | ||
# Also pretend that members of the extended enum are subclasses | ||
# of the __base_enum__. This is needed to circumvent error | ||
# checking in enum.__new__ (e.g., for `ProblemSense('minimize')`) | ||
return cls.__base_enum__.__subclasscheck__(type(instance)) | ||
|
||
def _missing_(cls, value): | ||
# Support attribute lookup by value or name | ||
for attr in ('value', 'name'): | ||
for member in cls: | ||
if getattr(member, attr) == value: | ||
return member | ||
return None | ||
|
||
def __new__(metacls, cls, bases, classdict, **kwds): | ||
# Support lookup by name - but only if the new Enum doesn't | ||
# specify its own implementation of _missing_ | ||
if '_missing_' not in classdict: | ||
classdict['_missing_'] = classmethod(ExtendedEnumType._missing_) | ||
return super().__new__(metacls, cls, bases, classdict, **kwds) | ||
|
||
|
||
class ObjectiveSense(enum.IntEnum): | ||
"""Flag indicating if an objective is minimizing (1) or maximizing (-1). | ||
While the numeric values are arbitrary, there are parts of Pyomo | ||
that rely on this particular choice of value. These values are also | ||
consistent with some solvers (notably Gurobi). | ||
""" | ||
|
||
minimize = 1 | ||
maximize = -1 | ||
|
||
# Overloading __str__ is needed to match the behavior of the old | ||
# pyutilib.enum class (removed June 2020). There are spots in the | ||
# code base that expect the string representation for items in the | ||
# enum to not include the class name. New uses of enum shouldn't | ||
# need to do this. | ||
def __str__(self): | ||
return self.name | ||
|
||
@classmethod | ||
def _missing_(cls, value): | ||
for member in cls: | ||
if member.name == value: | ||
return member | ||
return None | ||
|
||
|
||
minimize = ObjectiveSense.minimize | ||
maximize = ObjectiveSense.maximize |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# ___________________________________________________________________________ | ||
# | ||
# Pyomo: Python Optimization Modeling Objects | ||
# Copyright (c) 2008-2024 | ||
# National Technology and Engineering Solutions of Sandia, LLC | ||
# Under the terms of Contract DE-NA0003525 with National Technology and | ||
# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain | ||
# rights in this software. | ||
# This software is distributed under the 3-clause BSD License. | ||
# ___________________________________________________________________________ | ||
|
||
import enum | ||
|
||
import pyomo.common.unittest as unittest | ||
|
||
from pyomo.common.enums import ExtendedEnumType, ObjectiveSense | ||
|
||
|
||
class ProblemSense(enum.IntEnum, metaclass=ExtendedEnumType): | ||
__base_enum__ = ObjectiveSense | ||
|
||
unknown = 0 | ||
|
||
|
||
class TestExtendedEnumType(unittest.TestCase): | ||
def test_members(self): | ||
self.assertEqual( | ||
list(ProblemSense), | ||
[ProblemSense.unknown, ObjectiveSense.minimize, ObjectiveSense.maximize], | ||
) | ||
|
||
def test_isinstance(self): | ||
self.assertIsInstance(ProblemSense.unknown, ProblemSense) | ||
self.assertIsInstance(ProblemSense.minimize, ProblemSense) | ||
self.assertIsInstance(ProblemSense.maximize, ProblemSense) | ||
|
||
self.assertTrue(ProblemSense.__instancecheck__(ProblemSense.unknown)) | ||
self.assertTrue(ProblemSense.__instancecheck__(ProblemSense.minimize)) | ||
self.assertTrue(ProblemSense.__instancecheck__(ProblemSense.maximize)) | ||
|
||
def test_getattr(self): | ||
self.assertIs(ProblemSense.unknown, ProblemSense.unknown) | ||
self.assertIs(ProblemSense.minimize, ObjectiveSense.minimize) | ||
self.assertIs(ProblemSense.maximize, ObjectiveSense.maximize) | ||
|
||
def test_hasattr(self): | ||
self.assertTrue(hasattr(ProblemSense, 'unknown')) | ||
self.assertTrue(hasattr(ProblemSense, 'minimize')) | ||
self.assertTrue(hasattr(ProblemSense, 'maximize')) | ||
|
||
def test_call(self): | ||
self.assertIs(ProblemSense(0), ProblemSense.unknown) | ||
self.assertIs(ProblemSense(1), ObjectiveSense.minimize) | ||
self.assertIs(ProblemSense(-1), ObjectiveSense.maximize) | ||
|
||
self.assertIs(ProblemSense('unknown'), ProblemSense.unknown) | ||
self.assertIs(ProblemSense('minimize'), ObjectiveSense.minimize) | ||
self.assertIs(ProblemSense('maximize'), ObjectiveSense.maximize) | ||
|
||
with self.assertRaisesRegex(ValueError, "'foo' is not a valid ProblemSense"): | ||
ProblemSense('foo') | ||
with self.assertRaisesRegex(ValueError, "2 is not a valid ProblemSense"): | ||
ProblemSense(2) | ||
|
||
def test_contains(self): | ||
self.assertIn(ProblemSense.unknown, ProblemSense) | ||
self.assertIn(ProblemSense.minimize, ProblemSense) | ||
self.assertIn(ProblemSense.maximize, ProblemSense) | ||
|
||
self.assertNotIn(ProblemSense.unknown, ObjectiveSense) | ||
self.assertIn(ProblemSense.minimize, ObjectiveSense) | ||
self.assertIn(ProblemSense.maximize, ObjectiveSense) | ||
|
||
|
||
class TestObjectiveSense(unittest.TestCase): | ||
def test_members(self): | ||
self.assertEqual( | ||
list(ObjectiveSense), [ObjectiveSense.minimize, ObjectiveSense.maximize] | ||
) | ||
|
||
def test_hasattr(self): | ||
self.assertTrue(hasattr(ProblemSense, 'minimize')) | ||
self.assertTrue(hasattr(ProblemSense, 'maximize')) | ||
|
||
def test_call(self): | ||
self.assertIs(ObjectiveSense(1), ObjectiveSense.minimize) | ||
self.assertIs(ObjectiveSense(-1), ObjectiveSense.maximize) | ||
|
||
self.assertIs(ObjectiveSense('minimize'), ObjectiveSense.minimize) | ||
self.assertIs(ObjectiveSense('maximize'), ObjectiveSense.maximize) | ||
|
||
with self.assertRaisesRegex(ValueError, "'foo' is not a valid ObjectiveSense"): | ||
ObjectiveSense('foo') | ||
|
||
def test_str(self): | ||
self.assertEqual(str(ObjectiveSense.minimize), 'minimize') | ||
self.assertEqual(str(ObjectiveSense.maximize), 'maximize') |
Oops, something went wrong.