diff --git a/nl-writer2/CMakeLists.txt b/nl-writer2/CMakeLists.txt index 398c377c8..c19354571 100644 --- a/nl-writer2/CMakeLists.txt +++ b/nl-writer2/CMakeLists.txt @@ -12,29 +12,34 @@ option(NLW2_LIB_ORIG_HDR set(NLW2_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(NLW2_INCLUDE_PATH ${NLW2_DIR}/include) +set(NLW2_SRC_PATH ${NLW2_DIR}/src) +set(NLW2_EXAMPLE_PATH ${NLW2_DIR}/examples) + +# NLW2 library C++ sources set(NLW2_LIB_FILES - ${NLW2_DIR}/src/nl-writer2.cc - ${NLW2_DIR}/src/nl-utils2.cc - ${NLW2_DIR}/src/dtoa.c) + ${NLW2_SRC_PATH}/nl-writer2.cc + ${NLW2_SRC_PATH}/nl-utils2.cc + ${NLW2_SRC_PATH}/dtoa.c) set(NLW2_INC_FILES - ${NLW2_DIR}/include/mp/nlsol.h - ${NLW2_DIR}/include/mp/nl-header.h - ${NLW2_DIR}/include/mp/nl-feeder2.h - ${NLW2_DIR}/include/mp/nl-writer2.h - ${NLW2_DIR}/include/mp/nl-writer2.hpp - ${NLW2_DIR}/include/mp/nl-writer2-misc.h - ${NLW2_DIR}/include/mp/nl-utils2.h - ${NLW2_DIR}/include/mp/sol-reader2.h - ${NLW2_DIR}/include/mp/sol-reader2.hpp - ${NLW2_DIR}/include/mp/sol-handler2.h + ${NLW2_INCLUDE_PATH}/mp/nlsol.h + ${NLW2_INCLUDE_PATH}/mp/nl-header.h + ${NLW2_INCLUDE_PATH}/mp/nl-feeder2.h + ${NLW2_INCLUDE_PATH}/mp/nl-writer2.h + ${NLW2_INCLUDE_PATH}/mp/nl-writer2.hpp + ${NLW2_INCLUDE_PATH}/mp/nl-writer2-misc.h + ${NLW2_INCLUDE_PATH}/mp/nl-utils2.h + ${NLW2_INCLUDE_PATH}/mp/sol-reader2.h + ${NLW2_INCLUDE_PATH}/mp/sol-reader2.hpp + ${NLW2_INCLUDE_PATH}/mp/sol-handler2.h ) -# Create library +# Create C++ library set(NLW2_LIB_NAME "nlw2") add_library(${NLW2_LIB_NAME} STATIC ${NLW2_LIB_FILES} ${NLW2_INC_FILES}) target_include_directories( - ${NLW2_LIB_NAME} PUBLIC ${NLW2_DIR}/include) + ${NLW2_LIB_NAME} PUBLIC ${NLW2_INCLUDE_PATH}) if (NLW2_LIB_ORIG_HDR) message(STATUS " NLW2_LIB: Building with the original NL header comments") @@ -42,28 +47,63 @@ if (NLW2_LIB_ORIG_HDR) ${NLW2_LIB_NAME} PUBLIC NL_LIB2_ORIG_HDR) endif() -# NLW2 example -set(NLSOL_EX_FILES - ${NLW2_DIR}/examples/nlsol_ex.cc - ${NLW2_DIR}/examples/nlsol_ex_mdl.h - ${NLW2_DIR}/examples/nlsol_ex_nl.h - ${NLW2_DIR}/examples/nlsol_ex_sol.h) +# C API sources +set(NLW2_C_API_LIB_FILES + ${NLW2_DIR}/src/c_api.cc + ) +set(NLW2_C_API_INC_FILES + ${NLW2_INCLUDE_PATH}/api/c/nl-feeder2.h + ) + +# C API library +set(NLW2_C_API_LIB_NAME "nlw2_c_api") +add_library(${NLW2_C_API_LIB_NAME} STATIC + ${NLW2_C_API_LIB_FILES} ${NLW2_C_API_INC_FILES}) +target_include_directories( + ${NLW2_C_API_LIB_NAME} PUBLIC ${NLW2_INCLUDE_PATH}) + +###################################################### +# Examples + +# NLW2 C++ example +set(NLW2_CPP_EXAMPLE_PATH ${NLW2_EXAMPLE_PATH}/cpp) +set(NLSOL_CPP_EX_FILES + ${NLW2_CPP_EXAMPLE_PATH}/nlsol_ex.cc + ${NLW2_CPP_EXAMPLE_PATH}/nlsol_ex_mdl.h + ${NLW2_CPP_EXAMPLE_PATH}/nlsol_ex_nl.h + ${NLW2_CPP_EXAMPLE_PATH}/nlsol_ex_sol.h) + +# NLW2 C API example +set(NLW2_C_EXAMPLE_PATH ${NLW2_EXAMPLE_PATH}/c) +set(NLSOL_C_EX_FILES + ${NLW2_C_EXAMPLE_PATH}/nlsol_ex_c.c + ) option(BUILD_EXAMPLES_NLW2 "Build NLW2 examples (library not affected). Assumes nl-opcodes.h (generated by MP)" ON) if (BUILD_EXAMPLES_NLW2) # Actually build the example - add_executable(nl-writer-example ${NLSOL_EX_FILES}) - target_include_directories(nl-writer-example PUBLIC - ${NLW2_DIR}/include) - target_link_libraries(nl-writer-example ${NLW2_LIB_NAME}) + add_executable(nl-writer-example-cpp ${NLSOL_CPP_EX_FILES}) + target_include_directories(nl-writer-example-cpp PUBLIC + ${NLW2_INCLUDE_PATH}) + target_link_libraries(nl-writer-example-cpp ${NLW2_LIB_NAME}) + + add_executable(nl-writer-example-c ${NLSOL_C_EX_FILES}) + target_include_directories(nl-writer-example-c PUBLIC + ${NLW2_INCLUDE_PATH}) + target_link_libraries(nl-writer-example-c ${NLW2__C_API_LIB_NAME}) endif() + +################################################################## # Export library include path -set(NLW2_INCLUDE_PATH ${NLW2_DIR}/include PARENT_SCOPE) +set(NLW2_INCLUDE_PATH ${NLW2_INCLUDE_PATH} PARENT_SCOPE) # Export source files set(NLW2_SRC - ${NLW2_LIB_FILES} ${NLW2_INC_FILES} ${NLSOL_EX_FILES} + ${NLW2_LIB_FILES} ${NLW2_INC_FILES} ${NLSOL_CPP_EX_FILES} + ${NLW2_C_API_LIB_FILES} ${NLW2_C_API_INC_FILES} + ${NLSOL_C_EX_FILES} PARENT_SCOPE) -# Export library target name +# Export library target names set(NLW2_LIB_NAME ${NLW2_LIB_NAME} PARENT_SCOPE) +set(NLW2_C_API_LIB_NAME ${NLW2_C_API_LIB_NAME} PARENT_SCOPE) diff --git a/nl-writer2/examples/c/nlsol_ex_c.c b/nl-writer2/examples/c/nlsol_ex_c.c new file mode 100644 index 000000000..7f895da7a --- /dev/null +++ b/nl-writer2/examples/c/nlsol_ex_c.c @@ -0,0 +1,36 @@ +/** + * C API example using NLWriter2 and SOLReader2 + * to write NL file, execute solver, and read SOL file. + * + */ + +#include +#include +#include + +#include "api/c/nl-feeder2.h" + +#include "nlsol_ex_c_model.h" + +int main(int argc, const char* const* argv) { + if (argc<2) { + printf("%s\n", + "AMPL NL writer C API example.\n" + "Usage:\n" + " [\"\" [binary/text []]],\n\n" + "where is ipopt, gurobi, minos, ...;\n" + "binary/text is the NL format (default: binary.)\n" + "Examples:\n" + " highs \"\" text /tmp/stub\n" + " gurobi \"mip:return_gap=1\""); + exit(0); + } + + const char* solver = (argc>1) ? argv[1] : "highs"; + const char* sopts = (argc>2) ? argv[2] : ""; + int binary = (argc<=3) || strcmp("text", argv[3]); + const char* stub = (argc>4) ? argv[4] : "stub"; + + + return 0; +} diff --git a/nl-writer2/examples/c/nlsol_ex_c_model.h b/nl-writer2/examples/c/nlsol_ex_c_model.h new file mode 100644 index 000000000..5483924a7 --- /dev/null +++ b/nl-writer2/examples/c/nlsol_ex_c_model.h @@ -0,0 +1,41 @@ +#ifndef NLSOL_EX_C_MODEL_H +#define NLSOL_EX_C_MODEL_H + +// #include "api/c/nl-header.h" +//#include "mp/nl-opcodes.h" + +/** + * A linear model for NL Writer C API example. + * Illustrates NL variable order (continuous -> integer), + * linear constraints. + * + +## In AMPL, set option presolve 0; to reproduce +## +## To write NL file and name files in AMPL, use commands +## ampl: option nl_comments 1; +## ampl: option auxfiles rc; +## ampl: write gmodel; + +var x >=0, integer; +var y >=-17, <=504; +maximize TotalSum: + x + 13*y; +subj to C2: + 3700*x + 0.6*y <= 3e4; +subj to C3: + 22*x + 14536*y <= 3e5; + +## Initial guess +let x := 1.5; +let y := 0.11; + +## A suffix +suffix zork; +let C2.zork := 5; + + * + */ + + +#endif // NLSOL_EX_C_MODEL_H diff --git a/nl-writer2/examples/nlsol_ex.cc b/nl-writer2/examples/cpp/nlsol_ex.cc similarity index 100% rename from nl-writer2/examples/nlsol_ex.cc rename to nl-writer2/examples/cpp/nlsol_ex.cc diff --git a/nl-writer2/examples/nlsol_ex_mdl.h b/nl-writer2/examples/cpp/nlsol_ex_mdl.h similarity index 100% rename from nl-writer2/examples/nlsol_ex_mdl.h rename to nl-writer2/examples/cpp/nlsol_ex_mdl.h diff --git a/nl-writer2/examples/nlsol_ex_nl.h b/nl-writer2/examples/cpp/nlsol_ex_nl.h similarity index 100% rename from nl-writer2/examples/nlsol_ex_nl.h rename to nl-writer2/examples/cpp/nlsol_ex_nl.h diff --git a/nl-writer2/examples/nlsol_ex_sol.h b/nl-writer2/examples/cpp/nlsol_ex_sol.h similarity index 100% rename from nl-writer2/examples/nlsol_ex_sol.h rename to nl-writer2/examples/cpp/nlsol_ex_sol.h diff --git a/nl-writer2/include/api/c/nl-feeder2.h b/nl-writer2/include/api/c/nl-feeder2.h new file mode 100644 index 000000000..41ba204d3 --- /dev/null +++ b/nl-writer2/include/api/c/nl-feeder2.h @@ -0,0 +1,18 @@ +/** + * C API: extern "C" wrapper for the NLFeeder2 interface + * + */ + +#ifndef NLFEEDER2_H +#define NLFEEDER2_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // NLFEEDER2_H diff --git a/nl-writer2/src/c_api.cc b/nl-writer2/src/c_api.cc new file mode 100644 index 000000000..f8671b95c --- /dev/null +++ b/nl-writer2/src/c_api.cc @@ -0,0 +1,6 @@ +/** + * C API implementation + * + */ + +#include "api/c/nl-feeder2.h"