117 lines
4.8 KiB
Java
117 lines
4.8 KiB
Java
|
import org.chocosolver.solver.Model;
|
||
|
import org.chocosolver.solver.Solver;
|
||
|
import org.chocosolver.solver.search.limits.FailCounter;
|
||
|
import org.chocosolver.solver.search.strategy.Search;
|
||
|
import org.chocosolver.solver.search.strategy.selectors.variables.DomOverWDeg;
|
||
|
import org.chocosolver.solver.search.strategy.selectors.variables.ImpactBased;
|
||
|
import org.chocosolver.solver.variables.IntVar;
|
||
|
|
||
|
public class CarreMagique {
|
||
|
public static final int HEURISTIQUE_DEFAUT = 0;
|
||
|
public static final int HEURISTIQUE_DOMOVERWDEG = 1;
|
||
|
public static final int HEURISTIQUE_IMPACT_BASED_SEARCH = 2;
|
||
|
public static final int HEURISTIQUE_ACTIVITY = 3;
|
||
|
public static final String COHERENCE_BORNES = "BC";
|
||
|
public static final String COHERENCE_DOMAINES = "AC";
|
||
|
|
||
|
public static final int RESTART_AUCUN = 0;
|
||
|
public static final int RESTART_LUBY = 1;
|
||
|
public static final int RESTART_GEOMETRIQUE = 2;
|
||
|
|
||
|
public static void main(String[] args) {
|
||
|
final int n = 12;
|
||
|
|
||
|
final int heuristique = HEURISTIQUE_ACTIVITY;
|
||
|
final boolean bris_symetries = true;
|
||
|
final int restart = RESTART_GEOMETRIQUE;
|
||
|
final String coherence = COHERENCE_BORNES;
|
||
|
|
||
|
Model model = new Model("Carré magique");
|
||
|
|
||
|
// Creation d'une matrice de dimensions n x n de variables dont les domaines sont les entiers de 1 a n^2.
|
||
|
IntVar[][] lignes = model.intVarMatrix("x", n, n, 1, n * n);
|
||
|
|
||
|
// Vecteur contenant toutes les variables de la matrice dans un seul vecteur
|
||
|
IntVar[] toutesLesVariables = new IntVar[n * n];
|
||
|
for (int i = 0; i < n * n; i++) {
|
||
|
toutesLesVariables[i] = lignes[i / n][i % n];
|
||
|
}
|
||
|
|
||
|
// Ajout d'une contrainte forcant toutes les variables a prendre des variables differentes
|
||
|
model.allDifferent(toutesLesVariables, coherence).post();
|
||
|
|
||
|
// Creation de la tranpose de la matrice lignes.
|
||
|
IntVar[][] colonnes = new IntVar[n][n];
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
for (int j = 0; j < n; j++) {
|
||
|
colonnes[i][j] = lignes[j][i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
final int sommeMagique = n * (n * n + 1) / 2;
|
||
|
|
||
|
// Creation d'une variable n'ayant qu'une seule valeur dans son domaine
|
||
|
IntVar variableSommeMagique = model.intVar(sommeMagique);
|
||
|
IntVar[] diagonale1 = new IntVar[n]; // Contient les variables sur la diagonale negative de la matrice
|
||
|
IntVar[] diagonale2 = new IntVar[n]; // Contient les variables sur la diagonale positive de la matrice
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
// Ajout de deux contraintes forcant les sommes des lignes et des colonnes a etre egales a la constante magique
|
||
|
model.sum(lignes[i], "=", variableSommeMagique).post();
|
||
|
model.sum(colonnes[i], "=", variableSommeMagique).post();
|
||
|
diagonale1[i] = lignes[i][i];
|
||
|
diagonale2[i] = lignes[n - i - 1][i];
|
||
|
}
|
||
|
model.sum(diagonale1, "=", variableSommeMagique).post();
|
||
|
model.sum(diagonale2, "=", variableSommeMagique).post();
|
||
|
|
||
|
if (bris_symetries) {
|
||
|
for (int i = 1; i < n / 2; i++)
|
||
|
model.arithm(lignes[i - 1][i - 1], "<", lignes[i][i]).post();
|
||
|
|
||
|
model.arithm(lignes[0][0], "<", lignes[n - 1][0]).post();
|
||
|
model.arithm(lignes[0][0], "<", lignes[0][n - 1]).post();
|
||
|
model.arithm(lignes[0][0], "<", lignes[n - 1][n - 1]).post();
|
||
|
// model.arithm(lignes[n - 1][0], "<", lignes[0][n - 1]).post();
|
||
|
}
|
||
|
|
||
|
// Creation du solveur
|
||
|
Solver solver = model.getSolver();
|
||
|
|
||
|
switch(heuristique) {
|
||
|
case HEURISTIQUE_DOMOVERWDEG:
|
||
|
solver.setSearch(Search.domOverWDegSearch(toutesLesVariables));
|
||
|
break;
|
||
|
case HEURISTIQUE_IMPACT_BASED_SEARCH:
|
||
|
solver.setSearch(new ImpactBased(toutesLesVariables, true));
|
||
|
break;
|
||
|
case HEURISTIQUE_ACTIVITY:
|
||
|
solver.setSearch(Search.activityBasedSearch(toutesLesVariables));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch(restart) {
|
||
|
case RESTART_LUBY:
|
||
|
solver.setLubyRestart(2, new FailCounter(model, 2), 25000);
|
||
|
break;
|
||
|
case RESTART_GEOMETRIQUE:
|
||
|
solver.setGeometricalRestart(2, 2.1, new FailCounter(model, 2), 25000);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
solver.findSolution();
|
||
|
|
||
|
for (int i = 0; i < n; i++) {
|
||
|
for (int j = 0; j < n; j++) {
|
||
|
if (lignes[i][j].getValue() < 10)
|
||
|
System.out.print(" ");
|
||
|
if (lignes[i][j].getValue() < 100)
|
||
|
System.out.print(" ");
|
||
|
System.out.print(lignes[i][j].getValue());
|
||
|
System.out.print(" ");
|
||
|
}
|
||
|
System.out.println("");
|
||
|
}
|
||
|
solver.printStatistics();
|
||
|
}
|
||
|
}
|