1

i have simple binary liinear programming funcjon and i want to get more than one, for example 10 best solutions from Optimisation.Result = model.minimise(). Is this posible with OjAlgo?

I knew that purpose of function is to find one, best solution but is there any chance to generate more solutions or get solutions from solver iterations?

fun linearProgrammingSolver(meal: Meal): MutableList<String> {

        val mealList = meal.results
        val resultList = mutableListOf<String>()
        val listOfVariables= makeVariables(meal) as ImmutableList<Variable>

        val model = ExpressionsBasedModel()
        listOfVariables.forEach{
            model.addVariable(it)
        }


        val calories = model.addExpression("calories")
            .lower(1500)
            .upper(3000)
        listOfVariables.forEach {
           val index = listOfVariables.indexOf(it)
            calories.set(listOfVariables[index], mealList[index].nutrition.nutrients[0].amount)
        }

        val protein = model.addExpression("protein")
            .lower(60)
        listOfVariables.forEach {
            val index = listOfVariables.indexOf(it)
            protein.set(listOfVariables[index], mealList[index].nutrition.nutrients[1].amount)
        }


        val meals = model.addExpression("meals")
            .level(3)
        listOfVariables.forEach {
            val index = listOfVariables.indexOf(it)
            meals.set(listOfVariables[index], 1)
        }


        val result: Optimisation.Result = model.minimise()

        println("state ${result.state}")


        model.variables.forEach{
            if(it.value.toInt() == 1){
                println("model.var ${it}")
                resultList.add(it.name)
            }
        }

        println(model)
        println(result)
        println("list $resultList")

        return resultList
    }

2 Answers2

2

There are two ways to interpret this question.

  1. Get the best solution and the 9 next best solutions. This can be accomplished by looking at the optimal solution x*(i) and, setting a(i):=x*(i) and introducing an extra constraint to the model that forbids x* to be found again, and then resolve. Repeat this. The cut you need to add in each cycle can look like:

    sum(i, x(i) * a(i)) - sum(i, x(i) * (1-a(i))) <= sum(i, a(i)) - 1
    
  2. Collect solutions the algorithm finds and report the best 10 of them. That should not be too difficult to add to the algorithm (just keep track of the best 10). This would require changing the source code of the algorithm.

An alternative is using a more advanced (but likely much more expensive) solver that has a so-called solution pool.

Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39
  • Since there's already a constraint to always select precisely 3 meals, sum(i, a(i)) == 3, isn't it enough to say that at least one of the previously selected meals must now be excluded? Essentially: sum(i, x(i) * a(i)) <= 2 – apete Nov 19 '20 at 12:29
  • 1
    Correct. The code is rather difficult to read (for me) so I don't recognize much of the underlying equations. – Erwin Kalvelagen Nov 19 '20 at 14:00
1

ojAlgo returns 1 solution paired with state describing the "quality" of that solution – Optimal/Feasible/Approximate/Infeasible/Unbounded...

You can do what Erwin Kalvelagen suggested in his answer. ojAlgo's IntegerSolver does register/log each integer solution found, but currently only stores and returns the best one found.

apete
  • 1,250
  • 1
  • 10
  • 16