Skip to content

Initialization Module#3912

Open
michaelbynum wants to merge 62 commits into
Pyomo:mainfrom
michaelbynum:initialization
Open

Initialization Module#3912
michaelbynum wants to merge 62 commits into
Pyomo:mainfrom
michaelbynum:initialization

Conversation

@michaelbynum
Copy link
Copy Markdown
Contributor

@michaelbynum michaelbynum commented Apr 15, 2026

Fixes #3878

Summary/Motivation:

This PR adds a module to devel called initialization. The goal of the module is to provide methods to help initialize nonconvex nonlinear programming problems.

Changes proposed in this PR:

  • Add initialization module
  • Add an initialization method that uses a global optimization solver to find a feasible solution
  • Add an initialization method that builds a linear programming approximation using linear least squares
  • Add an initialization method that builds a piecewise linear approximation and iteratively refines it

Legal Acknowledgement

By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the BSD license.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 88.91129% with 55 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.10%. Comparing base (92951cb) to head (2d4594a).

Files with missing lines Patch % Lines
pyomo/devel/initialization/pwl_init.py 88.67% 24 Missing ⚠️
pyomo/devel/initialization/initialize.py 72.13% 17 Missing ⚠️
...omo/devel/initialization/bounds/bound_variables.py 73.33% 4 Missing ⚠️
...evel/initialization/examples/init_polynomial_ex.py 84.21% 3 Missing ⚠️
pyomo/devel/initialization/global_init.py 86.36% 3 Missing ⚠️
pyomo/devel/initialization/lp_approx_init.py 97.60% 3 Missing ⚠️
pyomo/devel/initialization/utils.py 96.55% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3912      +/-   ##
==========================================
- Coverage   90.10%   90.10%   -0.01%     
==========================================
  Files         909      917       +8     
  Lines      108525   109014     +489     
