Thursday, April 18, 2013

More optimization in JavaScript

http://www.optimizationzen.com/2013/04/18/optimization-framework-js/

Not sure if this model is as readable as I would like it to be. Not so easy to recognize a transportation model in this.

require.config({
    paths: {
        "Optimization.Framework": "
http://optimizationzen.com/optimization.framework.min"
    }
});
var TransportModel = (function () {
    function TransportModel(origins, destinations) {
        if (typeof origins === "undefined") {
            origins = [];
        }
        if (typeof destinations === "undefined") {
            destinations = [];
        }
        this.origins = origins;
        this.destinations = destinations;
    }
    return TransportModel;
})();
var Origin = (function () {
    function Origin(id, name, supply, cost) {
        this.id = id;
        this.name = name;
        this.supply = supply;
        this.cost = cost;
    }
    return Origin;
})();
var Destination = (function () {
    function Destination(id, name, demand) {
        this.id = id;
        this.name = name;
        this.demand = demand;
    }
    return Destination;
})();
var transportModel = new TransportModel();
var fra = new Destination(0, "FRA", 900);
var det = new Destination(1, "DET", 1200);
var lan = new Destination(2, "LAN", 600);
var win = new Destination(3, "WIN", 400);
var stl = new Destination(4, "STL", 1700);
var fre = new Destination(5, "FRE", 1100);
var laf = new Destination(6, "LAF", 1000);
transportModel.destinations = [
fra,
det,
lan,
win,
stl,
fre,
laf];
var garycost = {};
garycost["fra"] = 39;
garycost["det"] = 14;
garycost["lan"] = 11;
garycost["win"] = 14;
garycost["stl"] = 16;
garycost["fre"] = 82;
garycost["laf"] = 8;
var gary = new Origin(0, "GARY", 1400, garycost);
var clevcost = {};
clevcost["fra"] = 27;
clevcost["det"] = 9;
clevcost["lan"] = 12;
clevcost["win"] = 9;
clevcost["stl"] = 26;
clevcost["fre"] = 95;
clevcost["laf"] = 17;
var clev = new Origin(1, "clev", 2600, clevcost);
var pittcost = {};
pittcost["fra"] = 24;
pittcost["det"] = 14;
pittcost["lan"] = 17;
pittcost["win"] = 13;
pittcost["stl"] = 28;
pittcost["fre"] = 99;
pittcost["laf"] = 20;
var pitt = new Origin(2, "pitt", 2900, pittcost);
transportModel.origins = [
gary,
clev,
pitt];

function run() {
    require([
        'Optimization.Framework'], function (of) {
        var glpk = new of.Optimization.GLPKSolver();
        var mathModel = new of.Optimization.MathModel();
        var Transport = new of.Optimization.VariableCollection("Transport_", 0, Math.min(), of.Optimization.VariableType.Integer, transportModel.origins, transportModel.destinations);
        Transport.IndexValidation = false;
        mathModel.setObjective(new of.Optimization.Expression(Enumerable.from(transportModel.origins).selectMany(function (orig) {
            return Enumerable.from(transportModel.destinations).select(function (dest) {
                return Transport.varFromIndex(orig, dest).multiplyBy(orig.cost[dest.Name]);
            });
        }).toArray()));
        transportModel.origins.forEach(function (orig) {
            mathModel.addConstraint(new of.Optimization.Expression(Enumerable.from(transportModel.destinations).select(function (dest) {
                return Transport.varFromIndex(orig, dest);
            }).toArray()).eq(orig.supply));
        });
        transportModel.destinations.forEach(function (dest) {
            mathModel.addConstraint(new of.Optimization.Expression(Enumerable.from(transportModel.origins).select(function (orig) {
                return Transport.varFromIndex(orig, dest);
            }).toArray()).eq(dest.demand));
        });
        var solution = glpk.solve(mathModel);
        var lp = mathModel.write();
        $('#model_as_lp_file').val(lp);
        $('#log').html("Solution: " + JSON.stringify(solution, null, 4));
    });

};

See also http://yetanothermathprogrammingconsultant.blogspot.com/2013/01/c-vs-javascript.html.