Java使用ojAlgo做整数优化时如何设置目标函数(A - B.X)'(A - B.X)
ojAlgo整数二次规划目标函数修改方案
你需要的目标函数(A - B·X)ᵀ(A - B·X)因B为n×n对角矩阵,可以直接展开为各维度独立的平方和,无交叉项:
Σ (Bᵢ·Xᵢ - Aᵢ)² = Σ (Bᵢ²·Xᵢ² - 2·Aᵢ·Bᵢ·Xᵢ + Aᵢ²)
优化时常数项ΣAᵢ²不影响最优解,可直接忽略,只需最小化剩余的二次+线性部分即可,具体修改步骤如下:
步骤1:移除变量默认权重
原来的makeVariables方法中配置的weight()是为线性最大化目标服务的,当前场景不需要,修改为:
private List<Variable> makeVariables(HashMap<String, BigDecimal> matrixB) { List<Variable> result = new ArrayList<>(); for (String assetName : matrixB.keySet()) { // 移除原有weight配置,后续单独设置二次目标 result.add(new Variable(assetName)); } return result; }
步骤2:新增二次目标函数配置方法
新增方法向模型中添加最小化目标,需要传入你业务中定义的A矩阵映射(键为资产名,值为A矩阵对应维度的数值):
private void addQuadraticObjective(ExpressionsBasedModel model, List<Variable> variables, HashMap<String, BigDecimal> matrixB, HashMap<String, BigDecimal> matrixA) { // 创建目标表达式,设置权重为1表示该表达式为目标函数 Expression objective = model.addExpression("Objective").weight(1); int index = 0; for (String assetName : matrixB.keySet()) { Variable x = variables.get(index); BigDecimal b = matrixB.get(assetName); BigDecimal a = matrixA.get(assetName); // 设置二次项系数:B_i² objective.set(x, x, b.multiply(b)); // 设置一次项系数:-2*A_i*B_i objective.set(x, b.multiply(a).multiply(new BigDecimal("-2"))); index++; } }
步骤3:调整优化调用逻辑
- 在主流程中调用新增的目标配置方法
- 将原有最大化调用改为最小化
首先修改getIntegerOptimizationResult方法:
private HashMap<String, Long> getIntegerOptimizationResult(ExpressionsBasedModel model, HashMap<String, BigDecimal> matrixB) { // 从最大化改为最小化 Optimisation.Result result = model.minimise(); return prepareResult(result, matrixB); }
然后修改optimizeSharesCount方法的入参和逻辑,增加A矩阵传入:
// 入参新增matrixA:对应你问题中的A矩阵映射 public HashMap<String, Long> optimizeSharesCount(HashMap<String, BigDecimal> wantedAbsoluteSharesMap, HashMap<String, BigDecimal> matrixB, HashMap<String, BigDecimal> matrixA, BigDecimal idealTotalPrice) throws InputMismatchException { List<Variable> variableList = makeVariables(matrixB); ExpressionsBasedModel model = createExpressionModel(variableList); addExpressionConstraints(model, variableList, matrixB, wantedAbsoluteSharesMap, idealTotalPrice); // 新增调用:添加二次目标 addQuadraticObjective(model, variableList, matrixB, matrixA); setIntegerSolving(model); return getIntegerOptimizationResult(model, matrixB); }
步骤4:测试用例适配
根据你的业务定义传入A矩阵即可,比如如果你的A是目标持仓价值,测试用例可参考:
public static void main(String[] args) { AllocationOptimization allocationOptimization = new AllocationOptimization(); HashMap<String, BigDecimal> constr1 = allocationOptimization.createWantedAbsoluteSharesTest1(); HashMap<String, BigDecimal> matrixB = allocationOptimization.createAssetPricesMapTest1(); BigDecimal constr2 = new BigDecimal("5348.25"); // 构造A矩阵,按需修改为你实际的A值 HashMap<String, BigDecimal> matrixA = new HashMap<>(); for (String asset : matrixB.keySet()) { // 示例逻辑:A_i = B_i * 理想股数,即拟合目标持仓价值 matrixA.put(asset, matrixB.get(asset).multiply(constr1.get(asset))); } try { HashMap<String, Long> optimizedResult = allocationOptimization.optimizeSharesCount(constr1, matrixB, matrixA, constr2); allocationOptimization.log.info("optimizedResult size: " + optimizedResult.size()); } catch (Exception e) { e.printStackTrace(); } }
内容的提问来源于stack exchange,提问作者SGI
相关产品推荐
相关产品推荐

