A type-safe symbolic computing Haskell embeded DSL for solving optimization problems.
Symphony is a standalone language backed by HashedExpression, it somewhat resembles AMPL (but free).
We haven't yet publish it to Cabal (or Homebrew, apt-get), in the mean time, you can clone this repository and run:
$ stack install --ghc-options -O2
Below is an example of an optimization problem to reconstruct image from loss MRI signal, details about the problem can be found at MRI-Image-Reconstruction.
variables:
x[128][128] =0
constants:
im[128][128] =Dataset("data.h5", "im")
re[128][128] =Dataset("data.h5", "re")
signal[128][128] =Dataset("data.h5", "signal")
xLowerBound[128][128] =Dataset("data.h5", "x_lb")
xUpperBound[128][128] =Dataset("data.h5", "x_ub")
constraints:
x >= xLowerBound, x <= xUpperBound
let:
smootherX = rotate (0, 1) x + rotate (0, -1) x -2*. x
smootherY = rotate (1, 0) x + rotate (-1, 0) x -2*. x
regularization = huberNorm 2 smootherX + huberNorm 2 smootherY
minimize:
norm2square ((signal +:0) * (ft x - (re +: im))) +3000*. regularizationRunning:
$ symphony mri.sp
Will generate problem.c with the following interface:
#defineNUM_VARIABLES1
#defineNUM_ACTUAL_VARIABLES16384
#defineMEM_SIZE671774// all the actual double variables are allocated// one after another, starts from here
#defineVARS_START_OFFSET0constchar* var_name[NUM_VARIABLES] = {"x"};
constint var_num_dim[NUM_VARIABLES] = {2};
constint var_shape[NUM_VARIABLES][3] = {{128, 128, 1}};
constint var_size[NUM_VARIABLES] = {16384};
constint var_offset[NUM_VARIABLES] = {0};
constint partial_derivative_offset[NUM_VARIABLES] = {65543};
constint objective_offset = 81927;
double ptr[MEM_SIZE];
constint bound_pos[NUM_VARIABLES] = {0};
double lower_bound[NUM_ACTUAL_VARIABLES];
double upper_bound[NUM_ACTUAL_VARIABLES];
...
voidevaluate_partial_derivatives_and_objective() { .. } ;
voidevaluate_objective() { .. };
voidevaluate_partial_derivatives() { .. } ;
...Which you can plug to your favorite optimization solver.
We provide several optimization solvers (LBFGS, LBFGS-b, Ipopt) adapter in algorithms directory,
e.g: LBFGS-b.
To use symphony through docker (if you wish to avoid installing stack), build the docker image with
$ docker build . -t symphony
Then run the docker container. In order to provide the input file to the container, you'll have to link the path (say /some/path/) containing the the symphony file on your host machine to the /target path in the container
docker run -v /some/path:/target symphony
Copy the resulting /some/path/problem.c into your chosen algorithms directory (i.e ipopt, lbfgs, etc), which contain their own Dockerfile's for executing the optimization problem (see respective README's)
Build the docker image located in docs (it's important you do this from the root of the repo), with
docker build -t hashed-docker -f docs/Dockerfile .
Then run the docker container to generate the haddock documentation (NOTE: every time you alter the code base you'll have to rebuild the image)
docker run -v /some/path:/home/HashedExpression/docs hashed-docker
this will generate all the haddock documentation (in html) into /some/path on your local system
Please read Contributing.md. PRs are welcome.
The project is developed and maintained by Dr. Christopher Anand's research group, Computing and Software department, McMaster University.
List of contributors: