SPPA MINLP solver


License
MIT
Install
pip install sppa==1.1.0

Documentation

sppa

Sequential Piecewise Planar Approximation (SPPA) for piecewise linear programming. A convergent MINLP solver for mathematical programming problems. Arxiv preprint: https://arxiv.org/abs/2004.09474.

Installation

Use the package manager pip to install sppa.

pip install sppa

Use of CPLEX in sppa requires installation of the Python API of the CPLEX library.

sppa also requires the python packages PuLP and numpy which should be automatically installed withpip.

Documentation

API documentation available as a PDF file in the repo above.

Usage

An example usage of sppa on a spring design MINLP problem. AMPL model file available here. (E. Sangren, Trans. ASME, J. Mech. Design 112, 223-229, 1990)

from sppa import SPPA, Var, NlinExpr # equivalently, from sppa import *

# constant definitions
Pload = 300
Pmax = 1000
delm = 6
delw = 1.25
lmax = 14
Dmax = 3
S = 189000
G = 11.5E6
dmin = 0.2
pi = 3.141592654
d = [0.207, 0.225, 0.244, 0.263, 0.283, 0.307, 0.331, 0.362, 0.394, 0.4375, 0.5]
C_upbound = (Dmax-min(d))/min(d)

# Nonlinear function definitions
def f(D, d_index, N):
    return pi * D * d[d_index] ** 2 * (N + 2) / 4
def div_fun(D, d_index):
    return D / d[d_index]
def K_fun(C):
    return (4*C - 1)/(4*C - 4) + 0.615/C
def S_fun(K, D, d_index):
    return 8 * Pmax * K * D / (pi * d[d_index] ** 3)
def del_fun(N, D, d_index):
    return 8 * (N * D**3) / (G * d[d_index] ** 4)
def lmax_fun(N, d_index):
    return 1.05 * (N+2) * d[d_index]
def d_fun(d_index):
    return d[d_index]

# optimization variable definitions
di = Var('di', low_bound=0, up_bound=10, var_type='int', expand=True)
D = Var('D', low_bound=2*dmin, up_bound=Dmax-min(d))
N = Var('N', low_bound=1, up_bound=100, var_type='int')
C = Var('C', low_bound=1.1, up_bound=C_upbound)
K = Var('K', low_bound=K_fun(C_upbound), up_bound=K_fun(1.1))
del_ = Var('del', low_bound=0)

# initialize solver
prob = SPPA('testproblem_spring')

# set objective
prob.set_objective(NlinExpr(f, D, di, N), name='material')

# add equality constraints
prob.add_equality_constraint(C - NlinExpr(div_fun, D, di), 'C_def')
prob.add_equality_constraint(K - NlinExpr(K_fun, C), 'K_def')
prob.add_equality_constraint(del_ - NlinExpr(del_fun, N, D, di))

# add inequality constraints (expression >= 0)
prob.add_inequality_constraint(S - NlinExpr(S_fun, K, D, di))
prob.add_inequality_constraint(lmax - Pmax*del_ - NlinExpr(lmax_fun, N, di))
prob.add_inequality_constraint(Dmax - D - NlinExpr(d_fun, di))
prob.add_inequality_constraint(delm - Pload*del_)
prob.add_inequality_constraint((Pmax-Pload)*del_ - delw)

# solve problem
prob.compile(initial_n_pieces=4, n_pieces=3, solver='cbc', contract_frac=0.8)
prob.write()
prob.set_termination_criteria(ftol=None, xtol=1E-6, computation_time=None, max_iterations=100)
result = prob.solve()

print('Objective found: ' + str(result.value))
print('Solution found: ' + str(result.solution))

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

MIT