Skip to content

Commit

Permalink
Add ipopt autoload
Browse files Browse the repository at this point in the history
  • Loading branch information
metab0t committed Jun 8, 2024
1 parent 5f5ffcf commit 2b90904
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 19 deletions.
5 changes: 3 additions & 2 deletions src/pyoptinterface/_src/codegen_llvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,20 +226,21 @@ def create_indirect_load_store(module: ir.Module):
graph_op.sinh: "sinh",
graph_op.sqrt: "sqrt",
graph_op.tan: "tan",
graph_op.tanh: "tanh"
graph_op.tanh: "tanh",
}

math_ops = set(op2name.keys())

binary_ops = set([graph_op.pow])


def create_llvmir_basic_functions(module: ir.Module):
create_azmul(module)
create_sign(module)
create_direct_load_store(module)
create_indirect_load_store(module)

for (op, op_name) in op2name.items():
for op, op_name in op2name.items():
if op in binary_ops:
func_type = ir.FunctionType(D, [D, D])
else:
Expand Down
36 changes: 33 additions & 3 deletions src/pyoptinterface/_src/ipopt.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from io import StringIO
import types
import logging
import platform

from llvmlite import ir

from .ipopt_model_ext import RawModel, ApplicationReturnStatus
from .ipopt_model_ext import RawModel, ApplicationReturnStatus, load_library
from .codegen_c import generate_csrc_prelude, generate_csrc_from_graph
from .jit_c import TCCJITCompiler
from .codegen_llvm import create_llvmir_basic_functions, generate_llvmir_from_graph
Expand All @@ -29,6 +31,33 @@
from .aml import make_nd_variable


def detected_libraries():
libs = []

# default names
default_libnames = {
"Linux": ["libipopt.so"],
"Darwin": ["libpopt.dylib"],
"Windows": ["ipopt-3.dll", "ipopt.dll", "libipopt-3.dll", "libipopt.dll"],
}[platform.system()]
libs.extend(default_libnames)

return libs


def autoload_library():
libs = detected_libraries()
for lib in libs:
ret = load_library(lib)
if ret:
logging.info(f"Loaded IPOPT library: {lib}")
return True
return False


autoload_library()


def compile_functions_c(backend: RawModel, jit_compiler: TCCJITCompiler):
io = StringIO()

Expand Down Expand Up @@ -294,9 +323,10 @@ def get_constraint_primal(model, constraint):
dim = constraint.dim
values = [model.get_constraint_primal(index + i) for i in range(dim)]
return values

raise ValueError(f"Unknown constraint type: {type(constraint)}")


def get_constraint_dual(model, constraint):
if isinstance(constraint, ConstraintIndex):
return model.get_constraint_dual(constraint.index)
Expand All @@ -305,7 +335,7 @@ def get_constraint_dual(model, constraint):
dim = constraint.dim
values = [model.get_constraint_dual(index + i) for i in range(dim)]
return values

raise ValueError(f"Unknown constraint type: {type(constraint)}")


Expand Down
26 changes: 12 additions & 14 deletions tests/nlp.py → tests/test_nlp.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@
import pyoptinterface as poi
from pyoptinterface import ipopt

IPOPT_PATH = r"D:\Ipopt\bin\ipopt-3.dll"

if not ipopt.load_library(IPOPT_PATH):
if not ipopt.is_library_loaded():
exit(1)


def test_ipopt():
model = ipopt.Model()

x = model.add_variable(lb=0.0, ub=10.0, start=0.8)
y = model.add_variable(lb=0.0, ub=10.0, start=0.5)
x = model.add_variable(lb=0.1, ub=10.0, start=0.8)
y = model.add_variable(lb=0.1, ub=10.0, start=0.5)

model.add_linear_constraint(x + y, poi.Eq, 1.0)

Expand Down Expand Up @@ -93,7 +91,7 @@ def all_nlfuncs(vars):
if f == poi.acosh:
v = f(x + 1)
elif f == poi.pow:
v = f(x, x)
v = f(x, 2)
else:
v = f(x)
values.append(v)
Expand All @@ -103,7 +101,9 @@ def all_nlfuncs(vars):
all_nlfuncs_f = model.register_function(all_nlfuncs, var=["x"], name="all_nlfuncs")
N = len(nl_funcs)
B = 1e10
all_nlfuncs_con = model.add_nl_constraint(all_nlfuncs_f, [x], poi.In, lb=[-B] * N, ub=[B] * N)
all_nlfuncs_con = model.add_nl_constraint(
all_nlfuncs_f, [x], poi.In, lb=[-B] * N, ub=[B] * N
)

model.optimize()

Expand All @@ -120,19 +120,17 @@ def all_nlfuncs(vars):
obj_value = model.get_model_attribute(poi.ModelAttribute.ObjectiveValue)
assert obj_value == pytest.approx(math.exp(x_value) + math.exp(y_value))

con_values = model.get_constraint_attribute(all_nlfuncs_con, poi.ConstraintAttribute.Primal)

con_values = model.get_constraint_attribute(
all_nlfuncs_con, poi.ConstraintAttribute.Primal
)

correct_con_values = []
for f in py_funcs:
if f == math.acosh:
v = f(x_value + 1)
elif f == math.pow:
v = f(x_value, x_value)
v = f(x_value, 2)
else:
v = f(x_value)
correct_con_values.append(v)
assert con_values == pytest.approx(correct_con_values)


if __name__ == "__main__":
test_ipopt()

0 comments on commit 2b90904

Please sign in to comment.