Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create OLF Knitro AC solver extension #1

Merged
merged 59 commits into from
Dec 16, 2024
Merged
Changes from 1 commit
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
70a35be
OLF knitro solver extension
jeanneArchambault Nov 28, 2024
4ba4d36
Add target in gitignore
jeanneArchambault Nov 29, 2024
5bc4874
remove target folder
jeandemanged Nov 29, 2024
d4e63dc
checkstyle fix
jeandemanged Nov 29, 2024
2b8c66d
add logback-test
jeandemanged Nov 29, 2024
6c52e31
move to package com.powsybl.openloadflow.knitro.solver
jeandemanged Nov 29, 2024
3fa44e9
clean
jeandemanged Nov 29, 2024
5615319
clean
jeandemanged Nov 29, 2024
09ebcce
add PowsyblOpenLoadFlowKnitroSolverVersion
jeandemanged Nov 29, 2024
b708bca
rename ExternalSolverExtensionParameters to KnitroLoadFlowParameters
jeandemanged Nov 29, 2024
41b51e4
maven wrapper and CI
jeandemanged Nov 29, 2024
0d96433
fix mvnw permissions
jeandemanged Nov 29, 2024
35d25e2
delete unused test class
jeandemanged Nov 29, 2024
34b1f48
0.1.0-snapshot
jeandemanged Nov 29, 2024
5761e01
workaround kn finalization issue
jeandemanged Dec 3, 2024
1031f8d
fix
jeandemanged Dec 3, 2024
50e315f
Clean
jeanneArchambault Dec 4, 2024
9839a31
fix
jeandemanged Dec 4, 2024
796a887
Add CI
jeandemanged Dec 4, 2024
c6591ae
sonar cloud
jeandemanged Dec 4, 2024
57500a2
Add README.md
jeanneArchambault Dec 4, 2024
6542e0a
Merge branch 'init' of https://github.com/powsybl/powsybl-open-loadfl…
jeanneArchambault Dec 4, 2024
5e3b909
powsybl-core 6.6.0-RC1
jeandemanged Dec 5, 2024
67073a0
olf main branch
jeandemanged Dec 5, 2024
7628441
Update README file with installation/Setup instructions
jeanneArchambault Dec 5, 2024
39ced36
Merge branch 'init' of https://github.com/powsybl/powsybl-open-loadfl…
jeanneArchambault Dec 5, 2024
325c3fa
Delete useless class for knitro stopping criteria
jeanneArchambault Dec 11, 2024
2f0491f
Update knitro-interfaces version
jeanneArchambault Dec 11, 2024
23e0a0c
Clean
jeanneArchambault Dec 11, 2024
8f91034
Clean knitro
jeanneArchambault Dec 11, 2024
c486bba
Delete not usefull nonLinearConstraintsTypes list
jeanneArchambault Dec 11, 2024
acf66af
Clean
jeanneArchambault Dec 11, 2024
3190514
Clean
jeanneArchambault Dec 11, 2024
fca180f
FIXME CachingTest
jeanneArchambault Dec 11, 2024
35d1063
Clean
jeanneArchambault Dec 11, 2024
5b1509b
Clean
jeanneArchambault Dec 11, 2024
0cb79d2
Clean
jeanneArchambault Dec 11, 2024
893c86c
Bump to OLF v1.14.0 and password protect Knitro download (#3)
jeandemanged Dec 12, 2024
1cd8930
fix license header vs package ordering
jeandemanged Dec 12, 2024
dd0c0b9
use bridj from maven central + readme update
jeandemanged Dec 12, 2024
ef0a700
add LICENSE, gitignore update
jeandemanged Dec 12, 2024
5aa77c9
note on macOS
jeandemanged Dec 12, 2024
b3d8f75
note on knitro installation validation
jeandemanged Dec 13, 2024
040f12a
Add cron every 5 min (test)
jeanneArchambault Dec 13, 2024
b5c6fb4
Merge branch 'init' of https://github.com/powsybl/powsybl-open-loadfl…
jeanneArchambault Dec 13, 2024
8f80054
Solve sonarcloud issues
jeanneArchambault Dec 13, 2024
d60cb87
Add getter and setter for static field knitroParameters
jeanneArchambault Dec 13, 2024
ad4d31b
Delete useless equationId
jeanneArchambault Dec 13, 2024
156c4e1
Update pom
jeanneArchambault Dec 13, 2024
75153ee
Modify knitroParameters (make it non static + make it a parameter of …
jeanneArchambault Dec 13, 2024
f00d8f7
Revert "Update pom"
jeanneArchambault Dec 13, 2024
354b026
Add tests for knitroParameters
jeanneArchambault Dec 13, 2024
f507ddf
Delete cron + add test for Jacobian user routine + filter activated v…
jeanneArchambault Dec 13, 2024
e629bdd
Undo unvoluntary setting user routine
jeanneArchambault Dec 13, 2024
c900cb8
Modify gradient user routine test
jeanneArchambault Dec 13, 2024
ea4373d
better example Knitro output
jeandemanged Dec 13, 2024
5e81640
clean
jeandemanged Dec 13, 2024
b802754
clean
jeandemanged Dec 16, 2024
ed78aaf
clean
jeandemanged Dec 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
clean
Signed-off-by: Damien Jeandemange <damien.jeandemange@artelys.com>
jeandemanged committed Dec 16, 2024
commit b8027548e38e74dc2e60df3b6981208ecb026ee4
206 changes: 101 additions & 105 deletions src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroSolver.java
Original file line number Diff line number Diff line change
@@ -155,7 +155,7 @@ public List<Double> getUpperBounds() {
/**
* Handles initialization of the state vector.
*/
public class StateInitializer {
public static class StateInitializer {
private final List<Double> initialState;

public StateInitializer(LfNetwork lfNetwork, EquationSystem<AcVariableType, AcEquationType> equationSystem,
@@ -178,102 +178,6 @@ public List<Double> getInitialState() {
}
}

/**
* Adds constraints to the Knitro problem, classifying them as linear or non-linear.
*
* @param knitroProblem The Knitro problem to which constraints are added.
* @param sortedEquationsToSolve A list of equations to solve.
* @param solverUtils Utils for solving external non-linear equations.
* @param listNonLinearConsts A list to store ids of non-linear constraints.
*/
public void addLinearConstraints(KnitroProblem knitroProblem,
List<Equation<AcVariableType, AcEquationType>> sortedEquationsToSolve,
NonLinearExternalSolverUtils solverUtils, List<Integer> listNonLinearConsts) {

int numConst = sortedEquationsToSolve.size();

for (int equationId = 0; equationId < numConst; equationId++) {
addConstraint(equationId, knitroProblem, sortedEquationsToSolve, solverUtils, listNonLinearConsts);
}
}

/**
* Adds a specific constraint to the Knitro problem, classifying it as linear or non-linear.
*
* @param equationId The id of the equation.
* @param knitroProblem The Knitro problem to which the constraint is added.
* @param sortedEquationsToSolve A list of equations to solve.
* @param solverUtils Utils for solving external non-linear equations.
* @param listNonLinearConsts A list to store ids of non-linear constraints.
*/
public void addConstraint(int equationId, KnitroProblem knitroProblem, List<Equation<AcVariableType, AcEquationType>> sortedEquationsToSolve, NonLinearExternalSolverUtils solverUtils, List<Integer> listNonLinearConsts) {
Equation<AcVariableType, AcEquationType> equation = sortedEquationsToSolve.get(equationId);
AcEquationType typeEq = equation.getType();
List<EquationTerm<AcVariableType, AcEquationType>> terms = equation.getTerms();

if (NonLinearExternalSolverUtils.isLinear(typeEq, terms)) {
try {
List<Integer> listVar = solverUtils.getLinearConstraint(typeEq, terms).getListIdVar();

List<Double> listCoef = solverUtils.getLinearConstraint(typeEq, terms).getListCoef();

for (int i = 0; i < listVar.size(); i++) {
knitroProblem.addConstraintLinearPart(equationId, listVar.get(i), listCoef.get(i));
}
LOGGER.trace("Adding linear constraint n° {} of type {}", equationId, typeEq);
} catch (UnsupportedOperationException e) {
throw new PowsyblException(e);
}
} else {
// ----- Non-linear constraints -----
listNonLinearConsts.add(equationId); // Add constraint number to list of non-linear constraints
}
}

/**
* Configures the Jacobian matrix for the Knitro problem, using either a dense or sparse representation.
*
* @param knitroProblem The Knitro problem instance.
* @param lfNetwork The PowSyBl network.
* @param jacobianMatrix The PowSyBl Jacobian matrix.
* @param sortedEquationsToSolve The list of equations to solve.
* @param listNonLinearConsts The list of non-linear constraint ids.
* @param listNonZerosCtsDense Dense non-zero constraints.
* @param listNonZerosVarsDense Dense non-zero variables.
* @param listNonZerosCtsSparse Sparse non-zero constraints.
* @param listNonZerosVarsSparse Sparse non-zero variables.
* @throws KNException If an error occurs in Knitro operations.
*/
public void setJacobianMatrix(KnitroProblem knitroProblem, LfNetwork lfNetwork, JacobianMatrix<AcVariableType, AcEquationType> jacobianMatrix,
List<Equation<AcVariableType, AcEquationType>> sortedEquationsToSolve, List<Integer> listNonLinearConsts,
List<Integer> listNonZerosCtsDense, List<Integer> listNonZerosVarsDense,
List<Integer> listNonZerosCtsSparse, List<Integer> listNonZerosVarsSparse) throws KNException {

int numVar = equationSystem.getIndex().getSortedVariablesToFind().size();
if (knitroParameters.getGradientComputationMode() == 1) { // User routine to compute the Jacobian
if (knitroParameters.getGradientUserRoutine() == 1) {
// Dense method: all non-linear constraints are considered as a function of all variables.
buildDenseJacobianMatrix(numVar, listNonLinearConsts, listNonZerosCtsDense, listNonZerosVarsDense);
knitroProblem.setJacNnzPattern(listNonZerosCtsDense, listNonZerosVarsDense);
} else if (knitroParameters.getGradientUserRoutine() == 2) {
// Sparse method: compute Jacobian only for variables the constraints depend on.
buildSparseJacobianMatrix(sortedEquationsToSolve, listNonLinearConsts, listNonZerosCtsSparse, listNonZerosVarsSparse);
knitroProblem.setJacNnzPattern(listNonZerosCtsSparse, listNonZerosVarsSparse);
}
// Set the callback for gradient evaluations if the user directly passes the Jacobian to the solver.
knitroProblem.setGradEvalCallback(new KnitroProblem.CallbackEvalG(
jacobianMatrix,
listNonZerosCtsDense,
listNonZerosVarsDense,
listNonZerosCtsSparse,
listNonZerosVarsSparse,
lfNetwork,
equationSystem,
knitroParameters
));
}
}

public void buildDenseJacobianMatrix(int numVar, List<Integer> listNonLinearConsts, List<Integer> listNonZerosCtsDense, List<Integer> listNonZerosVarsDense) {
for (Integer idCt : listNonLinearConsts) {
for (int i = 0; i < numVar; i++) {
@@ -298,7 +202,7 @@ public void buildSparseJacobianMatrix(List<Equation<AcVariableType, AcEquationTy
List<Integer> listNonZerosVarsCurrentCt = new ArrayList<>(); //list of variables involved in current constraint

for (EquationTerm<AcVariableType, AcEquationType> term : terms) {
for (Variable variable : term.getVariables()) {
for (Variable<AcVariableType> variable : term.getVariables()) {
listNonZerosVarsCurrentCt.add(variable.getRow());
}
}
@@ -315,7 +219,7 @@ private final class KnitroProblem extends KNProblem {
* Callback function to evaluate non-linear parts of the objective and of constraints
*/

private final class CallbackEvalFC extends KNEvalFCCallback {
private static final class CallbackEvalFC extends KNEvalFCCallback {

private final List<Equation<AcVariableType, AcEquationType>> sortedEquationsToSolve;
private final List<Integer> listNonLinearConsts;
@@ -347,7 +251,7 @@ public void evaluateFC(final List<Double> x, final List<Double> obj, final List<
throw new IllegalArgumentException("Equation of type " + typeEq + " is linear, and should be considered in the main function of Knitro, not in the callback function");
} else {
// we evaluate the equation with respect to the current state
for (EquationTerm term : equation.getTerms()) {
for (EquationTerm<AcVariableType, AcEquationType> term : equation.getTerms()) {
term.setStateVector(currentState);
if (term.isActive()) {
valueConst += term.eval();
@@ -468,7 +372,7 @@ public void evaluateH(final List<Double> x, final double sigma, final List<Doubl
* - definition of non-linear constraints, evaluated in the callback function
* - definition of the Jacobian matrix passed to Knitro to solve the problem
*/
private KnitroProblem(LfNetwork lfNetwork, EquationSystem<AcVariableType, AcEquationType> equationSystem, TargetVector targetVector, VoltageInitializer voltageInitializer, JacobianMatrix<AcVariableType, AcEquationType> jacobianMatrix) throws KNException {
private KnitroProblem(LfNetwork lfNetwork, EquationSystem<AcVariableType, AcEquationType> equationSystem, TargetVector<AcVariableType, AcEquationType> targetVector, VoltageInitializer voltageInitializer, JacobianMatrix<AcVariableType, AcEquationType> jacobianMatrix) throws KNException {

// =============== Variables ===============
// Defining variables
@@ -502,7 +406,7 @@ private KnitroProblem(LfNetwork lfNetwork, EquationSystem<AcVariableType, AcEqua

// ----- Linear constraints -----
NonLinearExternalSolverUtils solverUtils = new NonLinearExternalSolverUtils();
addLinearConstraints(this, sortedEquationsToSolve, solverUtils, listNonLinearConsts); // add linear constraints and fill the list of non-linear constraints
addLinearConstraints(sortedEquationsToSolve, solverUtils, listNonLinearConsts); // add linear constraints and fill the list of non-linear constraints

// ----- Non-linear constraints -----
// Callback
@@ -526,10 +430,102 @@ private KnitroProblem(LfNetwork lfNetwork, EquationSystem<AcVariableType, AcEqua
List<Integer> listNonZerosCtsSparse = new ArrayList<>();
List<Integer> listNonZerosVarsSparse = new ArrayList<>();

setJacobianMatrix(this, lfNetwork, jacobianMatrix, sortedEquationsToSolve, listNonLinearConsts,
setJacobianMatrix(lfNetwork, jacobianMatrix, sortedEquationsToSolve, listNonLinearConsts,
listNonZerosCtsDense, listNonZerosVarsDense,
listNonZerosCtsSparse, listNonZerosVarsSparse);
}

/**
* Adds constraints to the Knitro problem, classifying them as linear or non-linear.
*
* @param sortedEquationsToSolve A list of equations to solve.
* @param solverUtils Utils for solving external non-linear equations.
* @param listNonLinearConsts A list to store ids of non-linear constraints.
*/
private void addLinearConstraints(List<Equation<AcVariableType, AcEquationType>> sortedEquationsToSolve,
NonLinearExternalSolverUtils solverUtils, List<Integer> listNonLinearConsts) {

int numConst = sortedEquationsToSolve.size();

for (int equationId = 0; equationId < numConst; equationId++) {
addConstraint(equationId, sortedEquationsToSolve, solverUtils, listNonLinearConsts);
}
}

/**
* Adds a specific constraint to the Knitro problem, classifying it as linear or non-linear.
*
* @param equationId The id of the equation.
* @param sortedEquationsToSolve A list of equations to solve.
* @param solverUtils Utils for solving external non-linear equations.
* @param listNonLinearConsts A list to store ids of non-linear constraints.
*/
private void addConstraint(int equationId, List<Equation<AcVariableType, AcEquationType>> sortedEquationsToSolve, NonLinearExternalSolverUtils solverUtils, List<Integer> listNonLinearConsts) {
Equation<AcVariableType, AcEquationType> equation = sortedEquationsToSolve.get(equationId);
AcEquationType typeEq = equation.getType();
List<EquationTerm<AcVariableType, AcEquationType>> terms = equation.getTerms();

if (NonLinearExternalSolverUtils.isLinear(typeEq, terms)) {
try {
List<Integer> listVar = solverUtils.getLinearConstraint(typeEq, terms).listIdVar();

List<Double> listCoef = solverUtils.getLinearConstraint(typeEq, terms).listCoef();

for (int i = 0; i < listVar.size(); i++) {
this.addConstraintLinearPart(equationId, listVar.get(i), listCoef.get(i));
}
LOGGER.trace("Adding linear constraint n° {} of type {}", equationId, typeEq);
} catch (UnsupportedOperationException e) {
throw new PowsyblException(e);
}
} else {
// ----- Non-linear constraints -----
listNonLinearConsts.add(equationId); // Add constraint number to list of non-linear constraints
}
}

/**
* Configures the Jacobian matrix for the Knitro problem, using either a dense or sparse representation.
*
* @param lfNetwork The PowSyBl network.
* @param jacobianMatrix The PowSyBl Jacobian matrix.
* @param sortedEquationsToSolve The list of equations to solve.
* @param listNonLinearConsts The list of non-linear constraint ids.
* @param listNonZerosCtsDense Dense non-zero constraints.
* @param listNonZerosVarsDense Dense non-zero variables.
* @param listNonZerosCtsSparse Sparse non-zero constraints.
* @param listNonZerosVarsSparse Sparse non-zero variables.
* @throws KNException If an error occurs in Knitro operations.
*/
private void setJacobianMatrix(LfNetwork lfNetwork, JacobianMatrix<AcVariableType, AcEquationType> jacobianMatrix,
List<Equation<AcVariableType, AcEquationType>> sortedEquationsToSolve, List<Integer> listNonLinearConsts,
List<Integer> listNonZerosCtsDense, List<Integer> listNonZerosVarsDense,
List<Integer> listNonZerosCtsSparse, List<Integer> listNonZerosVarsSparse) throws KNException {

int numVar = equationSystem.getIndex().getSortedVariablesToFind().size();
if (knitroParameters.getGradientComputationMode() == 1) { // User routine to compute the Jacobian
if (knitroParameters.getGradientUserRoutine() == 1) {
// Dense method: all non-linear constraints are considered as a function of all variables.
buildDenseJacobianMatrix(numVar, listNonLinearConsts, listNonZerosCtsDense, listNonZerosVarsDense);
this.setJacNnzPattern(listNonZerosCtsDense, listNonZerosVarsDense);
} else if (knitroParameters.getGradientUserRoutine() == 2) {
// Sparse method: compute Jacobian only for variables the constraints depend on.
buildSparseJacobianMatrix(sortedEquationsToSolve, listNonLinearConsts, listNonZerosCtsSparse, listNonZerosVarsSparse);
this.setJacNnzPattern(listNonZerosCtsSparse, listNonZerosVarsSparse);
}
// Set the callback for gradient evaluations if the user directly passes the Jacobian to the solver.
this.setGradEvalCallback(new KnitroProblem.CallbackEvalG(
jacobianMatrix,
listNonZerosCtsDense,
listNonZerosVarsDense,
listNonZerosCtsSparse,
listNonZerosVarsSparse,
lfNetwork,
equationSystem,
knitroParameters
));
}
}
}

private void setSolverParameters(KNSolver solver) throws KNException {
@@ -562,7 +558,7 @@ public void close() {

@Override
public AcSolverResult run(VoltageInitializer voltageInitializer, ReportNode reportNode) {
int nbIter = -1;
int nbIter;
AcSolverStatus acStatus;
KnitroProblem instance;

@@ -610,7 +606,7 @@ public AcSolverResult run(VoltageInitializer voltageInitializer, ReportNode repo
if (acStatus == AcSolverStatus.CONVERGED || knitroParameters.isAlwaysUpdateNetwork()) {
equationSystem.getStateVector().set(toArray(solution.getX())); // update equation system
for (Equation<AcVariableType, AcEquationType> equation : equationSystem.getEquations()) { // update terms
for (EquationTerm term : equation.getTerms()) {
for (EquationTerm<AcVariableType, AcEquationType> term : equation.getTerms()) {
term.setStateVector(equationSystem.getStateVector());
}
}
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ public double getLowerVoltageBound() {

public KnitroSolverParameters setLowerVoltageBound(double lowerVoltageBound) {
if (lowerVoltageBound < 0) {
throw new IllegalArgumentException("Realistic voltage bounds must strictly greater then 0");
throw new IllegalArgumentException("Realistic voltage bounds must strictly greater than 0");
}
this.lowerVoltageBound = lowerVoltageBound;
return this;
@@ -93,10 +93,10 @@ public double getUpperVoltageBound() {

public KnitroSolverParameters setUpperVoltageBound(double upperVoltageBound) {
if (upperVoltageBound < 0) {
throw new IllegalArgumentException("Realistic voltage bounds must strictly greater then 0");
throw new IllegalArgumentException("Realistic voltage bounds must strictly greater than 0");
}
if (upperVoltageBound <= lowerVoltageBound) {
throw new IllegalArgumentException("Realistic voltage upper bounds must greater then lower bounds");
throw new IllegalArgumentException("Realistic voltage upper bounds must greater than lower bounds");
}
this.upperVoltageBound = upperVoltageBound;
return this;
Original file line number Diff line number Diff line change
@@ -66,22 +66,7 @@ public VarAndCoefList getLinearConstraint(AcEquationType typeEq, List<EquationTe
return varAndCoefList;
}

public class VarAndCoefList {
private List<Integer> listIdVar;
private List<Double> listCoef;

public VarAndCoefList(List<Integer> listIdVar, List<Double> listCoef) {
this.listIdVar = listIdVar;
this.listCoef = listCoef;
}

public List<Integer> getListIdVar() {
return listIdVar;
}

public List<Double> getListCoef() {
return listCoef;
}
public record VarAndCoefList(List<Integer> listIdVar, List<Double> listCoef) {
}

public VarAndCoefList addConstraintConstantTarget(List<EquationTerm<AcVariableType, AcEquationType>> terms) {
Loading