Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast panoc implementation #5

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions demos/demo_panoc.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
% Only use this demo after installing the panoc library. This is only
% supported on Windows right now. Run ./external_library/setup.m to
% install panoc.

clear all;
%%
f=@rosen;
g=indBox(-4,4);
x0=[0;0];
aff=0; % not supported with panoc
opts.solver='panoc';
opts.tol=1e-12;
opts.maxit=200;

% g.name='blah'; % uncomment this line if you want to use the Matlab function constraint
tic
out = forbes(f, g, x0, aff, [], opts) % this problem should take 20 iterations
toc

% double check the results
if(out.iterations~=20)
disp(['Error: not solved in 20 iterations as expected but in ' ...
num2str(out.iterations) 'iterations'] );
end

theoretical_solution = [1;1];
if(norm(out.x-theoretical_solution)>opts.tol)
disp(['Error: solution not [1;1] as expected but[' ...
num2str(out.x(1)) ';' num2str(out.x(2)) ']' ]);
end
9 changes: 9 additions & 0 deletions demos/rosen.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
function [function_value,gradient] = rosen(initial_point)
a=1;
b=100;
function_value =(a-initial_point(1))^2 + b*(initial_point(2)-initial_point(1))^2;

if nargout > 1
gradient = [-2*(a-(b+1)*initial_point(1)+b*initial_point(2)); 2*b*(initial_point(2)-initial_point(1)) ];
end
end
1 change: 1 addition & 0 deletions external_library/forbes_panoc/bin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
panoc.mexw64
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions external_library/forbes_panoc/bin/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# build folder panoc
This folder contains binary's of the draft panoc library: https://github.com/Zilleplus/draf_panoc.
28 changes: 28 additions & 0 deletions external_library/setup.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
% install external libs
lib_path = pwd;

%% install panoc


if ismac
disp('Using mex interface Mac os');
mex_file_location=fullfile(lib_path,'forbes_panoc','bin','PANOC_Mac64_clang.mexmaci64');
mex_file_destination = fullfile(lib_path,'forbes_panoc','bin','panoc.mexmaci64');
elseif isunix
disp('Using mex interface Linux');
mex_file_location=fullfile(lib_path,'forbes_panoc','bin','PANOC_linux64_gcc.mexa64');
mex_file_destination = fullfile(lib_path,'forbes_panoc','bin','panoc.mexa64');
elseif ispc
disp('Using mex interface Windows');
mex_file_location=fullfile(lib_path,'forbes_panoc','bin','panoc_Windows64VStudio.mexw64');
else
disp('Platform not supported')
end
copyfile(mex_file_location,mex_file_destination);


%% add paths to path and save
addpath(fullfile(lib_path,'forbes_panoc','bin'));
addpath(fullfile(lib_path,'src_Matlab'));
savepath;% write away path variable

1 change: 1 addition & 0 deletions external_library/src_Matlab/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#Matlab code that links external library's with forbes
45 changes: 45 additions & 0 deletions external_library/src_Matlab/solve_panoc.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function [ out ] = solve_panoc( f, g ,opt , intial_solution )
%SOLVE_PANOC Solve problem with panoc lib

if(~isfield(g,'name'))
g.name='costum';
end

% parse the options into the panoc format
problem.dimension = length(intial_solution);

if(strcmp(g.name,'box'))
problem.constraint_type = 'box';

problem.upper_bound=g.upper_bound;
problem.lower_bound=g.lower_bound;
else % unknown function, use the matlab version provided by the user
disp(['WARNING: No C implementation found of the constraint ' ...
'function using the matlab implementation,'...
' this may impact performance.']);
problem.constraint_type = 'costum';

% convert the function into the right format and set gamma=0
g_function = g.makeprox();
constraint = @(x,gamma) g_function(x,gamma);
problem.constraint = constraint;
end

solver_params.tolerance = opt.tol;
solver_params.buffer_size = 20;
solver_params.max_iterations = opt.maxit;

% Solve the problem with panoc,
% copy over by value the initial position.
solution=zeros(problem.dimension,1);
for i=1:problem.dimension
solution(i)=intial_solution(i);
end

panoc('init',problem,solver_params);
number_of_iterations = panoc('solve',solution,f);
panoc('cleanup');