==========================================
+ Hits        97787    98224     +437     
- Misses      10738    10790      +52     
Flag Coverage Δ
builders 29.06% <26.00%> (-0.02%) ⬇️
default 86.10% <85.88%> (?)
expensive 35.07% <26.00%> (?)
linux 87.62% <88.91%> (-1.98%) ⬇️
linux_other 87.62% <88.91%> (+<0.01%) ⬆️
oldsolvers 28.03% <26.00%> (-0.01%) ⬇️
osx 83.09% <88.91%> (+0.02%) ⬆️
win 85.38% <88.91%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@blnicho blnicho marked this pull request as draft April 30, 2026 12:57
@blnicho blnicho changed the title [Depends on #3821 and #3744] Initialization Module [Depends on #3744] Initialization Module May 15, 2026
@michaelbynum michaelbynum changed the title [Depends on #3744] Initialization Module Initialization Module May 19, 2026
@michaelbynum michaelbynum marked this pull request as ready for review May 19, 2026 19:05
@michaelbynum
Copy link
Copy Markdown
Contributor Author

See #3878 for the changes I had to make to contrib.piecewise.

@michaelbynum
Copy link
Copy Markdown
Contributor Author

Thanks for updating the imports, @blnicho!

Comment thread doc/OnlineDocs/conf.py
baron_available = bool(_opt.check_available_solvers('baron'))
glpk_available = bool(_opt.check_available_solvers('glpk'))
gurobipy_available = bool(_opt.check_available_solvers('gurobi_direct'))
scip_available = bool(_opt.check_available_solvers('scip_direct'))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this maybe be named pyscip_available or pyscipopt_available? I think scip_available implies the long-time-existing command line version, but it's actually the Python interface that we are looking for.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing copyright

opts = {'SolutionLimit': 1}
else:
raise NotImplementedError(
'Currently, the initialization module only works with new solver interface, so the global solvers are limited to ScipDirect, ScipPersistent, and GurobiDirectMINLP.'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'Currently, the initialization module only works with new solver interface, so the global solvers are limited to ScipDirect, ScipPersistent, and GurobiDirectMINLP.'
'Currently, the initialization module only works with new solver interfaces, so the global solvers are limited to ScipDirect, ScipPersistent, and GurobiDirectMINLP.'

# ____________________________________________________________________________________

from pyomo.core.base.block import BlockData
import pyomo.environ as pe
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Michael! pyo, not pe 😜

Comment on lines +10 to +66
from pyomo.core.base.block import BlockData
import pyomo.environ as pe
from pyomo.devel.initialization.bounds.bound_variables import (
bound_all_nonlinear_variables,
)
from pyomo.devel.initialization.utils import (
fix_vars_with_equal_bounds,
shallow_clone,
get_vars,
)
from pyomo.core.expr.visitor import identify_components
from pyomo.contrib.piecewise.piecewise_linear_expression import (
PiecewiseLinearExpression,
)
from pyomo.contrib.piecewise.piecewise_linear_function import PiecewiseLinearFunction
from pyomo.contrib.solver.common.results import SolutionStatus
from pyomo.common.collections import ComponentMap, ComponentSet
from typing import MutableMapping, Sequence, List
from pyomo.core.base.constraint import ConstraintData
from pyomo.core.expr.visitor import StreamBasedExpressionVisitor
from pyomo.common.numeric_types import native_numeric_types
from pyomo.core.expr.numvalue import NumericConstant
from pyomo.core.expr.numeric_expr import (
NegationExpression,
PowExpression,
ProductExpression,
MonomialTermExpression,
DivisionExpression,
SumExpression,
LinearExpression,
UnaryFunctionExpression,
NPV_NegationExpression,
NPV_PowExpression,
NPV_ProductExpression,
NPV_DivisionExpression,
NPV_SumExpression,
NPV_UnaryFunctionExpression,
)
from pyomo.core.expr.relational_expr import (
EqualityExpression,
InequalityExpression,
RangedExpression,
)
from pyomo.repn.util import ExitNodeDispatcher
from pyomo.core.base.var import ScalarVar, VarData
from pyomo.core.base.param import ScalarParam, ParamData
from pyomo.core.base.expression import ScalarExpression, ExpressionData
import math
from pyomo.contrib.solver.common.base import SolverBase
import logging
from pyomo.common.modeling import unique_component_name
from pyomo.devel.initialization.pwl_init import _minimize_infeasibility
from pyomo.contrib.fbbt.fbbt import fbbt
from pyomo.repn.linear import LinearRepnVisitor, LinearRepn
from pyomo.core.expr.visitor import identify_variables
from pyomo.common.dependencies import numpy as np
from pyomo.common.dependencies import attempt_import
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preferred import order (plus changed to pyo instead of pe).

Suggested change
from pyomo.core.base.block import BlockData
import pyomo.environ as pe
from pyomo.devel.initialization.bounds.bound_variables import (
bound_all_nonlinear_variables,
)
from pyomo.devel.initialization.utils import (
fix_vars_with_equal_bounds,
shallow_clone,
get_vars,
)
from pyomo.core.expr.visitor import identify_components
from pyomo.contrib.piecewise.piecewise_linear_expression import (
PiecewiseLinearExpression,
)
from pyomo.contrib.piecewise.piecewise_linear_function import PiecewiseLinearFunction
from pyomo.contrib.solver.common.results import SolutionStatus
from pyomo.common.collections import ComponentMap, ComponentSet
from typing import MutableMapping, Sequence, List
from pyomo.core.base.constraint import ConstraintData
from pyomo.core.expr.visitor import StreamBasedExpressionVisitor
from pyomo.common.numeric_types import native_numeric_types
from pyomo.core.expr.numvalue import NumericConstant
from pyomo.core.expr.numeric_expr import (
NegationExpression,
PowExpression,
ProductExpression,
MonomialTermExpression,
DivisionExpression,
SumExpression,
LinearExpression,
UnaryFunctionExpression,
NPV_NegationExpression,
NPV_PowExpression,
NPV_ProductExpression,
NPV_DivisionExpression,
NPV_SumExpression,
NPV_UnaryFunctionExpression,
)
from pyomo.core.expr.relational_expr import (
EqualityExpression,
InequalityExpression,
RangedExpression,
)
from pyomo.repn.util import ExitNodeDispatcher
from pyomo.core.base.var import ScalarVar, VarData
from pyomo.core.base.param import ScalarParam, ParamData
from pyomo.core.base.expression import ScalarExpression, ExpressionData
import math
from pyomo.contrib.solver.common.base import SolverBase
import logging
from pyomo.common.modeling import unique_component_name
from pyomo.devel.initialization.pwl_init import _minimize_infeasibility
from pyomo.contrib.fbbt.fbbt import fbbt
from pyomo.repn.linear import LinearRepnVisitor, LinearRepn
from pyomo.core.expr.visitor import identify_variables
from pyomo.common.dependencies import numpy as np
from pyomo.common.dependencies import attempt_import
import logging
import math
from typing import List, MutableMapping, Sequence
import pyomo.environ as pyo
from pyomo.common.collections import ComponentMap, ComponentSet
from pyomo.common.dependencies import attempt_import
from pyomo.common.dependencies import numpy as np
from pyomo.common.modeling import unique_component_name
from pyomo.common.numeric_types import native_numeric_types
from pyomo.contrib.fbbt.fbbt import fbbt
from pyomo.contrib.piecewise.piecewise_linear_expression import (
PiecewiseLinearExpression,
)
from pyomo.contrib.piecewise.piecewise_linear_function import PiecewiseLinearFunction
from pyomo.contrib.solver.common.base import SolverBase
from pyomo.contrib.solver.common.results import SolutionStatus
from pyomo.core.base.block import BlockData
from pyomo.core.base.constraint import ConstraintData
from pyomo.core.base.expression import ExpressionData, ScalarExpression
from pyomo.core.base.param import ParamData, ScalarParam
from pyomo.core.base.var import ScalarVar, VarData
from pyomo.core.expr.numvalue import NumericConstant
from pyomo.core.expr.numeric_expr import (
DivisionExpression,
LinearExpression,
MonomialTermExpression,
NegationExpression,
NPV_DivisionExpression,
NPV_NegationExpression,
NPV_PowExpression,
NPV_ProductExpression,
NPV_SumExpression,
NPV_UnaryFunctionExpression,
PowExpression,
ProductExpression,
SumExpression,
UnaryFunctionExpression,
)
from pyomo.core.expr.relational_expr import (
EqualityExpression,
InequalityExpression,
RangedExpression,
)
from pyomo.core.expr.visitor import (
StreamBasedExpressionVisitor,
identify_components,
identify_variables,
)
from pyomo.devel.initialization.bounds.bound_variables import (
bound_all_nonlinear_variables,
)
from pyomo.devel.initialization.pwl_init import _minimize_infeasibility
from pyomo.devel.initialization.utils import (
fix_vars_with_equal_bounds,
get_vars,
shallow_clone,
)
from pyomo.repn.linear import LinearRepn, LinearRepnVisitor
from pyomo.repn.util import ExitNodeDispatcher

Comment on lines +10 to +60
from pyomo.core.base.block import BlockData
import pyomo.environ as pe
from pyomo.devel.initialization.bounds.bound_variables import (
bound_all_nonlinear_variables,
)
from pyomo.devel.initialization.utils import (
fix_vars_with_equal_bounds,
shallow_clone,
get_vars,
)
from pyomo.core.expr.visitor import identify_components
from pyomo.contrib.piecewise.piecewise_linear_expression import (
PiecewiseLinearExpression,
)
from pyomo.contrib.piecewise.piecewise_linear_function import PiecewiseLinearFunction
from pyomo.common.collections import ComponentMap, ComponentSet
from typing import MutableMapping, Sequence, List
from pyomo.core.base.constraint import ConstraintData
from pyomo.core.expr.visitor import StreamBasedExpressionVisitor
from pyomo.common.numeric_types import native_numeric_types
from pyomo.core.expr.numvalue import NumericConstant
from pyomo.core.expr.numeric_expr import (
NegationExpression,
PowExpression,
ProductExpression,
MonomialTermExpression,
DivisionExpression,
SumExpression,
LinearExpression,
UnaryFunctionExpression,
NPV_NegationExpression,
NPV_PowExpression,
NPV_ProductExpression,
NPV_DivisionExpression,
NPV_SumExpression,
NPV_UnaryFunctionExpression,
)
from pyomo.core.expr.relational_expr import (
EqualityExpression,
InequalityExpression,
RangedExpression,
)
from pyomo.repn.util import ExitNodeDispatcher
from pyomo.core.base.var import ScalarVar, VarData
from pyomo.core.base.param import ScalarParam, ParamData
from pyomo.core.base.expression import ScalarExpression, ExpressionData
import math
from pyomo.contrib.solver.common.base import SolverBase
import logging
from pyomo.common.modeling import unique_component_name
from pyomo.contrib.solver.common.results import SolutionStatus
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from pyomo.core.base.block import BlockData
import pyomo.environ as pe
from pyomo.devel.initialization.bounds.bound_variables import (
bound_all_nonlinear_variables,
)
from pyomo.devel.initialization.utils import (
fix_vars_with_equal_bounds,
shallow_clone,
get_vars,
)
from pyomo.core.expr.visitor import identify_components
from pyomo.contrib.piecewise.piecewise_linear_expression import (
PiecewiseLinearExpression,
)
from pyomo.contrib.piecewise.piecewise_linear_function import PiecewiseLinearFunction
from pyomo.common.collections import ComponentMap, ComponentSet
from typing import MutableMapping, Sequence, List
from pyomo.core.base.constraint import ConstraintData
from pyomo.core.expr.visitor import StreamBasedExpressionVisitor
from pyomo.common.numeric_types import native_numeric_types
from pyomo.core.expr.numvalue import NumericConstant
from pyomo.core.expr.numeric_expr import (
NegationExpression,
PowExpression,
ProductExpression,
MonomialTermExpression,
DivisionExpression,
SumExpression,
LinearExpression,
UnaryFunctionExpression,
NPV_NegationExpression,
NPV_PowExpression,
NPV_ProductExpression,
NPV_DivisionExpression,
NPV_SumExpression,
NPV_UnaryFunctionExpression,
)
from pyomo.core.expr.relational_expr import (
EqualityExpression,
InequalityExpression,
RangedExpression,
)
from pyomo.repn.util import ExitNodeDispatcher
from pyomo.core.base.var import ScalarVar, VarData
from pyomo.core.base.param import ScalarParam, ParamData
from pyomo.core.base.expression import ScalarExpression, ExpressionData
import math
from pyomo.contrib.solver.common.base import SolverBase
import logging
from pyomo.common.modeling import unique_component_name
from pyomo.contrib.solver.common.results import SolutionStatus
import logging
import math
from typing import List, MutableMapping, Sequence
import pyomo.environ as pyo
from pyomo.common.collections import ComponentMap, ComponentSet
from pyomo.common.modeling import unique_component_name
from pyomo.common.numeric_types import native_numeric_types
from pyomo.contrib.piecewise.piecewise_linear_expression import (
PiecewiseLinearExpression,
)
from pyomo.contrib.piecewise.piecewise_linear_function import PiecewiseLinearFunction
from pyomo.contrib.solver.common.base import SolverBase
from pyomo.contrib.solver.common.results import SolutionStatus
from pyomo.core.base.block import BlockData
from pyomo.core.base.constraint import ConstraintData
from pyomo.core.base.expression import ExpressionData, ScalarExpression
from pyomo.core.base.param import ParamData, ScalarParam
from pyomo.core.base.var import ScalarVar, VarData
from pyomo.core.expr.numvalue import NumericConstant
from pyomo.core.expr.numeric_expr import (
DivisionExpression,
LinearExpression,
MonomialTermExpression,
NegationExpression,
NPV_DivisionExpression,
NPV_NegationExpression,
NPV_PowExpression,
NPV_ProductExpression,
NPV_SumExpression,
NPV_UnaryFunctionExpression,
PowExpression,
ProductExpression,
SumExpression,
UnaryFunctionExpression,
)
from pyomo.core.expr.relational_expr import (
EqualityExpression,
InequalityExpression,
RangedExpression,
)
from pyomo.core.expr.visitor import (
StreamBasedExpressionVisitor,
identify_components,
)
from pyomo.devel.initialization.bounds.bound_variables import (
bound_all_nonlinear_variables,
)
from pyomo.devel.initialization.utils import (
fix_vars_with_equal_bounds,
get_vars,
shallow_clone,
)
from pyomo.repn.util import ExitNodeDispatcher

Comment on lines +240 to +242
# var_vals = tuple(i.value for i in expr.args)
# for v, val in zip(expr.args, var_vals):
# print(f'{str(v):<20}{val:<20.5f}{v.lb:<20.5f}{v.ub:<20.5f}{id(v):<20}')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Residual?

Comment on lines +10 to +14
import pyomo.environ as pe
from pyomo.common.collections import ComponentSet
from pyomo.core.base.block import BlockData
from pyomo.core.expr.visitor import identify_variables
import math
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import pyomo.environ as pe
from pyomo.common.collections import ComponentSet
from pyomo.core.base.block import BlockData
from pyomo.core.expr.visitor import identify_variables
import math
import math
import pyomo.environ as pyo
from pyomo.common.collections import ComponentSet
from pyomo.core.base.block import BlockData
from pyomo.core.expr.visitor import identify_variables

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Piecewise Nonlinear => PWL nudge

3 participants