首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于OjAlgo目标函数的整数优化

基于OjAlgo目标函数的整数优化
EN

Stack Overflow用户
提问于 2021-09-28 21:51:58
回答 2查看 118关注 0票数 1

我正在尝试使用Java语言中的ojAlgo库来实现整数优化,但是我无法提供我想要的目标函数。

我想最小化函数:(A - B.X)'(A - B.X),其中A是(n X 1)矩阵,B是(n X n)对角矩阵,X是带有优化变量的(n X 1)矩阵。我希望X中的结果只包含整数。

我可以设置一个不同的目标函数来最大化B.X。我如何将其更改为(A - B.X)'(A - B.X)?以下是到目前为止的代码。

代码语言:javascript
复制
import org.apache.log4j.Logger;
import org.ojalgo.optimisation.Expression;
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.Optimisation;
import org.ojalgo.optimisation.Variable;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.List;

public class AllocationOptimization {
    protected Logger log = Logger.getLogger(AllocationOptimization.class);

    // This is the objective function, since weight() is assigned to it. How to change this objective function to what I want?
    private List<Variable> makeVariables(HashMap<String, BigDecimal> matrixB) {
        List<Variable> result = new ArrayList<>();
        for (String assetName : matrixB.keySet()) {
            result.add(new Variable(assetName).weight(matrixB.get(assetName)));
        }
        return result;
    }

    private ExpressionsBasedModel createExpressionModel(List<Variable> variables) {
        final ExpressionsBasedModel model = new ExpressionsBasedModel();
        for (Variable v : variables) {
            model.addVariable(v);
        }
        return model;
    }

    private void addExpressionConstraints(ExpressionsBasedModel model, List<Variable> variables,
                                          HashMap<String, BigDecimal> matrixB,
                                          HashMap<String, BigDecimal> wantedAbsoluteSharesMap,
                                          BigDecimal idealTotalPrice) {
        Expression expression = model.addExpression("C1").upper(idealTotalPrice);
        int i = 0;
        for (String assetName : matrixB.keySet()) {
            expression.set(variables.get(i), matrixB.get(assetName));
            i += 1;
        }

        for (Variable v : variables) {
            long absShares = wantedAbsoluteSharesMap.get(v.getName()).longValue();
            v.lower((long) Math.max(0, 0.8 * absShares)).upper((long) Math.max(Math.max(0, 1.2 * absShares), 5));
        }
    }

    private void setIntegerSolving(ExpressionsBasedModel model) {
        for (Variable v : model.getVariables()) {
            v.setInteger(true);
        }
    }

    private HashMap<String, Long> getIntegerOptimizationResult(ExpressionsBasedModel model, HashMap<String, BigDecimal> matrixB) {
        Optimisation.Result result = model.maximise();

        return prepareResult(result, matrixB);
    }


    private HashMap<String, Long> prepareResult(Optimisation.Result result, HashMap<String, BigDecimal> matrixB) {
        int i = 0;
        HashMap<String, Long> optimizedResult = new HashMap<>();
        BigDecimal sumAssetPrices = new BigDecimal("0.0");

        for (String assetName : matrixB.keySet()) {
            long sharesCount = result.get(i).longValue();
            log.debug(assetName + ": " + sharesCount);
            optimizedResult.put(assetName, sharesCount);
            sumAssetPrices = sumAssetPrices.add(matrixB.get(assetName).multiply(BigDecimal.valueOf(sharesCount)));
            i += 1;
        }
        log.debug("Total assets value after converting shares to integer numbers: " + sumAssetPrices);

        return optimizedResult;
    }

    public HashMap<String, Long> optimizeSharesCount(HashMap<String, BigDecimal> constraint1,
                                                     HashMap<String, BigDecimal> matrixB,
                                                     BigDecimal constraint2) throws InputMismatchException {
        List<Variable> variableList = makeVariables(matrixB);
        ExpressionsBasedModel model = createExpressionModel(variableList);
        addExpressionConstraints(model, variableList, matrixB, constraint1, constraint2);
        setIntegerSolving(model);
        HashMap<String, Long> resultMap = getIntegerOptimizationResult(model, matrixB);

        return resultMap;

    }

    private HashMap<String, BigDecimal> createWantedAbsoluteSharesTest1() {
        HashMap<String, BigDecimal> absShares = new HashMap<>();
        absShares.put("NFLX", new BigDecimal("2"));
        absShares.put("MSFT", new BigDecimal("4"));
        absShares.put("GOOG", new BigDecimal("0"));
        absShares.put("AAPL", new BigDecimal("25"));

        return absShares;
    }

    private HashMap<String, BigDecimal> createAssetPricesMapTest1() {
        HashMap<String, BigDecimal> assetPrices = new HashMap<>();
        assetPrices.put("NFLX", new BigDecimal("601.06"));
        assetPrices.put("MSFT", new BigDecimal("296.75"));
        assetPrices.put("GOOG", new BigDecimal("2843.78"));
        assetPrices.put("AAPL", new BigDecimal("149.07"));

        return assetPrices;
    }


    public static void main(String[] args) {
        AllocationOptimization allocationOptimization = new AllocationOptimization();
        // For testing
        HashMap<String, BigDecimal> constr1 = allocationOptimization.createWantedAbsoluteSharesTest1();
        HashMap<String, BigDecimal> matrixB = allocationOptimization.createAssetPricesMapTest1();
        BigDecimal constr2 = new BigDecimal("5348.25");

        HashMap<String, Long> optimizedResult = null;
        try {
            optimizedResult = allocationOptimization.optimizeSharesCount(constr1, matrixB, constr2);
        } catch (Exception e) {
            e.printStackTrace();
        }
        assert optimizedResult != null;
        allocationOptimization.log.info("optimizedResult size: " + optimizedResult.size());
    }

}
EN

回答 2

Stack Overflow用户

发布于 2021-09-29 06:09:29

您为Variable指定了权重,这使它们成为目标函数的一部分。您还可以将权重分配给Expression:s。任何/所有具有权重的内容都会相加,以形成目标函数。

代码语言:javascript
复制
    Expression objective = model.addExpression("Whole Objective").weight(BigDecimal.ONE);
    for (Variable variableR : variables) {
        objective.set(variableR, linearParameter);
        for (Variable variableC : variables) {
            objective.set(variableR, variableC, quadraticParameter);
        }
    }

等同于:

代码语言:javascript
复制
    Expression objective = model.addExpression("Objective Part").weight(BigDecimal.ONE);
    for (Variable variableR : variables) {
        variableR.weight(linearParameter);
        for (Variable variableC : variables) {
            objective.set(variableR, variableC, quadraticParameter);
        }
    }
票数 1
EN

Stack Overflow用户

发布于 2021-11-02 21:33:59

根据@apete的评论,我修改了目标函数并添加了必要的约束。在这里发布我的解决方案给其他人。

代码语言:javascript
复制
private List<Variable> makeVariables(HashMap<String, BigDecimal> matrixB) {
    List<Variable> result = new ArrayList<>();
    for (String assetName : matrixB.keySet()) {
        result.add(new Variable(assetName));
    }
    return result;
}

private ExpressionsBasedModel createObjective(ExpressionsBasedModel model, List<Variable> variables,
                                              HashMap<String, BigDecimal> matrixA,
                                              HashMap<String, BigDecimal> matrixB) {
    // Anything and everything with that has a weight is summed up to form the objective function
    Expression objective = model.addExpression("Objective function").weight(BigDecimal.ONE);
    for (Variable variable : variables) {
        String assetName = variable.getName();
        objective.set(variable, new BigDecimal("-2").multiply(matrixA.get(assetName)).multiply(matrixB.get(assetName)));
        objective.set(variable, variable, matrixB.get(assetName).pow(2));
    }
    return model;
}

private void addExpressionConstraints(ExpressionsBasedModel model, List<Variable> variables,
                                      HashMap<String, BigDecimal> matrixB,
                                      HashMap<String, BigDecimal> wantedAbsoluteSharesMap,
                                      HashMap<String, BigDecimal> matrixA,
                                      BigDecimal idealTotalPrice, BigDecimal accountBalance) {
    Expression expression1 = model.addExpression("C1").upper(idealTotalPrice);
    for (Variable variable : variables) {
        expression1.set(variable, matrixB.get(variable.getName()));
    }

    for (Variable v : variables) {
        // No negative values constraint
        v.lower(0);
    }

    // This constraint is used to compensate for the constants arising in the quadratic objective function
    BigDecimal sumSquaresUserAllocation = new BigDecimal("0.0");
    for (String assetName : this.assetsList) {
        sumSquaresUserAllocation = sumSquaresUserAllocation.add(matrixA.get(assetName).pow(2));
    }

    Expression expression2 = model.addExpression("C2").upper(new BigDecimal("1.01").multiply(sumSquaresUserAllocation.multiply(new BigDecimal("-1"))));
    expression2.lower(new BigDecimal("0.99").multiply(sumSquaresUserAllocation.multiply(new BigDecimal("-1"))));
    for (Variable variable : variables) {
        String assetName = variable.getName();
        expression2.set(variable, new BigDecimal("-2").multiply(matrixA.get(assetName)).multiply(matrixB.get(assetName)));
        expression2.set(variable, variable, matrixB.get(assetName).pow(2));
    }
}

最后,我使用model.minimise()来最小化目标函数,而不是使用model.maximise()函数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69368877

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档