123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- #import std
- #import nat
- #import flo
- #comment -[
- This module contains functions and data structures for solving linear
- programming problems by way of a more convenient interface than direct
- invocation of the virtual machine's library functions, because it
- allows symbolic names for variables, positive and negative solutions,
- and costs proportional to magnitudes. A few matrix operations are also
- included. Replacement functions implemented in virtual code are
- provided in case the virtual machine doesn't have the required
- libraries (lapack, umf, and pcx or glpk) but performance and memory
- efficiency will suffer considerably.
- Copyright (C) 2007-2010 Dennis Furey]-
- #library+
- #optimize+
- ------------------------------------------------ data structures -----------------------------------------------------------
- linear_system ::
- lower_bounds %geAS # the minimum allowed value for each variable in the solution
- upper_bounds %geAS # the maximum allowed value for each variable in the solution
- costs %geAS # the proportional contribution of each variable to the objective function to be minimized
- taxes %geAS # the proportional contribution of the magnitude of each variable to the objective function
- equations %egXSeXS # the equations to be satisfied in the form <(<(coefficient,name)..>,total)..>
- integers %gS # the variables constrained to integer values
- binaries %gS # the variables constrained to binary values
- derivations %egXSm # <name: <(coefficient,name)..>> original variables expressed in terms of standardized variables
- ------------------------------------------- general operations on matrices -------------------------------------------------
- mmult = iprod*rlD*rK7lD # matrix multiplication
- #library-
- upper_triangular = # takes a matrix and transforms it to upper triangular form by row reductions
- ~&a^& (~&aitB?\~&a ^rlhPlthS2rpCB/~&a ~&fattS2R)^J/~&f ~&a; (not fleq+ abs~~)-<&h; (fleq/eps+ abs+ ~&hh)&& -+
- :^/~&h ~&htPtD; * :/0.+ minus^*p/~&rt times*+ ~&rhPlD,
- :^\~&t ~&h; :/1.+ vid*+ ~&htD+-
- #library+
- msolve = # takes a square matrix and a vector to a vector using gauss jordan elimination with pivoting
- lapack.|dgesvx -+
- ~&i&& ~&xzS+ ~&a^& :^(~&ah,^p/~&athS ~&fattS2R)^J/~&f ~&a; :^/~&h ~&htD; * minus^*p/~&r times*+ ~&rhPlD,
- ~&plrNCTS; ~&iyxPzNCTSxPB+ upper_triangular+-
- minverse = ~&K7+ msolve^*D/~& ^DlSzyCK9\~& :/1.+ 0.!*+ ~&t
- sparso = # storage efficient solution of systems of linear equations in sparse matrix form
- %nWeXLeLXMk; umf.|di_a_trp msolve^\~&r ^DrlHS/iol+~&r ~&l; |=≪ nleq-<&hll; * *+ -:0.!+ ~&lrPrXS
- ------------------------------------------- arbitrary precision versions ---------------------------------------------------
- mp_solve = # same as msolve but a lot slower and for mpfr (arbitrary precision) numbers
- -+
- ~&i&& ~&xzS+ ~&a^& :^(~&ah,^p/~&athS ~&fattS2R)^J/~&f ~&a; :^/~&h ~&htD; * mpfr..sub^*p/~&r mpfr..mul*rhPlD,
- ~&plrNCTS; ~&iyxPzNCTSxPB+ ~&a^& -+
- ~&aitB?\~&a ^rlhPlthS2rpCB/~&a ~&fattS2R,
- ^J/~&f ~&a; (not mpfr..lessequal_p+ mpfr..abs~~)-<&h; (mpfr..lessequal_p/1E-16+ mpfr..abs+ ~&hh)&& -+
- :^/~&h ~&htPtD; * :/0E0+ mpfr..sub^*p/~&rt mpfr..mul*rhPlD,
- :^\~&t ~&h; :/1E0+ mpfr..vid*+ ~&htD+-+-+-
- mp_sparso = # replacement function for sparso with mpfr numbers, but no advantage in storage efficiency
- %nWEXLELXMk; mp_solve^\~&r ^DrlHS/iol+~&r ~&l; |=≪ nleq-<&hll; * *+ -:0E0!+ ~&lrPrXS
- ------------------------------------------------- linear programming functions ---------------------------------------------
- standard_form = # removes finite and negative bounds and unsigned costs from linear systems by variable substitutions
- -+
- linear_system$l[
- taxes: <>!,
- upper_bounds: <>!,
- lower_bounds: :0.^*js\~&rlnS --+ ~/&rlmrSPSL &l.equations.&lrSPSL,
- costs: -+
- ^A(~&hn,plus:-0.+ ~&mS)*+ |=&n+ ^T(
- ~&l; *= ||~&lNC ~&lmPrD; * ^A/~&rr times+~&lrlPX,
- ~&r; *= ||~&lNC ~&lmPrD; * ^A/~&rr times^/~&l abs+~&rl),
- %seAesXLXLWMk^H\~&l.(costs,taxes) ~*+ ^/~&+ ~&n;+ -:0!+ ~&rl+-,
- equations: (^\~&r ~&l~<{0.,-0.}*~+ ~&l)^*T\~&rr -+
- * %esXLeXMk+ ^\~&rr ~&lrlPDlrHS; %esXLMk+ *= ||~&lNC ~&llPrD; * ^\~&rr times+~&lrlPX,
- ^D\~&l.equations ^/~&+ ~&r;+ -:0!+ ~&rl+-,
- derivations: --+ ~/&l.derivations &rl],
- ^/~& -+
- %esXLmesXLeXLXMk+ ~&lSLPrSLPX+ * -?
- ~&rml;fleq/0.: ~&NiX+ ~&L+ <.
- ~&rml~=0.&& ^iNC\~&rml ^H/(:^/~&h+ ~&t;+ ~&l) <.~&/1.,~&/-1.+ --'_bloat'>+ ~&rn,
- ~&rmr~=inf&& ^iNC\~&rmr ^H/(:^/~&h+ ~&t;+ ~&l) <.~&/1.,~&/1.+ --'_headroom'>+ ~&rn>,
- ~&rmr;fleq\0.: ^/(^ANC/~&rn ^H/~&l ~&iNC/-1.+ --'_complement'+ ~&rn) ~&L+ <.
- ~&rmr~=0.&& ^iNC\negative+~&rmr ^H/~&l <.~&/1.,~&/-1.+ --'_bloat'>+ --'_complement'+ ~&rn,
- ~&rml~=ninf&& ^iNC\negative+~&rml ^H/~&l <.~&/1.,~&/1.+ --'_headroom'>+ --'_complement'+ ~&rn>,
- ^/(^ANC/~&rn ^H/~&l <.~&/1.+ --'_credit',~&/-1.+ --'_debit'>+ ~&rn) ~&L+ <.
- ~&rml~=ninf&& ^iNC\~&rml ^H/~&l <.~&/1.+ --'_credit',~&/-1.+ --'_debit',~&/-1.+ --'_bloat'>+ ~&rn,
- ~&rmr~=inf&& ^iNC\~&rmr ^H/~&l <.~&/1.+ --'_credit',~&/-1.+ --'_debit',~&/1.+ --'_headroom'>+ ~&rn>?-,
- %fOseWAXLMk^D((~&?\~&! *+ !; ^\~&; //+ ~&rrPlw->r &rr:= :/``+ ~&rr)+ ~&lrlPU; *~ -=/`_,~&rr)^(
- ~derivations.&nmrSPCSLs,
- ^H\~equations.&lrSPSLs ^/~&+ (*+ ^llPlrPrXA)^\-:inf!+~upper_bounds ^/~&+ -:ninf!+ ~lower_bounds)+-,
- upper_bounds:= ^Ts(~&DrlAS/1.+ ~binaries,^niK12/~upper_bounds ~binaries),
- lower_bounds:= ^Ts(~&DrlAS/0.+ ~binaries,^niK12/~lower_bounds ~binaries)+-
- solution = # takes a linear system to a result of type %em
- gint~&lnPrE^\~equations.&lSLrS standard_form; -+
- %emMk^T\~&r ~&m~<{0.,-0.}*~+ ^DrnPlrmPHAS\~&l %fMk+ plus:-0.++ *+ times^/~&l+ ~&r;+ -:0.!+ ~&r,
- %esXLmemXMk^/~&l.derivations %emMk^DlrlPHrrPAS/~&rrr %neXLMk+ mip_solver^(
- %nLWMk^H/~*@rrl ~&l.(binaries,integers),
- %eLnWeXLeLXXMk^(
- %eLMk+ (#:/0.+#) ~&rS+ %neXLMk+ (nleq-<&l)^DlrnPHrmPXS/~&rrl %emMk^T(~&r,gdif~&EbnPO)^\~&l.costs ~&A\*0.+ ~&rl,
- ^\%eLMk+~&l.equations.&rS %nWeXLMk+ ~&DSLlrlPXrrPXS+ num+ nleq-<&l*+ ~&DlrrPHrlPXSPS^D/~&rrl ~&l.equations.&lS)),
- _linear_system%sSfOWXXMk^/~& ~equations.&lSLrSs; ^/~& -:0!~~+ ~&rlXSiX+ num+-
- mip_solver = # takes an argument ((b,i),c,m,y) of type %nLWeLnWeXLeLXXX to a result of type %neXL
- ~&Y?l\lp_solver@r ~&ll?\lpsolve..iform@lrPrX ~&lr?\lpsolve..bform@llPrX lpsolve..biform
- lp_solver = # lower level interface, takes an argument (c,m,y) of type %eLnWeXLeLXX to a result of type %neXL
- lpsolve.|stdform glpk.|simplex glpk.|interior replacement_lp_solver
- replacement_lp_solver = # solves it the hard way without calling an external library function
- ^|(num,~&); -+
- %fnWeXLLneXLXXnLLXMk; @NiX ~&rr->lilB ^\~&rlrtPXP @lrlrhPXPX %neXLeXZfnWeXLLneXLXXnLXXCk -+
- ~&r?\~&l ~&l?\~&r %neXLeXZWMk; lesser fleq@br,
- ^/~&l (%fneXLXMk; ~&r&& ^/~&r plus:-0.+ times*DlrlPHrrPXS)^/~&rll -+
- eql+~&llPrX&& eql+~&lrlrPSs3rX&& %nLnWeXLXneXLXMk; -+
- %neXLMk+ -&~&r; ~&i&& all fleq/0.,~&p&-^|/~& sparso,
- %nLnWeXLeLXXMk^/~&ll ^\~&rrS ^H\~&lr @rlSPllPX *+ ^\~&r+ ~&l;+ ^|+ ~~ -$^/~& iol+-,
- (^/~&l ~&rlrPX; gint~&llPrll2E)^\~&rlrr ~&rrPrlrl3X; %nLnWeXLXMk^/~&l ~&L+ ~&rhlr3lw~|+-+-,
- ^(^/-:+~&l ^\num+~&rr |=&lr+ ~&rl,leql?rrPlX\<'bad linear program'>!% %nLLMk+ choices^/~&llS length+ ~&rr)+-
|