use of org.ojalgo.optimisation.ExpressionsBasedModel in project ojAlgo by optimatika.
the class NewIntegerSolver method compute.
void compute(final NodeKey nodeKey) {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("\nBranch&Bound Node");
NewIntegerSolver.this.log(nodeKey.toString());
NewIntegerSolver.this.log(NewIntegerSolver.this.toString());
}
if (!NewIntegerSolver.this.isIterationAllowed() || !NewIntegerSolver.this.isIterationNecessary()) {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("Reached iterations or time limit - stop!");
}
normal &= false;
}
if (!NewIntegerSolver.this.isGoodEnoughToContinueBranching(nodeKey.objective)) {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("No longer a relevant node!");
}
normal &= true;
}
ExpressionsBasedModel tmpModel = NewIntegerSolver.this.makeNodeModel(nodeKey);
final Optimisation.Result tmpResult = tmpModel.solve(NewIntegerSolver.this.getBestResultSoFar());
NewIntegerSolver.this.incrementIterationsCount();
if ((tmpModel.options.logger_appender != null) && (tmpModel.options.logger_appender instanceof PrinterBuffer)) {
if (NewIntegerSolver.this.getIntegerModel().options.logger_appender != null) {
((PrinterBuffer) tmpModel.options.logger_appender).flush(NewIntegerSolver.this.getIntegerModel().options.logger_appender);
}
}
if (tmpResult.getState().isOptimal()) {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("Node solved to optimality!");
}
if (NewIntegerSolver.this.options.validate && !tmpModel.validate(tmpResult)) {
// This should not be possible. There is a bug somewhere.
NewIntegerSolver.this.log("Node solution marked as OPTIMAL, but is actually INVALID/INFEASIBLE/FAILED. Stop this branch!");
// IntegerSolver.this.logDebug(myKey.toString());
// IntegerSolver.this.logDebug(tmpModel.toString());
// final GenericSolver tmpDefaultSolver = tmpModel.getDefaultSolver();
// tmpDefaultSolver.solve();
// IntegerSolver.this.logDebug(tmpDefaultSolver.toString());
normal &= false;
}
final int tmpBranchIndex = NewIntegerSolver.this.identifyNonIntegerVariable(tmpResult, nodeKey);
final double tmpSolutionValue = NewIntegerSolver.this.evaluateFunction(tmpResult);
if (tmpBranchIndex == -1) {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("Integer solution! Store it among the others, and stop this branch!");
}
final Optimisation.Result tmpIntegerSolutionResult = new Optimisation.Result(Optimisation.State.FEASIBLE, tmpSolutionValue, tmpResult);
NewIntegerSolver.this.markInteger(nodeKey, null, tmpIntegerSolutionResult);
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log(NewIntegerSolver.this.getBestResultSoFar().toString());
}
BasicLogger.debug();
BasicLogger.debug(NewIntegerSolver.this.toString());
// BasicLogger.debug(DaemonPoolExecutor.INSTANCE.toString());
} else {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("Not an Integer Solution: " + tmpSolutionValue);
}
final double tmpVariableValue = tmpResult.doubleValue(NewIntegerSolver.this.getGlobalIndex(tmpBranchIndex));
if (NewIntegerSolver.this.isGoodEnoughToContinueBranching(tmpSolutionValue)) {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("Still hope, branching on {} @ {} >>> {}", tmpBranchIndex, tmpVariableValue, tmpModel.getVariable(NewIntegerSolver.this.getGlobalIndex(tmpBranchIndex)));
}
tmpModel.dispose();
tmpModel = null;
final NodeKey tmpLowerBranchTask = nodeKey.createLowerBranch(tmpBranchIndex, tmpVariableValue, tmpResult.getValue());
final NodeKey tmpUpperBranchTask = nodeKey.createUpperBranch(tmpBranchIndex, tmpVariableValue, tmpResult.getValue());
this.add(tmpLowerBranchTask);
this.add(tmpUpperBranchTask);
if (DaemonPoolExecutor.isDaemonAvailable()) {
DaemonPoolExecutor.invoke(new NodeWorker());
}
normal &= true;
} else {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("Can't find better integer solutions - stop this branch!");
}
}
}
} else {
if (NewIntegerSolver.this.isDebug()) {
NewIntegerSolver.this.log("Failed to solve problem - stop this branch!");
}
}
normal &= true;
}
use of org.ojalgo.optimisation.ExpressionsBasedModel in project ojAlgo by optimatika.
the class SimplexSolver method build.
static SimplexTableau build(final ExpressionsBasedModel model) {
final List<Variable> tmpPosVariables = model.getPositiveVariables();
final List<Variable> tmpNegVariables = model.getNegativeVariables();
final Set<IntIndex> tmpFixVariables = model.getFixedVariables();
final Expression tmpObjFunc = model.objective().compensate(tmpFixVariables);
final List<Expression> tmpExprsEq = model.constraints().filter(c -> c.isEqualityConstraint() && !c.isAnyQuadraticFactorNonZero()).collect(Collectors.toList());
final List<Expression> tmpExprsLo = model.constraints().filter(c -> c.isLowerConstraint() && !c.isAnyQuadraticFactorNonZero()).collect(Collectors.toList());
final List<Expression> tmpExprsUp = model.constraints().filter(c -> c.isUpperConstraint() && !c.isAnyQuadraticFactorNonZero()).collect(Collectors.toList());
final List<Variable> tmpVarsPosLo = model.bounds().filter(v -> v.isPositive() && v.isLowerConstraint() && (v.getLowerLimit().signum() > 0)).collect(Collectors.toList());
final List<Variable> tmpVarsPosUp = model.bounds().filter(v -> v.isPositive() && v.isUpperConstraint() && (v.getUpperLimit().signum() > 0)).collect(Collectors.toList());
final List<Variable> tmpVarsNegLo = model.bounds().filter(v -> v.isNegative() && v.isLowerConstraint() && (v.getLowerLimit().signum() < 0)).collect(Collectors.toList());
final List<Variable> tmpVarsNegUp = model.bounds().filter(v -> v.isNegative() && v.isUpperConstraint() && (v.getUpperLimit().signum() < 0)).collect(Collectors.toList());
final int tmpConstraiCount = tmpExprsEq.size() + tmpExprsLo.size() + tmpExprsUp.size() + tmpVarsPosLo.size() + tmpVarsPosUp.size() + tmpVarsNegLo.size() + tmpVarsNegUp.size();
final int tmpProblVarCount = tmpPosVariables.size() + tmpNegVariables.size();
final int tmpSlackVarCount = tmpExprsLo.size() + tmpExprsUp.size() + tmpVarsPosLo.size() + tmpVarsPosUp.size() + tmpVarsNegLo.size() + tmpVarsNegUp.size();
final SimplexTableau retVal = SimplexTableau.make(tmpConstraiCount, tmpProblVarCount, tmpSlackVarCount);
final int tmpPosVarsBaseIndex = 0;
final int tmpNegVarsBaseIndex = tmpPosVarsBaseIndex + tmpPosVariables.size();
final int tmpSlaVarsBaseIndex = tmpNegVarsBaseIndex + tmpNegVariables.size();
for (final IntIndex tmpKey : tmpObjFunc.getLinearKeySet()) {
final double tmpFactor = model.isMaximisation() ? -tmpObjFunc.getAdjustedLinearFactor(tmpKey) : tmpObjFunc.getAdjustedLinearFactor(tmpKey);
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
if (tmpPosInd >= 0) {
retVal.objective().set(tmpPosInd, tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
if (tmpNegInd >= 0) {
retVal.objective().set(tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
}
}
int tmpConstrBaseIndex = 0;
int tmpCurrentSlackVarIndex = tmpSlaVarsBaseIndex;
final int tmpExprsEqLength = tmpExprsEq.size();
for (int c = 0; c < tmpExprsEqLength; c++) {
final Expression tmpExpr = tmpExprsEq.get(c).compensate(tmpFixVariables);
final double tmpRHS = tmpExpr.getAdjustedLowerLimit();
if (tmpRHS < ZERO) {
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpRHS);
for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
}
}
} else {
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpRHS);
for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
}
}
}
}
tmpConstrBaseIndex += tmpExprsEqLength;
final int tmpExprsLoLength = tmpExprsLo.size();
for (int c = 0; c < tmpExprsLoLength; c++) {
final Expression tmpExpr = tmpExprsLo.get(c).compensate(tmpFixVariables);
final double tmpRHS = tmpExpr.getAdjustedLowerLimit();
if (tmpRHS < ZERO) {
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpRHS);
for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
}
}
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, ONE);
} else {
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpRHS);
for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
}
}
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, NEG);
}
}
tmpConstrBaseIndex += tmpExprsLoLength;
final int tmpExprsUpLength = tmpExprsUp.size();
for (int c = 0; c < tmpExprsUpLength; c++) {
final Expression tmpExpr = tmpExprsUp.get(c).compensate(tmpFixVariables);
final double tmpRHS = tmpExpr.getAdjustedUpperLimit();
if (tmpRHS < ZERO) {
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpRHS);
for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
}
}
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, NEG);
} else {
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpRHS);
for (final IntIndex tmpKey : tmpExpr.getLinearKeySet()) {
final double tmpFactor = tmpExpr.getAdjustedLinearFactor(tmpKey);
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey.index);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey.index);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
}
}
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, ONE);
}
}
tmpConstrBaseIndex += tmpExprsUpLength;
final int tmpVarsPosLoLength = tmpVarsPosLo.size();
for (int c = 0; c < tmpVarsPosLoLength; c++) {
final Variable tmpVar = tmpVarsPosLo.get(c);
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpVar.getAdjustedLowerLimit());
final int tmpKey = model.indexOf(tmpVar);
final double tmpFactor = tmpVar.getAdjustmentFactor();
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
}
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, NEG);
}
tmpConstrBaseIndex += tmpVarsPosLoLength;
final int tmpVarsPosUpLength = tmpVarsPosUp.size();
for (int c = 0; c < tmpVarsPosUpLength; c++) {
final Variable tmpVar = tmpVarsPosUp.get(c);
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, tmpVar.getAdjustedUpperLimit());
final int tmpKey = model.indexOf(tmpVar);
final double tmpFactor = tmpVar.getAdjustmentFactor();
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, -tmpFactor);
}
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, ONE);
}
tmpConstrBaseIndex += tmpVarsPosUpLength;
final int tmpVarsNegLoLength = tmpVarsNegLo.size();
for (int c = 0; c < tmpVarsNegLoLength; c++) {
final Variable tmpVar = tmpVarsNegLo.get(c);
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpVar.getAdjustedLowerLimit());
final int tmpKey = model.indexOf(tmpVar);
final double tmpFactor = tmpVar.getAdjustmentFactor();
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
}
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, ONE);
}
tmpConstrBaseIndex += tmpVarsNegLoLength;
final int tmpVarsNegUpLength = tmpVarsNegUp.size();
for (int c = 0; c < tmpVarsNegUpLength; c++) {
final Variable tmpVar = tmpVarsNegUp.get(c);
retVal.constraintsRHS().set(tmpConstrBaseIndex + c, -tmpVar.getAdjustedUpperLimit());
final int tmpKey = model.indexOf(tmpVar);
final double tmpFactor = tmpVar.getAdjustmentFactor();
final int tmpPosInd = model.indexOfPositiveVariable(tmpKey);
if (tmpPosInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpPosVarsBaseIndex + tmpPosInd, -tmpFactor);
}
final int tmpNegInd = model.indexOfNegativeVariable(tmpKey);
if (tmpNegInd >= 0) {
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpNegVarsBaseIndex + tmpNegInd, tmpFactor);
}
retVal.constraintsBody().set(tmpConstrBaseIndex + c, tmpCurrentSlackVarIndex++, NEG);
}
tmpConstrBaseIndex += tmpVarsNegUpLength;
if (retVal.getOvercapacity() <= OjAlgoUtils.ENVIRONMENT.getCacheElements(8L)) {
return retVal.toDense();
} else {
return retVal;
}
}
use of org.ojalgo.optimisation.ExpressionsBasedModel in project ojAlgo by optimatika.
the class ConvexProblems method buildModel.
static ExpressionsBasedModel buildModel(final PrimitiveDenseStore[] matrices, final PrimitiveDenseStore expectedSolution) {
final ExpressionsBasedModel retVal = new ExpressionsBasedModel();
final int tmpNumberOfVariables = (int) matrices[3].count();
for (int v = 0; v < tmpNumberOfVariables; v++) {
final Variable tmpVariable = Variable.make("X" + v);
tmpVariable.setValue(BigDecimal.valueOf(expectedSolution.doubleValue(v)));
retVal.addVariable(tmpVariable);
}
if ((matrices[0] != null) && (matrices[1] != null)) {
for (int e = 0; e < matrices[0].countRows(); e++) {
final Expression tmpExpression = retVal.addExpression("E" + e);
for (int v = 0; v < tmpNumberOfVariables; v++) {
tmpExpression.set(v, matrices[0].get(e, v));
}
tmpExpression.level(matrices[1].doubleValue(e));
}
}
if ((matrices[4] != null) && (matrices[5] != null)) {
for (int i = 0; i < matrices[4].countRows(); i++) {
final Expression tmpExpression = retVal.addExpression("I" + i);
for (int v = 0; v < tmpNumberOfVariables; v++) {
tmpExpression.set(v, matrices[4].get(i, v));
}
tmpExpression.upper(matrices[5].doubleValue(i));
}
}
final Expression tmpObjQ = retVal.addExpression("Q");
for (int r = 0; r < tmpNumberOfVariables; r++) {
for (int v = 0; v < tmpNumberOfVariables; v++) {
tmpObjQ.set(r, v, matrices[2].doubleValue(r, v));
}
}
tmpObjQ.weight(HALF);
final Expression tmpObjC = retVal.addExpression("C");
for (int v = 0; v < tmpNumberOfVariables; v++) {
tmpObjC.set(v, matrices[3].doubleValue(v));
}
tmpObjC.weight(NEG);
return retVal;
}
use of org.ojalgo.optimisation.ExpressionsBasedModel in project ojAlgo by optimatika.
the class ConvexProblems method testInfeasibleCase.
/**
* Just make sure an obviously infeasible problem is recognised as such - this has been a problem in the
* past
*/
@Test
public void testInfeasibleCase() {
final Variable[] tmpVariables = new Variable[] { new Variable("X1").lower(ONE).upper(TWO).weight(ONE), new Variable("X2").lower(ONE).upper(TWO).weight(TWO), new Variable("X3").lower(ONE).upper(TWO).weight(THREE) };
final ExpressionsBasedModel tmpModel = new ExpressionsBasedModel(tmpVariables);
final Expression tmpExprQ = tmpModel.addExpression("Q1");
for (int i = 0; i < tmpModel.countVariables(); i++) {
for (int j = 0; j < tmpModel.countVariables(); j++) {
tmpExprQ.set(i, i, Math.random());
}
}
// May not be positive definite, but infeasibillity should be realised before that becomes a problem
tmpExprQ.weight(TEN);
// tmpModel.options.debug(ConvexSolver.class);
final Expression tmpExprC1 = tmpModel.addExpression("C1");
for (int i = 0; i < tmpModel.countVariables(); i++) {
tmpExprC1.set(i, ONE);
}
tmpExprC1.upper(TWO);
Optimisation.Result tmpResult = tmpModel.maximise();
TestUtils.assertFalse(tmpResult.getState().isFeasible());
tmpExprC1.upper(null);
tmpExprC1.lower(SEVEN);
tmpResult = tmpModel.maximise();
TestUtils.assertFalse(tmpResult.getState().isFeasible());
OptimisationConvexTests.assertDirectAndIterativeEquals(tmpModel, null);
}
use of org.ojalgo.optimisation.ExpressionsBasedModel in project ojAlgo by optimatika.
the class FinancePortfolioProblem method buildModel.
private static ExpressionsBasedModel buildModel(final BasicMatrix covariances, final BasicMatrix returns, final BigDecimal riskAversion) {
ProgrammingError.throwIfNotSquare(covariances);
ProgrammingError.throwIfNotEqualRowDimensions(covariances, returns);
final int numberOfVariables = (int) returns.countRows();
final Variable[] tmpVariables = new Variable[numberOfVariables];
for (int i = 0; i < numberOfVariables; i++) {
tmpVariables[i] = Variable.make("Asset_" + Integer.toString(i)).lower(ZERO).upper(ONE).weight(-returns.doubleValue(i));
}
final ExpressionsBasedModel retVal = new ExpressionsBasedModel(tmpVariables);
final Expression tmp100P = retVal.addExpression("Balance");
for (int i = 0; i < numberOfVariables; i++) {
tmp100P.set(i, ONE);
}
tmp100P.level(ONE);
final Expression tmpVar = retVal.addExpression("Variance");
for (int i = 0; i < numberOfVariables; i++) {
for (int j = 0; j < numberOfVariables; j++) {
tmpVar.set(i, j, covariances.doubleValue(i, j));
}
}
tmpVar.weight(BigFunction.DIVIDE.invoke(riskAversion, TWO));
return retVal;
}
Aggregations