Skip to content

Commit

Permalink
[MEX] alpaqa.version function
Browse files Browse the repository at this point in the history
  • Loading branch information
tttapa committed Nov 14, 2023
1 parent 00959c0 commit 04bd6c5
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 27 deletions.
7 changes: 6 additions & 1 deletion examples/Matlab/getting_started.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[version, build_time] = alpaqa.version

%% Build the problem (CasADi code, independent of alpaqa)
import casadi.*

Expand Down Expand Up @@ -51,8 +53,11 @@
problem, x0, y0, method=solver, params=params);

%% Print the results
disp(stats.status)
disp('Stats:');
disp(stats);
disp(stats.inner);
disp('Solution:');
disp(x_sol);
disp('Multipliers:');
disp(y_sol);
disp(stats.status)
2 changes: 1 addition & 1 deletion interfaces/matlab/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ endif()

# Install the final MEX file
install(FILES $<TARGET_FILE:alpaqa_mex>
"minimize.m" "Problem.m"
"minimize.m" "version.m" "Problem.m"
EXCLUDE_FROM_ALL
COMPONENT mex_interface
DESTINATION "+alpaqa")
18 changes: 9 additions & 9 deletions interfaces/matlab/minimize.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
f = casadi.Function('f', {problem.x', problem.param'}, {problem.f});
g = casadi.Function('g', {problem.x', problem.param'}, {problem.g'});

problem_struct = struct
problem_struct.f = f.serialize()
problem_struct.g = g.serialize()
problem_struct.C_lb = problem.C_lowerbound
problem_struct.C_ub = problem.C_upperbound
problem_struct.D_lb = problem.D_lowerbound
problem_struct.D_ub = problem.D_upperbound
problem_struct.l1_reg = problem.l1_regularization
problem_struct.param = problem.param_value
problem_struct = struct;
problem_struct.f = f.serialize();
problem_struct.g = g.serialize();
problem_struct.C_lb = problem.C_lowerbound;
problem_struct.C_ub = problem.C_upperbound;
problem_struct.D_lb = problem.D_lowerbound;
problem_struct.D_ub = problem.D_upperbound;
problem_struct.l1_reg = problem.l1_regularization;
problem_struct.param = problem.param_value;

[varargout{1:nargout}] = alpaqa.alpaqa_mex('minimize', ...
problem_struct, x0, y0, convertStringsToChars(options.method), params_str);
Expand Down
41 changes: 25 additions & 16 deletions interfaces/matlab/src/alpaqa_mex.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <alpaqa/util/demangled-typename.hpp>
#include <MatlabDataArray/ArrayType.hpp>
#include <alpaqa-version.h>
#include <alpaqa-mex-types.hpp>

#include <mex.hpp>
Expand Down Expand Up @@ -45,35 +46,46 @@ class MexFunction : public matlab::mex::Function {

// Main entry-point for the MEX-file.
void operator()(ArgumentList outputs, ArgumentList inputs) override {
std::u16string command;
// Check arguments
if (inputs.size() < 1) {
if (inputs.size() < 1)
displayError(u"At least one input required.");
}
if (outputs.size() > 3) {
displayError(u"Too many outputs specified.");
}
if (inputs[0].getType() == ArrayType::CHAR) {
command = static_cast<CharArray>(inputs[0]).toUTF16();
} else {
if (inputs[0].getType() != ArrayType::CHAR)
displayError(u"First argument must be a character array.");
}
auto command = static_cast<CharArray>(inputs[0]).toUTF16();

// First argument is a string that determines action to take
using handler_t = void (MexFunction::*)(ArgumentList, ArgumentList);
std::map<std::u16string_view, handler_t> handlers{
{u"minimize", &MexFunction::call_minimize},
{u"version", &MexFunction::call_version},
};
if (auto handler = handlers.find(command); handler != handlers.end())
(this->*handler->second)(outputs, inputs);
else
displayError(u"Invalid command");
}

// Solve the given minimization problem.
void call_version(ArgumentList outputs, ArgumentList) noexcept {
if (outputs.size() > 3)
displayError(u"version returns at most three outputs.");
ArrayFactory factory;
if (outputs.size() >= 1)
outputs[0] = factory.createCharArray(ALPAQA_VERSION_FULL);
if (outputs.size() >= 2)
outputs[1] = factory.createCharArray(alpaqa_build_time);
if (outputs.size() >= 3)
outputs[2] = factory.createCharArray(alpaqa_commit_hash);
}

// Solve the given minimization problem.
void call_minimize(ArgumentList outputs, ArgumentList inputs) try {
using namespace alpaqa::mex;
using nlohmann::json;
if (inputs.size() < 6)
displayError(u"minimize requires six arguments.");
if (outputs.size() > 3)
displayError(u"minimize returns at most three outputs.");
// problem
if (inputs[1].getType() != ArrayType::STRUCT ||
inputs[1].getNumberOfElements() != 1) {
Expand Down Expand Up @@ -119,20 +131,17 @@ class MexFunction : public matlab::mex::Function {
matlab::data::TypedArray<double> x0a = std::move(inputs[2]);
std::vector<double> x0(x0a.begin(), x0a.end());
// y0
if (inputs[3].getType() != ArrayType::DOUBLE) {
if (inputs[3].getType() != ArrayType::DOUBLE)
displayError(u"Fourth argument (y0) must be an array of double.");
}
matlab::data::TypedArray<double> y0a = std::move(inputs[3]);
std::vector<double> y0(y0a.begin(), y0a.end());
// method
if (inputs[4].getType() != ArrayType::CHAR) {
if (inputs[4].getType() != ArrayType::CHAR)
displayError(u"Fifth argument (method) must be a character array.");
}
auto method = utf16to8(static_cast<CharArray>(inputs[4]).toUTF16());
// params
if (inputs[5].getType() != ArrayType::CHAR) {
if (inputs[5].getType() != ArrayType::CHAR)
displayError(u"Sixth argument (params) must be a character array.");
}
auto params_str = utf16to8(static_cast<CharArray>(inputs[5]).toUTF16());
auto opts = json::parse(params_str);

Expand Down
5 changes: 5 additions & 0 deletions interfaces/matlab/version.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function [v, varargout] = version()
%version - Return the alpaqa version, build time, and commit hash.

[v, varargout{1:max(nargout, 1) - 1}] = alpaqa.alpaqa_mex('version');
end

0 comments on commit 04bd6c5

Please sign in to comment.