tpIFT7020/exemple/CarreMagique.java

117 lines
4.8 KiB
Java
Raw Normal View History

2018-02-02 05:24:44 +00:00
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();
}
}