A Python implementation of Augmented Lagrangian Coordination for decomposition-based and multidisciplinary design optimization
Project description
Python implementation of Augmented Lagrangian Coordination framework for decomposition-based and multidisciplinary design optimization
Installation
PyPI Installation
The package can easily be installed from PyPI:
pip install alcoord
Optimization Solver Installation
Depending on the optimization models you solve, you may need external optimization solvers such as Gurobi, BARON, CPLEX, SCIP, and IPOPT.
Optimization problems are modeled using Pyomo, so solver availability depends on your environment and Pyomo configuration.
To see available solvers, run:
pyomo help --solvers
Note that solvers need to be visible to Pyomo in addition to being installed system-wide, which may require configuring environment variables.
Development Installation
This project uses poetry for development.
If you want to work on the source code, you can install from source (e.g., with conda):
git clone https://github.com/masaisaji/alcoord.git
cd alcoord
conda create -n alcoord python=3.11
conda activate alcoord
poetry install
If virtualenv or similar is preferred, run poetry install in the newly created virtual environment with Python version 3.11 or later.
During development, it is recommended to run tests to ensure that the code works correctly after modifications:
poetry run pytest
Usage Pattern
The following skeleton illustrates the expected structure. Let's say you have the following problem you want to decompose
$$ \begin{aligned} \min & f_1(x_1,x_2,x_3) + f_2(x_2,x_3,x_4,x_5)\ \text{s.t.} & g_1(x_1, x_2, x_3) \leq 0\ & g_{21}(x_2, x_5) \leq 0 \ & g_{22}(x_3, x_4) \leq 0 \end{aligned} $$
into two subproblems such as
$$ \begin{aligned} \min & f_1(x_1,x_2,x_3) + \phi(x_1,x_2,x_3)\ \text{s.t.} & g_1(x_1, x_2, x_3) \leq 0 \end{aligned} $$ $$ \begin{aligned} \min & f_2(x_2,x_3,x_4,x_5) + \phi(x_2,x_3,x_4,x_5)\ \text{s.t.} & g_{21}(x_2, x_5) \leq 0 \ & g_{22}(x_3, x_4) \leq 0 \end{aligned} $$
where $\phi$ is the augmented Lagrangian term for the corresponding subproblem. To solve such problems with the augmented Lagrangian coordination method implemented in this codebase, you need:
- a method that builds and solves each subproblem modeled with
pyomo - an initial guess (for nonlinear programming (NLP) subproblems)
High-Level Flow and a Skeleton Code
Assuming that you already have the subproblem solve methods and an initial guess, the overall usage flow is as follows
- Create a "dependency matrix" with 1/0 or True/False. For example, the dependency of subproblem 1 above would be
[1, 1, 1, 0, 0]since it depends on $x_1, x_2, x_3$ but not on $x_4, x_5$. - In a
dict, specify the following for each subproblem:- the optimization type ("MIP" or "NLP"),
- the function that returns the subproblem solve result (to be detailed later), and
- optional arguments needed for the solve function
- Build instances of the
alcoordclasses (DimensionConverter,InnerLoop, andOuterLoop) - Run the algorithm and retrieve the results
A skeleton script for the above example:
from alcoord import (
InnerLoop,
OuterLoop,
DimensionConverter,
AllSubpDict,
)
import numpy as np
from example_subproblem import solve_subproblem_1, solve_subproblem_2
initial_guess: np.ndarray = np.array(
[
# define initial guess here
]
)
# Indicate subproblem's variable dependency with 1/0 or True/False
depen_matrix: list[list[int]] = [
[1, 1, 1, 0, 0],
[0, 1, 1, 1, 1],
]
dim_all_var = 5
# Create a dict including:
# the optimization type ("MIP" or "NLP"),
# function returning subproblem solve results,
# and optional arguments
# for each subproblem
all_subprob_dict: AllSubpDict = {
0: {"optim type": "NLP", "function": solve_subproblem_1, "args": None},
1: {"optim type": "NLP", "function": solve_subproblem_2, "args": None},
}
# Build necessary objects/instances
# See docs of each class for additional parameter settings
dim_conv = DimensionConverter(
dependency_matrix=depen_matrix,
dim_all_var=dim_all_var,
)
inner_loop = InnerLoop(
dc=dim_conv,
all_subprob_dict=all_subprob_dict,
initial_guess=initial_guess,
)
outer_loop = OuterLoop(
inner_loop=inner_loop,
)
# Run the algorithm/routine and retrieve results
res = outer_loop.run()
obj = res["objectives"]
var = res["design vars"]
Subproblem Solve Function
A function that solves a subproblem and returns its solution is expected to take the following arguments:
local_shared_var_targetlagrange_estpenalty_weightlocal_var_idxlocal_shared_var_idxargsinitial_guess
Except for args and initial_guess, these arguments are mostly used to reflect the subproblem's relation with the other subproblems, which is captured through the augmented Lagrangian terms in the objective.
The augmented Lagrangian term can be obtained using a helper function get_aug_lag_term_for_pyomo, which returns a Pyomo expression you can use directly when defining the objective.
Once the subproblem optimization model is built and solved, the function is expected to return a SubproblemResult object, which is a simple dict with "objective" and "design var" keys.
A skeleton script for the above example is as follows:
from alcoord import (
SubproblemResult,
get_aug_lag_term_for_pyomo,
)
import pyomo.environ as pyo
import numpy as np
def solve_subproblem_1(
local_shared_var_target: np.ndarray,
lagrange_est: np.ndarray,
penalty_weight: np.ndarray,
local_var_idx: list[int],
local_shared_var_idx: list[int],
args=None,
initial_guess=None,
) -> SubproblemResult:
model = pyo.ConcreteModel()
#
# define indices, variables, constraints, etc
#
penalty_term = get_aug_lag_term_for_pyomo(
local_shared_var_target=local_shared_var_target,
lagrange_est=lagrange_est,
penalty_weight=penalty_weight,
pyomo_local_shared_var_ls=[
model.x2, model.x3
],
)
original_objective = ... # objective expression w/o penalty
model.obj = pyo.Objective(
expr=original_objective + penalty_term
)
pyo.SolverFactory("ipopt").solve(model, tee=False)
obj = float(pyo.value(model.obj))
design_var = np.array(
[
# extract design variable values...
]
)
subp_res: SubproblemResult = {"objective": obj, "design var": design_var}
return subp_res
Module Dependencies Map
Note: $\fbox{calling module} \rightarrow \fbox{called module}$
graph TD
inner_loop.py --> dimension_converter.py
inner_loop.py --> subproblems.py
inner_loop.py --> type_defs.py
subproblems.py --> type_defs.py
outer_loop.py --> inner_loop.py
outer_loop.py --> type_defs.py
Legacy version for Linux
On Linux, the legacy version lets you use pygmo and its compatible solvers for continuous nonlinear programming (NLP) problems.
To install the dependency for this legacy version, run
poetry install -E legacy
for development, or
pip install "alcoord[legacy]"
for PyPI installation.
A separate set of tests for the legacy version can be run with:
poetry run pytest -m legacy
This version is unsupported on other platforms.
References
- Augmented Lagrangian coordination for distributed optimal design in MDO
- MDO Approach to Integrated Space Mission Planning and Spacecraft Design
Acknowledgment
This material is based upon work supported by the National Science Foundation under Award No. 1942559. Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file alcoord-0.1.0.tar.gz.
File metadata
- Download URL: alcoord-0.1.0.tar.gz
- Upload date:
- Size: 17.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.11.2 Linux/6.18.33.1-microsoft-standard-WSL2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3243c928f7d96def3a84f225fda3fcef79e28cf826a4636042649216c0b1ade
|
|
| MD5 |
931d2ed10e73e60fed95856992f37012
|
|
| BLAKE2b-256 |
1a1da7970426c56d0a10a2097b7d6ef888f87e53361be973704c77ad40c2c5d1
|
File details
Details for the file alcoord-0.1.0-py3-none-any.whl.
File metadata
- Download URL: alcoord-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.11.2 Linux/6.18.33.1-microsoft-standard-WSL2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7106703a31fa391b59d456f34d099678783cb0da5b007c397ef9cf135028a40a
|
|
| MD5 |
c25c2b780f74e9ec38b52731f93d680c
|
|
| BLAKE2b-256 |
b480e116b2c5337084a9692c42510ca35aa41490821b5cc445d28551c1db720b
|