示例 12:投资组合问题
问题描述
市场上有n种资产
购买
设定一个投资组合方案,给定资金
数学模型
变量
中间值
1. 是否有购置
2. 手续费
3. 收益
4. 风险
目标函数
1. 收益最大
约束
1. 资金和为
2. 风险限制
期望结果
代码实现
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.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 Product(
val yield: Flt64,
val risk: Flt64,
val premium: Flt64,
val minPremium: Flt64
) : AutoIndexed(Product::class)
val products: List<Product> = ... // 产品列表
val funds = Flt64(1000000.0)
val maxRisk = Flt64(0.02)
// 创建模型实例
val metaModel = LinearMetaModel("demo12")
// 定义变量
val x = UIntVariable1("x", Shape1(products.size))
metaModel.add(x)
// 定义中间值
val assignment = LinearIntermediateSymbols1(
"assignment",
Shape1(products.size)
) { i, _ ->
BinaryzationFunction(
x = LinearPolynomial(x[i]),
name = "assignment_$i"
)
}
metaModel.add(assignment)
val premium = LinearIntermediateSymbols1(
"premium",
Shape1(products.size)
) { i, _ ->
val product = products[i]
MaxFunction(
listOf(
LinearPolynomial(product.premium * x[i]),
LinearPolynomial(product.minPremium * assignment[i])
),
"premium_$i"
)
}
metaModel.add(premium)
val risk = LinearExpressionSymbol(
sum(products.map { p -> p.risk * x[p] / funds }),
"risk"
)
metaModel.add(risk)
val yield = LinearExpressionSymbol(
sum(products.map { p -> p.yield * x[p] - premium[p] }),
"yield"
)
metaModel.add(yield)
// 定义目标函数
metaModel.maximize(yield, "yield")
// 定义约束
metaModel.addConstraint(
sum(products.map { p -> x[p] + premium[p] }) eq funds,
"funs"
)
metaModel.addConstraint(
risk leq maxRisk,
"risk"
)
// 调用求解器求解
val solver = ScipLinearSolver()
when (val ret = solver(metaModel)) {
is Ok -> {
metaModel.tokens.setSolution(ret.value.solution)
}
is Failed -> {}
}
// 解析结果
val solution = HashMap<Product, UInt64>()
for (token in metaModel.tokens.tokens) {
if (token.result!! geq Flt64.one && token.variable.belongsTo(x)) {
val vector = token.variable.vectorView
val product = products[vector[0]]
solution[product] = token.result!!.round().toUInt64()
}
}
完整实现请参考: