[maxima] lagrange multiplier solver
I made Lagrange multiplier solver for maxima.
This can deal matrix without define each element.
diff_level_by_variables_sub(expression,variables,diff_level):=map(lambda([x],if x=0 then diff_level else (diff_level_by_variables_sub(x,variables,diff_level +1))),map(lambda([x],diff(expression,x,1) ) ,variables )); diff_level_by_variables(expression,variables):=diff_level_by_variables_sub(expression,variables,0); total_diff_level_by_variables(expression,variables):=apply(max,flatten(diff_level_by_variables(expression,variables))); is_const_or_linear_for_variables(expression,variables):=is(total_diff_level_by_variables(expression,variables)<2); linear_aproximate_for_variables(expression,variables):=map(lambda([x],if is_const_or_linear_for_variables(x,variables) then x else 0) ,expand(expression)); _lagrange_multipliers_:makelist(concat(_lagrange_multiplier_,k),k,1,10); declare(''_lagrange_multipliers_,scalar); lagrange_multiplier_solve(obj_fn,eqs,variables,constant_coordinate_diff_mod_matrix):=block( [lagrangian ,lagrangian_diffs ,solved_lagrangian_for_variables ,solved_lagrangian_for_variables_without_lagrange_multiplier ,eqs_lagrange_multipliers ,eqs_lagrange_multipliers_factoed ,solved_lagrange_multiplier ,neqs:length(eqs) ,lagrange_multipliers:makelist(_lagrange_multipliers_[k],k,1,length(eqs)) ], dotscrules:true, dotexptsimp:false, dotassoc:false, disp(lagrangian:obj_fn-lagrange_multipliers . eqs), disp(lagrangian_diffs:makelist(subst(constant_coordinate_diff_mod_matrix[k].variables[k]=variables[k],expand(constant_coordinate_diff_mod_matrix[k].diff(lagrangian,variables[k]))),k,1,length(variables))), disp(solved_lagrangian_for_variables:solve(lagrangian_diffs,variables)), disp(eqs_lagrange_multipliers:subst(solved_lagrangian_for_variables,eqs)), /*need change for other problem*/ eqs_lagrange_multipliers_factoed:eqs_lagrange_multipliers, disp(solved_lagrange_multiplier:solve(eqs_lagrange_multipliers_factoed,lagrange_multipliers)), solved_lagrangian_for_variables_without_lagrange_multiplier:subst(solved_lagrange_multiplier, solved_lagrangian_for_variables) /*,[solved_lagrangian_for_variables_without_lagrange_multiplier,[solved_lagrangian_for_variables,solved_lagrange_multiplier]]*/ );
Usage
Let derivate formulation in
K. Kanatani, Y. Sugaya, and H. Niitsuma, Triangulation from two views revisited: Hartley-Sturm vs. optimal correction
Proceedings of the 19th British Machine Vision Conference (BMVC'08), September 2008, Leeds, U.K., pp. 173--182.
http://www.suri.cs.okayama-u.ac.jp/~kanatani/papers/bmtriang.pdf
/*usage*/ /* equation(9) <= linear_aproximate_for_variables( (8) ,[dx,dy] solve min (8) sub (9) 3rd coordinate is constant dx/dx3=0 dy/dy3=0 => Pk.dx=dx where Pk=diag([1,1,0]) */ result1:lagrange_multiplier_solve(dx.dx+dy.dy,[ /* linear_aproximate_for_variables(inprod((x-dx),F.(y-dy)),[dx,dy])*/ linear_aproximate_for_variables(((x-dx).F.(y-dy)),[dx,dy]) ],[dx,dy],[Pk,Pk]); /*you will see same formulation (18)*/ /*can not deal nonlinear constraint*/ /*lagrange_multiplier_solve(dx.dx+dy.dy,[(x-dx).F.(y-dy)],[dx,dy],[Pk,Pk]);*/ /* equation(24) <= linear_aproximate_for_variables( eq(23) ,[dx,dy] solve min (21) sub (24) 3rd coordinate is constant dxh/dxh3=0 dyh/dyh3=0 => Pk.dx=dx where Pk=diag([1,1,0]) */ lagrange_multiplier_solve( (xt+dxh)^^2+(yt+dyh)^^2 ,[ /*linear_aproximate_for_variables(inprod((xh-dxh),F.(yh-dyh)),[dxh,dyh])*/ linear_aproximate_for_variables((xh-dxh).F.(yh-dyh),[dxh,dyh]) ] ,[dxh,dyh],[Pk,Pk]); /*you will see same formulation (32) */ /* Convert to C using http://www.rbt.his.u-fukui.ac.jp/~naniwa/pub/maxima/cform.lisp */ load("cform.lisp"); result1; load(diag); Pk:diag([1,1,0]); /*kill(Pk,F,x,y)*/ F:genmatrix(lambda([i,j],f[i][j]),3,3 ); x:makelist(x[i],i,1,3); y:makelist(y[i],i,1,3); cform(''(result1[1][1]) );