Example 1: Assignment Problem
Problem Description
Several companies have their own capital, liabilities, and profits.
CAPITAL | LIABILITIES | PROFIT | |
---|---|---|---|
Co. A | |||
Co. B | |||
Co. C | |||
Co. D | |||
Co. E |
Select a subset of companies to maximize total profit, while satisfying:
- Total capital is greater than or equal to
; - Total liabilities is less than or equal to
。
Mathematical Model
Variables
Intermediate Expressions
1. Total Capital
2. Total Liabilities
3. Total Profit
Objective Function
1. Maximize Total Profit
Constraints
1. Minimum Capital Limit
2. Maximum Liability Limit
Expected Result
Optimal selection: companies A, B and C 。
Code Implementation
kotlin
import fuookami.ospf.kotlin.utils.math.*
import fuookami.ospf.kotlin.utils.concept.*
import fuookami.ospf.kotlin.utils.functional.*
import fuookami.ospf.kotlin.utils.multi_array.*
import fuookami.ospf.kotlin.core.frontend.variable.*
import fuookami.ospf.kotlin.core.frontend.expression.monomial.*
import fuookami.ospf.kotlin.core.frontend.expression.polynomial.*
import fuookami.ospf.kotlin.core.frontend.expression.symbol.*
import fuookami.ospf.kotlin.core.frontend.inequality.*
import fuookami.ospf.kotlin.core.frontend.model.mechanism.*
import fuookami.ospf.kotlin.core.backend.plugins.scip.*
data class Company(
val capital: Flt64,
val liability: Flt64,
val profit: Flt64
) : AutoIndexed(Company::class)
val companies: List<Company> = ... // company data
val minCapital = Flt64(10.0)
val maxLiability = Flt64(5.0)
// create a model instance
val metaModel = LinearMetaModel("demo1")
// define variables
val x = BinVariable1("x", Shape1(companies.size))
for (c in companies) {
x[c].name = "${x.name}_${c.index}"
}
metaModel.add(x)
// define intermediate expressions
val capital = LinearExpressionSymbol(
sum(companies) { it.capital * x[it] },
"capital"
)
metaModel.add(capital)
val liability = LinearExpressionSymbol(
sum(companies) { it.liability * x[it] },
"liability"
)
metaModel.add(liability)
val profit = LinearExpressionSymbol(
sum(companies) { it.profit * x[it] },
"profit"
)
metaModel.add(profit)
// define objective function
metaModel.maximize(profit)
// define constraints
metaModel.addConstraint(capital geq minCapital)
metaModel.addConstraint(liability leq maxLiability)
// solve the model
val solver = ScipLinearSolver()
when (val ret = solver(metaModel)) {
is Ok -> {
metaModel.tokens.setSolution(ret.value.solution)
}
is Failed -> {}
}
// parse results
val solution = ArrayList<Company>()
for (token in metaModel.tokens.tokens) {
if (token.result!! eq Flt64.one && token.variable.belongsTo(x)) {
solution.add(companies[token.variable.index])
}
}
For the complete implementation, please refer to: