elcheapogary
elcheapogary

Reputation: 11

How to encourage a balanced solution in ojAlgo ExpressionBasedModel

I have the following model:

        ExpressionsBasedModel model = new ExpressionsBasedModel();

        Variable va = model.addVariable("va")
                .lower(0);

        Variable vb = model.addVariable("vb")
                .lower(0);

        Variable vc = model.addVariable("vc")
                .lower(0);

        Variable vd = model.addVariable("vd")
                .lower(0);

        Variable ve = model.addVariable("ve")
                .lower(0);

        Expression ef = model.addExpression("ef")
                .lower(0);

        Expression eg = model.addExpression("eg")
                .lower(0);

        Expression eh = model.addExpression("eh")
                .lower(-240);

        Expression ei = model.addExpression("ei")
                .lower(0);

        Expression ej = model.addExpression("ej")
                .lower(0);

        Expression ek = model.addExpression("ek")
                .lower(0);

        Expression el = model.addExpression("el")
                .lower(-2000);

        ef.set(va, -50);
        el.set(va, -100);
        eg.set(va, 100);

        eh.set(vb, -30);
        ef.set(vb, 40);
        ej.set(vb, 20);

        ek.set(vc, -30);
        eg.set(vc, -30);
        ei.set(vc, 60);

        ei.set(vd, -30);
        eg.set(vd, -30);
        ek.set(vd, 60);

        ej.set(ve, -40);
        el.set(ve, -40);
        ek.set(ve, 20);

        ei.weight(1);
        ek.weight(1);

        /*
         * These next 2 lines required to get balanced solution.
         * Without them ei = 720 and ek = 0.
         */
//        ek.lower(360);
//        ei.lower(360);

        model.maximise();

        BasicLogger.debug(model);

Although ei and ek are equally weighted, the solution I get is:

############################################
0 <= va: 6.4 <= 6.4
0 <= vb: 8 <= 8
0 <= vc: 15.111111 (300)
0 <= vd: 6.222222 (300)
0 <= ve: 4 (200) <= 4
0 <= ef: 0.0
0 <= eg: 0.0
-240 <= eh: -240.0
0 <= ei: 720.0
0 <= ej: 0.0
0 <= ek: -0.0
-2000 <= el: -800.0
############################################

ei == 720, ek == 0.

I would prefer a solution in which ei and ek are as balanced as possible, (ei == 360, ek == 360). Is there some way of encoding that requirement for "as balanced as possible" as a weighted expression?

In this specific example I have commented out the lower value constraint that actually result in the behavior I want. In real life, the model is dynamic and I may have 5 equally weighted expressions. I won't know the correct values in order to set the lower constraints.

Upvotes: 0

Views: 78

Answers (1)

elcheapogary
elcheapogary

Reputation: 11

For future readers, I was able to do this by first converting the values represented by ei and ek into new variables, with the existing expressions ei and ek constraining the value of the new variables to the value these expressions previously had. Then I added a new variable, weighted it heavily, and constrained it to be less than each of the new variables.

        Expression ei = model.addExpression("ei")
                .lower(0);

        Expression ek = model.addExpression("ek")
                .lower(0);

became:

        Expression ei = model.addExpression("ei")
                .level(0);
        Variable vei = model.addVariable("vei")
                .lower(0);
        ei.set(vei, -1);

        Expression ek = model.addExpression("ek")
                .level(0);
        Variable vek = model.addVariable("vek")
                .lower(0);
        ek.set(vek, -1);

Weighting became:

        vei.weight(1);
        vek.weight(1);

And added balance variable and constraints:

        Variable balance = model.addVariable("balance")
                .weight(100);

        model.addExpression("balance constraint for vei")
                .set(vei, 1)
                .set(balance, -1)
                .lower(0);

        model.addExpression("balance constraint for vek")
                .set(vek, 1)
                .set(balance, -1)
                .lower(0);

This results in a solution that is as balanced as possible:

############################################
0 <= va: 6.4 <= 6.4
0 <= vb: 8 <= 8
0 <= vc: 11.111111
0 <= vd: 10.222222
0 <= ve: 4 <= 4
0 <= vei: 360 (1)
0 <= vek: 360 (1)
balance: 360 (100)
0 <= ef: 0.0
0 <= eg: 0.0
-240 <= eh: -240.0
0 <= ei: 0.0 <= 0
0 <= ej: 0.0
0 <= ek: -0.0 <= 0
-2000 <= el: -800.0
0 <= balance constraint for vei: 0.0
0 <= balance constraint for vek: 0.0
############################################

Upvotes: 1

Related Questions