You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:调整优化调用逻辑

  1. 在主流程中调用新增的目标配置方法
  2. 将原有最大化调用改为最小化
    首先修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 11:27:03