Skip to content

Commit 05fce3e

Browse files
committed
Rewrite the structured NLP API
1 parent 3560582 commit 05fce3e

File tree

312 files changed

+6779
-6485
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

312 files changed

+6779
-6485
lines changed

CMakeLists.txt

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,6 @@ add_subdirectory(thirdparty/fmt)
3838
add_subdirectory(thirdparty/cppad)
3939

4040
set(POI_INSTALL_DIR ${SKBUILD_PLATLIB_DIR}/pyoptinterface/_src)
41-
# install the DLL of cppad
42-
if(MSVC)
43-
install(TARGETS cppad_thread_alloc RUNTIME DESTINATION ${POI_INSTALL_DIR})
44-
else()
45-
install(TARGETS cppad_thread_alloc LIBRARY DESTINATION ${POI_INSTALL_DIR})
46-
endif()
4741

4842
add_library(core STATIC)
4943
target_sources(core PRIVATE
@@ -57,12 +51,28 @@ target_sources(core PRIVATE
5751
target_include_directories(core PUBLIC include thirdparty)
5852
target_link_libraries(core PUBLIC fmt)
5953

60-
add_library(nlcore STATIC)
61-
target_sources(nlcore PRIVATE
62-
include/pyoptinterface/nlcore.hpp
63-
lib/nlcore.cpp
54+
add_library(nlexpr STATIC)
55+
target_sources(nlexpr PRIVATE
56+
include/pyoptinterface/nlexpr.hpp
57+
lib/nlexpr.cpp
58+
)
59+
target_include_directories(nlexpr PUBLIC include thirdparty)
60+
target_link_libraries(nlexpr PUBLIC fmt)
61+
62+
add_library(nleval STATIC)
63+
target_sources(nleval PRIVATE
64+
include/pyoptinterface/nleval.hpp
65+
lib/nleval.cpp
6466
)
65-
target_link_libraries(nlcore PUBLIC core cppad)
67+
target_link_libraries(nleval PUBLIC core)
68+
69+
add_library(cppad_interface STATIC)
70+
target_sources(cppad_interface PRIVATE
71+
include/pyoptinterface/cppad_interface.hpp
72+
lib/cppad_interface.cpp
73+
)
74+
target_include_directories(cppad_interface PUBLIC include thirdparty)
75+
target_link_libraries(cppad_interface PUBLIC nlexpr cppad)
6676

6777
# Build Python extensions
6878
find_package(Python ${PYTHON_VERSION}
@@ -83,14 +93,34 @@ target_link_libraries(core_ext PUBLIC core)
8393
install(TARGETS core_ext LIBRARY DESTINATION ${POI_INSTALL_DIR})
8494

8595
nanobind_add_module(
86-
nlcore_ext
96+
nlexpr_ext
97+
98+
STABLE_ABI NB_STATIC
99+
100+
lib/nlexpr_ext.cpp
101+
)
102+
target_link_libraries(nlexpr_ext PUBLIC nlexpr)
103+
install(TARGETS nlexpr_ext LIBRARY DESTINATION ${POI_INSTALL_DIR})
104+
105+
nanobind_add_module(
106+
nleval_ext
107+
108+
STABLE_ABI NB_STATIC
109+
110+
lib/nleval_ext.cpp
111+
)
112+
target_link_libraries(nleval_ext PUBLIC nleval)
113+
install(TARGETS nleval_ext LIBRARY DESTINATION ${POI_INSTALL_DIR})
114+
115+
nanobind_add_module(
116+
cppad_interface_ext
87117

88118
STABLE_ABI NB_STATIC
89119

90-
lib/nlcore_ext.cpp
120+
lib/cppad_interface_ext.cpp
91121
)
92-
target_link_libraries(nlcore_ext PUBLIC nlcore)
93-
install(TARGETS nlcore_ext LIBRARY DESTINATION ${POI_INSTALL_DIR})
122+
target_link_libraries(cppad_interface_ext PUBLIC cppad_interface)
123+
install(TARGETS cppad_interface_ext LIBRARY DESTINATION ${POI_INSTALL_DIR})
94124

95125
# Solvers
96126

@@ -178,7 +208,7 @@ target_sources(ipopt_model PRIVATE
178208
include/pyoptinterface/ipopt_model.hpp
179209
lib/ipopt_model.cpp
180210
)
181-
target_link_libraries(ipopt_model PUBLIC nlcore)
211+
target_link_libraries(ipopt_model PUBLIC nleval)
182212

183213
nanobind_add_module(
184214
ipopt_model_ext
@@ -191,7 +221,7 @@ target_link_libraries(ipopt_model_ext PUBLIC ipopt_model)
191221
install(TARGETS ipopt_model_ext LIBRARY DESTINATION ${POI_INSTALL_DIR})
192222

193223
# Set RPATH
194-
set_rpath(nlcore_ext)
224+
# set_rpath(nlcore_ext)
195225
set_rpath(ipopt_model_ext)
196226

197227
# stub
@@ -203,10 +233,24 @@ nanobind_add_stub(
203233
)
204234

205235
nanobind_add_stub(
206-
nlcore_ext_stub
236+
nlexpr_ext_stub
237+
INSTALL_TIME
238+
MODULE pyoptinterface._src.nlexpr_ext
239+
OUTPUT ${POI_INSTALL_DIR}/nlexpr_ext.pyi
240+
)
241+
242+
nanobind_add_stub(
243+
nleval_ext_stub
244+
INSTALL_TIME
245+
MODULE pyoptinterface._src.nleval_ext
246+
OUTPUT ${POI_INSTALL_DIR}/nleval_ext.pyi
247+
)
248+
249+
nanobind_add_stub(
250+
cppad_interface_ext_stub
207251
INSTALL_TIME
208-
MODULE pyoptinterface._src.nlcore_ext
209-
OUTPUT ${POI_INSTALL_DIR}/nlcore_ext.pyi
252+
MODULE pyoptinterface._src.cppad_interface_ext
253+
OUTPUT ${POI_INSTALL_DIR}/cppad_interface_ext.pyi
210254
)
211255

212256
nanobind_add_stub(
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
#include "cppad/cppad.hpp"
4+
#include "pyoptinterface/nlexpr.hpp"
5+
#include "pyoptinterface/nleval.hpp"
6+
7+
using ADFunDouble = CppAD::ADFun<double>;
8+
9+
ADFunDouble dense_jacobian(const ADFunDouble &f);
10+
11+
using sparsity_pattern_t = CppAD::sparse_rc<std::vector<size_t>>;
12+
13+
struct JacobianHessianSparsityPattern
14+
{
15+
sparsity_pattern_t jacobian;
16+
sparsity_pattern_t hessian;
17+
sparsity_pattern_t reduced_hessian;
18+
};
19+
20+
JacobianHessianSparsityPattern jacobian_hessian_sparsity(ADFunDouble &f,
21+
HessianSparsityType hessian_sparsity);
22+
23+
// [p, x] -> Jacobian
24+
ADFunDouble sparse_jacobian(const ADFunDouble &f, const sparsity_pattern_t &pattern_jac,
25+
const std::vector<double> &x_values,
26+
const std::vector<double> &p_values);
27+
28+
// [p, w, x] -> \Sigma w_i * Hessian_i
29+
ADFunDouble sparse_hessian(const ADFunDouble &f, const sparsity_pattern_t &pattern_hes,
30+
const sparsity_pattern_t &pattern_subset,
31+
const std::vector<double> &x_values,
32+
const std::vector<double> &p_values);
33+
34+
// Transform ExpressionGraph to CppAD function
35+
ADFunDouble cppad_trace_function(const ExpressionGraph &graph,
36+
const std::vector<ExpressionHandle> &outputs);
37+
38+
struct CppADAutodiffGraph
39+
{
40+
CppAD::cpp_graph f_graph, jacobian_graph, hessian_graph;
41+
};
42+
43+
// Generate computational graph for the CppAD function (itself, Jacobian and Hessian)
44+
// Analyze its sparsity as well
45+
void cppad_autodiff(ADFunDouble &f, AutodiffSymbolicStructure &structure, CppADAutodiffGraph &graph,
46+
const std::vector<double> &x_values, const std::vector<double> &p_values);

include/pyoptinterface/ipopt_model.hpp

Lines changed: 18 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

33
#include "solvers/ipopt/IpStdCInterface.h"
4-
#include "pyoptinterface/nlcore.hpp"
4+
#include "pyoptinterface/nleval.hpp"
55

66
#define APILIST \
77
B(CreateIpoptProblem); \
@@ -120,56 +120,22 @@ struct IpoptModel
120120
}
121121
}
122122

123-
FunctionIndex register_function(ADFunD &f, const std::string &name,
124-
const std::vector<double> &x_values,
125-
const std::vector<double> &p_values);
126-
127-
NLConstraintIndex add_empty_nl_constraint(int dim, ConstraintSense sense,
128-
const std::vector<double> &rhss);
129-
NLConstraintIndex add_empty_nl_constraint(int dim, ConstraintSense sense,
130-
const std::vector<double> &lbs,
131-
const std::vector<double> &ubs);
132-
133-
NLConstraintIndex add_nl_constraint(const FunctionIndex &k,
134-
const std::vector<VariableIndex> &xs,
135-
const std::vector<ParameterIndex> &ps,
136-
ConstraintSense sense, const std::vector<double> &rhss);
137-
NLConstraintIndex add_nl_constraint(const FunctionIndex &k,
138-
const std::vector<VariableIndex> &xs,
139-
const std::vector<double> &ps, ConstraintSense sense,
140-
const std::vector<double> &rhss);
141-
NLConstraintIndex add_nl_constraint(const FunctionIndex &k,
142-
const std::vector<VariableIndex> &xs, ConstraintSense sense,
143-
const std::vector<double> &rhss);
144-
145-
NLConstraintIndex add_nl_constraint(const FunctionIndex &k,
146-
const std::vector<VariableIndex> &xs,
147-
const std::vector<ParameterIndex> &ps,
148-
ConstraintSense sense, const std::vector<double> &lbs,
149-
const std::vector<double> &ubs);
150-
NLConstraintIndex add_nl_constraint(const FunctionIndex &k,
151-
const std::vector<VariableIndex> &xs,
152-
const std::vector<double> &ps, ConstraintSense sense,
153-
const std::vector<double> &lbs,
154-
const std::vector<double> &ubs);
155-
NLConstraintIndex add_nl_constraint(const FunctionIndex &k,
156-
const std::vector<VariableIndex> &xs, ConstraintSense sense,
157-
const std::vector<double> &lbs,
158-
const std::vector<double> &ubs);
159-
160-
void add_nl_expression(const NLConstraintIndex &constraint, const FunctionIndex &k,
161-
const std::vector<VariableIndex> &xs,
162-
const std::vector<ParameterIndex> &ps);
163-
void add_nl_expression(const NLConstraintIndex &constraint, const FunctionIndex &k,
164-
const std::vector<VariableIndex> &xs, const std::vector<double> &ps);
165-
void add_nl_expression(const NLConstraintIndex &constraint, const FunctionIndex &k,
166-
const std::vector<VariableIndex> &xs);
123+
FunctionIndex _register_function(const AutodiffSymbolicStructure &structure);
124+
void _set_function_evaluator(const FunctionIndex &k, const AutodiffEvaluator &evaluator);
125+
126+
NLConstraintIndex _add_nl_constraint_bounds(const FunctionIndex &k,
127+
const std::vector<VariableIndex> &xs,
128+
const std::vector<ParameterIndex> &ps,
129+
const std::vector<double> &lbs,
130+
const std::vector<double> &ubs);
167131

168-
void add_nl_objective(const FunctionIndex &k, const std::vector<VariableIndex> &xs);
169-
void add_nl_objective(const FunctionIndex &k, const std::vector<VariableIndex> &xs,
170-
const std::vector<ParameterIndex> &ps);
171-
void add_nl_objective(const FunctionIndex &k, const std::vector<VariableIndex> &xs,
172-
const std::vector<double> &ps);
132+
NLConstraintIndex _add_nl_constraint_eq(const FunctionIndex &k,
133+
const std::vector<VariableIndex> &xs,
134+
const std::vector<ParameterIndex> &ps,
135+
const std::vector<double> &eqs);
136+
137+
void _add_nl_objective(const FunctionIndex &k, const std::vector<VariableIndex> &xs,
138+
const std::vector<ParameterIndex> &ps);
173139

174140
void clear_nl_objective();
175141

@@ -197,8 +163,8 @@ struct IpoptModel
197163
std::vector<size_t> m_hessian_rows, m_hessian_cols;
198164
Hashmap<VariablePair, size_t> m_hessian_index_map;
199165

200-
NonlinearFunctionModel m_function_model;
201-
LinearQuadraticModel m_lq_model;
166+
NonlinearFunctionEvaluator m_function_model;
167+
LinearQuadraticEvaluator m_lq_model;
202168

203169
// The options of the Ipopt solver, we cache them before constructing the m_problem
204170
Hashmap<std::string, int> m_options_int;

0 commit comments

Comments
 (0)