diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 9674e2a1..1a5ca7ad 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -3,9 +3,9 @@ name: Linux Build and Tests on: workflow_dispatch: push: - branches: [ main ] + branches: [ main, dev ] pull_request: - branches: [ main ] + branches: [ main, dev ] jobs: @@ -43,3 +43,25 @@ jobs: run: | cd build make test + + pycoek_pybind11: + runs-on: ubuntu-latest + needs: coek-build-and-test-with-tpls + steps: + - uses: actions/checkout@v2 + - name: run cmake + run: | + mkdir build + cd build + cmake -Dbuild_all=ON ../lib/coek + - name: build + run: | + cd build + make tpls + make + - name: build pycoek_pybind11 + run: | + cd build + cmake -Dwith_pybind11=ON ../lib/coek + make + diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 00000000..80159b06 --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,8 @@ +# ChangeLog + +Here we list changes of Coek. More detailed information about incremental changes can be found in the +[commit history](https://github.com/sandialabs/coek/commits). + +## 1.0 + +Initial public release. diff --git a/lib/coek/coek/model/compact_model.cpp b/lib/coek/coek/model/compact_model.cpp index ca08c50f..91a939a9 100644 --- a/lib/coek/coek/model/compact_model.cpp +++ b/lib/coek/coek/model/compact_model.cpp @@ -73,7 +73,7 @@ VariableMap& CompactModel::add_variable(VariableMap& vars) { repn->variables.insert(repn->variables.end(), vars.begin(), vars.end()); -repn->variable_names.insert(repn->variable_names.end(), varray.variables.size(), ""); +repn->variable_names.insert(repn->variable_names.end(), vars.size(), ""); /* auto end = vars.end(); for (auto it=vars.begin(); it != end; ++it) { @@ -88,7 +88,7 @@ VariableMap& CompactModel::add_variable(VariableMap&& vars) { repn->variables.insert(repn->variables.end(), vars.begin(), vars.end()); -repn->variable_names.insert(repn->variable_names.end(), varray.variables.size(), ""); +repn->variable_names.insert(repn->variable_names.end(), vars.size(), ""); /* auto end = vars.end(); for (auto it=vars.begin(); it != end; ++it) { @@ -103,7 +103,7 @@ VariableArray& CompactModel::add_variable(VariableArray& vars) { repn->variables.insert(repn->variables.end(), vars.begin(), vars.end()); -repn->variable_names.insert(repn->variable_names.end(), varray.variables.size(), ""); +repn->variable_names.insert(repn->variable_names.end(), vars.size(), ""); /* auto end = vars.end(); for (auto it=vars.begin(); it != end; ++it) { @@ -118,7 +118,7 @@ VariableArray& CompactModel::add_variable(VariableArray&& vars) { repn->variables.insert(repn->variables.end(), vars.begin(), vars.end()); -repn->variable_names.insert(repn->variable_names.end(), varray.variables.size(), ""); +repn->variable_names.insert(repn->variable_names.end(), vars.size(), ""); /* auto end = vars.end(); for (auto it=vars.begin(); it != end; ++it) { diff --git a/lib/coek/coek/solvers/gurobi/gurobi.cpp b/lib/coek/coek/solvers/gurobi/gurobi.cpp index 8b51232b..ed7749df 100644 --- a/lib/coek/coek/solvers/gurobi/gurobi.cpp +++ b/lib/coek/coek/solvers/gurobi/gurobi.cpp @@ -118,34 +118,31 @@ gmodel = new GRBModel(*env); assert(_model->objectives.size() == 1); // Add Gurobi variables -for (std::vector::iterator it=_model->variables.begin(); it != _model->variables.end(); ++it) { - coek::VariableTerm* v = it->repn; - if (v->fixed) { - ; - } - else { - double lb = v->lb->eval(); - double ub = v->ub->eval(); - if (v->binary) - x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_BINARY); - else if (v->integer) - x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_INTEGER); - else { - if (ub >= 1e19) { - if (lb <= -1e19) - x[ v->index ] = gmodel->addVar(-GRB_INFINITY, GRB_INFINITY, 0, GRB_CONTINUOUS); - else - x[ v->index ] = gmodel->addVar(lb, GRB_INFINITY, 0, GRB_CONTINUOUS); - } - else { - if (lb <= -1e19) - x[ v->index ] = gmodel->addVar(-GRB_INFINITY, ub, 0, GRB_CONTINUOUS); - else - x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_CONTINUOUS); +for (auto& var : _model->variables) { + coek::VariableTerm* v = var->repn; + if (not v->fixed) { + double lb = v->lb->eval(); + double ub = v->ub->eval(); + if (v->binary) + x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_BINARY); + else if (v->integer) + x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_INTEGER); + else { + if (ub >= 1e19) { + if (lb <= -1e19) + x[ v->index ] = gmodel->addVar(-GRB_INFINITY, GRB_INFINITY, 0, GRB_CONTINUOUS); + else + x[ v->index ] = gmodel->addVar(lb, GRB_INFINITY, 0, GRB_CONTINUOUS); + } + else { + if (lb <= -1e19) + x[ v->index ] = gmodel->addVar(-GRB_INFINITY, ub, 0, GRB_CONTINUOUS); + else + x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_CONTINUOUS); + } } } } -} gmodel->update(); @@ -175,8 +172,6 @@ if (nobj > 1) { try { coek::QuadraticExpr repn; for (auto& con : model.repn->constraints) { - //crepn[i].collect_terms(_model->constraints[i]); - //Constraint c = cval->expand(); add_gurobi_constraint(gmodel, con, x, repn); } } @@ -200,11 +195,11 @@ try { // TODO: Is there a string description of the solver status? // Collect values of Gurobi variables - for (std::vector::iterator it=_model->variables.begin(); it != _model->variables.end(); ++it) { + for (auto& var : _model->variables) { coek::VariableTerm* v = it->repn; - if (!(v->fixed)) { - v->set_value( x[v->index].get(GRB_DoubleAttr_X) ); - } + if (not v->fixed) { + v->set_value( x[v->index].get(GRB_DoubleAttr_X) ); + } } } } @@ -236,8 +231,8 @@ assert(model.objectives.size() == 1); std::cout << "BUILDING GUROBI MODEL" << std::endl << std::flush; // Add Gurobi variables -for (std::vector::iterator it=model.variables.begin(); it != model.variables.end(); ++it) { - coek::VariableTerm* v = it->repn; +for (auto& var : model->variables) { + coek::VariableTerm* v = var->repn; double lb = v->lb->eval(); double ub = v->ub->eval(); if (v->binary) @@ -363,33 +358,30 @@ if (initial_solve()) { assert(_model->objectives.size() == 1); // Add Gurobi variables - for (std::vector::iterator it=_model->variables.begin(); it != _model->variables.end(); ++it) { - coek::VariableTerm* v = it->repn; - if (v->fixed) { - ; - } - else { - double lb = v->lb->eval(); - double ub = v->ub->eval(); - if (v->binary) - x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_BINARY); - else if (v->integer) - x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_INTEGER); - else { - if (ub >= 1e19) { - if (lb <= -1e19) - x[ v->index ] = gmodel->addVar(-GRB_INFINITY, GRB_INFINITY, 0, GRB_CONTINUOUS); - else - x[ v->index ] = gmodel->addVar(lb, GRB_INFINITY, 0, GRB_CONTINUOUS); - } - else { - if (lb <= -1e19) - x[ v->index ] = gmodel->addVar(-GRB_INFINITY, ub, 0, GRB_CONTINUOUS); - else - x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_CONTINUOUS); - } - } - } + for (auto& var : _model->variables) { + coek::VariableTerm* v = var->repn; + if (not v->fixed) { + double lb = v->lb->eval(); + double ub = v->ub->eval(); + if (v->binary) + x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_BINARY); + else if (v->integer) + x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_INTEGER); + else { + if (ub >= 1e19) { + if (lb <= -1e19) + x[ v->index ] = gmodel->addVar(-GRB_INFINITY, GRB_INFINITY, 0, GRB_CONTINUOUS); + else + x[ v->index ] = gmodel->addVar(lb, GRB_INFINITY, 0, GRB_CONTINUOUS); + } + else { + if (lb <= -1e19) + x[ v->index ] = gmodel->addVar(-GRB_INFINITY, ub, 0, GRB_CONTINUOUS); + else + x[ v->index ] = gmodel->addVar(lb, ub, 0, GRB_CONTINUOUS); + } + } + } } gmodel->update(); @@ -398,9 +390,9 @@ if (initial_solve()) { int nobj=0; try { coek::QuadraticExpr orepn; - for (auto it=model.repn->objectives.begin(); it != model.repn->objectives.end(); ++it) { - Expression tmp = it->expr(); - add_gurobi_objective(gmodel, tmp, it->sense(), x, orepn); + for (auto& obj : model.repn->objectives) { + Expression tmp = obj->expr(); + add_gurobi_objective(gmodel, tmp, obj->sense(), x, orepn); nobj++; } } @@ -419,10 +411,8 @@ if (initial_solve()) { // Add Gurobi constraints try { coek::QuadraticExpr repn; - for (auto it=_model->constraints.begin(); it != _model->constraints.end(); ++it) { - //crepn[i].collect_terms(_model->constraints[i]); - //Constraint c = cval->expand(); - add_gurobi_constraint(gmodel, *it, x, repn); + for (auto& con : model->constraints) { + add_gurobi_constraint(gmodel, con, x, repn); } } catch (GRBException e) { diff --git a/lib/coek/coek/solvers/ipopt/ipopt_capi.cpp b/lib/coek/coek/solvers/ipopt/ipopt_capi.cpp index b9c33b84..c3603621 100644 --- a/lib/coek/coek/solvers/ipopt/ipopt_capi.cpp +++ b/lib/coek/coek/solvers/ipopt/ipopt_capi.cpp @@ -1,6 +1,7 @@ #include #include +#include "coek/util/sequence.hpp" #include "coek/api/expression.hpp" #include "coek/api/objective.hpp" #include "coek/api/constraint.hpp" @@ -429,8 +430,8 @@ if (start_from_last_x) { this); } else { - for (size_t i=0; iperform_solve(); int IpoptSolver::resolve() { +#ifdef DEBUG auto start = std::chrono::high_resolution_clock::now(); +#endif if (not initial_solve()) model->reset(); @@ -36,9 +38,11 @@ else repn->set_start_from_last_x(false); int status = repn->perform_solve(); +#ifdef DEBUG auto curr = std::chrono::high_resolution_clock::now(); std::chrono::duration diff = curr-start; -//std::cout << "Time to solve: " << diff.count() << " s\n"; +std::cout << "Time to solve: " << diff.count() << " s\n"; +#endif return status; } diff --git a/lib/coek/examples/invquad_array_resolve.cpp b/lib/coek/examples/invquad_array_resolve.cpp index 78daa0c7..febb1df5 100644 --- a/lib/coek/examples/invquad_array_resolve.cpp +++ b/lib/coek/examples/invquad_array_resolve.cpp @@ -7,19 +7,19 @@ void invquad_array_resolve() coek::Model m; size_t N=5; -std::vector p(N); +auto p = coek::parameter("p", N); for (auto& param : p) param.value(0.5); // Initialize variables and add them to the model -auto x = coek::variable("x", p.size()) +auto x = coek::variable("x", N) .bounds(-10,10).value(0.0); m.add(x); // Create objective and add it to the model auto e = coek::expression(); -for (size_t i : coek::range(p.size())) - e -= (x(i)-p[i])*(x(i)-p[i]); +for (size_t i : coek::range(N)) + e -= (x(i)-p(i))*(x(i)-p(i)); m.add_objective( e ); // Optimize the model @@ -30,13 +30,13 @@ solver.load(nlp); solver.resolve(); // x^*_i = -10 -for (size_t i=0; i p(10); +auto p = coek::parameter("p", N); for (auto& param : p) param.value(0.5); @@ -18,8 +18,8 @@ m.add(x); // Create objective and add it to the model auto e = coek::expression(); -for (size_t i : coek::range(p.size())) - e -= (x(i)-p[i])*(x(i)-p[i]); +for (size_t i : coek::range(N)) + e -= (x(i)-p(i))*(x(i)-p(i)); m.add_objective( e ); // Optimize the model @@ -29,6 +29,6 @@ solver.set_option("print_level", 0); solver.solve(nlp); // x^*_i = -10 -for (size_t i=0; i& p); coek::Model invquad_array(std::vector& p); std::vector invquad_soln_5 {-10,-10,-10,-10,-10}; -coek::Model invquad_array_solve(); -coek::Model invquad_array_resolve(); +void invquad_array_solve(); +void invquad_array_resolve(); void check(std::vector& variables, std::vector& soln) @@ -90,6 +90,7 @@ if (solver.available()) { check(m.get_variables(), invquad_soln_5); } +/* WHEN( "resolve - Warm Start" ) { auto m = invquad_vector(p); @@ -111,6 +112,7 @@ if (solver.available()) { check(m.get_variables(), invquad_soln_5); } +*/ } SECTION( "invquad_array" ) { @@ -126,7 +128,6 @@ if (solver.available()) { check(m.get_variables(), invquad_soln_5); } -/* WHEN( "resolve - Same start" ) { auto m = invquad_array(p); @@ -157,6 +158,7 @@ if (solver.available()) { check(m.get_variables(), invquad_soln_5); } +/* WHEN( "resolve - Warm Start" ) { auto m = invquad_array(p); @@ -183,12 +185,9 @@ if (solver.available()) { WHEN( "invquad_solve" ) { invquad_array_solve(); } - -/* WHEN( "invquad_resolve" ) { invquad_array_resolve(); } -*/ } } else { diff --git a/test/aml_comparisons/CMakeLists.txt b/test/aml_comparisons/CMakeLists.txt index 9db79adf..16f44350 100644 --- a/test/aml_comparisons/CMakeLists.txt +++ b/test/aml_comparisons/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.12) -PROJECT(coek_testmodels) +PROJECT(compare_amls) # # For now, let's just assume we have C++17 @@ -56,11 +56,11 @@ message("-- with_gurobi: ${with_gurobi}") ##################### COEK configuration ##################### if("${coek_dir}" STREQUAL "") - if (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../../coek/build/install) - list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../coek/build/install/lib/cmake/coek") - list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../coek/build/install/lib/cmake/fmt") - list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../coek/build/install/lib64/cmake/coek") - list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../coek/build/install/lib64/cmake/fmt") + if (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../../../lib/coek/build/install) + list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../../lib/coek/build/install/lib/cmake/coek") + list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../../lib/coek/build/install/lib/cmake/fmt") + list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../../lib/coek/build/install/lib64/cmake/coek") + list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../../lib/coek/build/install/lib64/cmake/fmt") endif() else() if(NOT IS_ABSOLUTE ${coek_dir})