# ONumerical OCaml library featuring: * Sparse Linear Expressions Functorized module for dealing with linear expressions over any number type and over any variable type (Zarith rationals, floats, integers for numbers and strings for variables are supported out-of-the-box):
module Expression = Expression_f.Make(Str_var)(Float_number);;
let a = Expression.of_assoc_list_and_const
[("x", 1.0), ("y", 1.0)] 0.0;;
let b = Expression.of_assoc_list_and_const
[("x", -1.0), ("z", 3.0)] 5.0;;
Expression.(to_string (a ++ b));;
(* Output: 1 (y) + 3 (z) + 5 *)
* Generic vectors, represented using arrays:
module Vector = Vector_f.Make(Float_number);;
let a = [| 0.0; 3.0; 4.0 |];;
let b = [| 2.0; 8.0; 2.0 |];;
Vector.(to_string (a -- b));;
(* Output: [-2.0 -5.0 2.0] *)
* Generic matrixes represented using arrays:
module Matrix = Matrix_f.Make(Float_number);;
let a = [|
[|2.0; 3.0; 4.0|];
[|1.0; 9.0; 1.0|];
[|0.5; -1.0; 0.0|];
|];;
let b = [|
[|2.0; 3.0; 4.0|];
[|3.0; 6.0; 3.0|];
[|0.5; -1.0; 3.0|];
|];;
Matrix.(to_string (a *** b))
(* Output:
| 15.0 20.0 29.0|
| 29.5 56.0 34.0|
|-2.0 -4.5 1.0|
*)
* Dual Simplex Solver on expressions:
Solves linear optimization problems which are dual-feasible.
module Solver = Opt_solver_f.Make(Str_var)(Float_number)
module Expression = Solver.Expression
let constraints = [
([("x1", -1.0); ("x2", -1.0); ("x3", 2.0)], 3.0);
([("x1", -4.0); ("x2", -2.0); ("x3", 1.0)], 4.0);
([("x1", 1.0); ("x2", 1.0); ("x3", -4.0)], -2.0);
];;
let opt_problem = Solver.of_constraints_and_objective
(List.map constraints ~f:(fun (coeffs, const) -> (
Opt.LessThanZero,
(Expression.of_assoc_list_and_const coeffs const)
)))
(Opt.Maximize
Expression.of_assoc_list_and_const
[("x1", -4.0); ("x2", -2.0); ("x3", -1.0)]
0.0
);;
let Opt.Solution solution = Opt.solve opt_problem;;
solution.primal_var_assignment
(* output: [("x1", 0.0); ("x2", 4.0, "x3", 0.5)] *)
### Sample Application: Balancing Chemical Equations
There is a typical problem in high-school chemistry: balance (add coefficients
to) a reaction equation.
For example we start with a simple equation
H2S + O2 -> H2O + SO2
And we wish to obtain the balanced version
2 H2S + 3 O2 -> 2 H2O + 2 SO2
While for the simple reactions the problem is trivial enough to be given as a
homework, the solution in the general case requires the application of a
simplex method (minimize the sum of all constraints subject to balancing atoms
on left and right hand side and subject to the strict positivity constraint).
Moreover, since we want to minimize the quantity with no negative coefficients
the problem is dual-feasible.
The solution is implemented as a sample application of `ONumerical`, and can
be launched as a standalone executable:
echo "H2S + O2 -> H2O + SO2" | ./chem_balancer.native
2H2S + 3O2 -> 2H2O + 2SO2
### Compiling and Installation
Compiling:
$ make
Installation:
$ make install
To remove:
$ make remove
Running tests:
$ make run_test
Compiling the balancer:
$ make chem_balancer
$ ./chem_balancer # to run
### Dependencies
* `Dolog`
* `OCamlbuild` for complilation
* `Core`
* `Re2`
* `OUnit` if you want to run unit tests
### NOTE
Dual Simplex uses a very inefficient dense representation and is not optimized
for performance.
So are the linear algebra primitives, as they re-create the data-structure
after each operation.