out.x=solution;
out.iterations=number_of_iterations;
end
44 changes: 25 additions & 19 deletions forbes.m
Original file line number Diff line number Diff line change
Expand Up @@ -105,27 +105,33 @@
if nargin < 4, aff = []; end
if nargin < 5, constr = []; end
if nargin < 6, opt = []; end

if(strcmp(opt.solver,'panoc'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In principle zerofpr2 should be renamed panoc at some point... (See #1, although I'm not sure if and when this reorganization will be finalized). Just to avoid conflicts I would try to use here strings for the solver selection that make clear that one is selecting an "external" one.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it should be clear that it's a external one. It is also the reason why i put it in a separate folder. It leads to an other question, should we even include the library inside ForBes or should we put it as a separate project and put it as optional dependency. And just leave the Matlab code that interfaces the two in place?

I don't like mex files either, nmpc-codegen doesn't use mex files but calllib and Cmake. But because i needed callback's here (c-code call's Matlab functions) i had to do it with a mex file.

I have an older mac at home, i will install Matlab 2016a on it and compile it. Considering compiled Mex files are forward (NOT backward) compatible you should be able to run it. I think binary's are probably the best way to go, it avoids users having to compile it themselves.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. Maybe it's a good idea to keep this in a separate, and maybe provide it with its own MATLAB interface. The purpose of ForBES was that of having algorithms and functions and use them together, if a method implementation works with its own function library and options, then its probably cleaner to think about a MATLAB interface of its own...

What do you think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It already has its own Matlab interface (the mex file) i might add a slightly more friendly interface later on. The MATLAB code added in forbes here allows the usage of all the forbes constraint functions. The nice thing about this is, that you can switch between a C or MATLAB implementation by only changing the name of the solver.

Or maybe we can add a option "speedy" instead, that is by default false, but if true, forbes uses the C implementation if it is available. (so no overlap with zerofpr2)

So i would suggest: leave the clue between the library's in place: https://github.com/Zilleplus/ForBES/blob/master/external_library/src_Matlab/solve_panoc.m

But we don't put these binary files in here : https://github.com/Zilleplus/ForBES/tree/master/external_library/forbes_panoc/bin

We could call it CPanoc or so and add it in a repo on github. If you want to use a speedy library, you will need to install it. Right now its here: https://github.com/Zilleplus/draf_panoc

It's very doable to add a zerofpr.c to my library and with a little bit of code, you have the zerofpr and panoc solver in C. In that case the name CPanoc makes no sense.

disp('WARNING: Using external lib, not all options are supported here.');
% constr is not supported by panoc, ignore it
out=solve_panoc( fs, gs ,opt , init );
else
[prob, id] = Process_Problem(fs, gs, init, aff, constr);
opt = Process_Options(opt);
lsopt = Process_LineSearchOptions(opt);

[prob, id] = Process_Problem(fs, gs, init, aff, constr);
opt = Process_Options(opt);
lsopt = Process_LineSearchOptions(opt);

preprocess = toc(t0);
preprocess = toc(t0);

out_solver = opt.solverfun(prob, opt, lsopt);
out_solver = opt.solverfun(prob, opt, lsopt);

out.message = out_solver.message;
out.flag = out_solver.flag;
if id == 1
out.x = out_solver.x;
else
[out.x1, out.x2, out.z] = prob.Get_DualPoints(out_solver.x, out_solver.gam);
out.y = out_solver.x;
out.message = out_solver.message;
out.flag = out_solver.flag;
if id == 1
out.x = out_solver.x;
else
[out.x1, out.x2, out.z] = prob.Get_DualPoints(out_solver.x, out_solver.gam);
out.y = out_solver.x;
end
out.solver = out_solver;
out.prob = prob;
out.opt = opt;
out.lsopt = lsopt;
out.preprocess = preprocess;
out.time = toc(t0);
end
out.solver = out_solver;
out.prob = prob;
out.opt = opt;
out.lsopt = lsopt;
out.preprocess = preprocess;
out.time = toc(t0);
end
3 changes: 3 additions & 0 deletions library/indBox.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
function obj = indBox(lower, upper)
obj.isConvex = 1;
obj.makeprox = @() @(x, gam) call_indBox_prox(x, lower, upper);
obj.name='box';
obj.upper_bound=upper;
obj.lower_bound=lower;
end

function [prox, val] = call_indBox_prox(x, lower, upper)
Expand Down