stub Party backtrack
This commit is contained in:
222
PartyStub.java
Normal file
222
PartyStub.java
Normal file
@@ -0,0 +1,222 @@
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This is a stub, you should rename the file to Party.java
|
||||
*
|
||||
* Party is a class to solve the party problem in general (not just for trees).
|
||||
*
|
||||
* The party problem takes a graph as input.
|
||||
* A vertex of this graph models a person.
|
||||
* Each vertex has a positive weight modelling the Person's fun factor.
|
||||
* An edge between two vertices indicates an incompatibility to organise a party : e.g. dislike, one person is a direct boss of the other etc.
|
||||
*
|
||||
* A Party is a subset of the vertices that are pairwise not connected by an edge (an independent set in graph jargon).
|
||||
* The sum of the fun factors of guests (member of the subset) evaluates the quality of the party.
|
||||
* The higher it is, the best it is.
|
||||
*
|
||||
* The Party Problem consists in computing the best possible party value / computing a solution with the best party value.
|
||||
*
|
||||
* In graph parlance, this problem is known as Maximum Weighted Independent Set. It is known to be NP-complete for general graphs as inputs.
|
||||
* This means that it is very unlikely that a polynomial time (in the size of the input graph) algorithm exists.
|
||||
*
|
||||
* This class proposes an exponential time algorithm that proceeds as follows.
|
||||
* It initialises the search with a greedy method to yield a lower bound on the best Party.
|
||||
* It proceeds with a backtracking method to search through (partial) parties.
|
||||
* A search may be cut off if :
|
||||
* adding the current vertex would not yield a Party (the added vertex is a neighbour of a vertex already present) above in the search; or,
|
||||
* adding all remaining vertices would not yield a Party better than the currently known best one (just pretend all remaining vertices would be added).
|
||||
*
|
||||
* @author Florent Madelaine
|
||||
*
|
||||
*/
|
||||
|
||||
public class Party {
|
||||
|
||||
// graphe (il faut des 0 et des 1) pour arêtes pas arêtes.
|
||||
private int[][] graphe;
|
||||
|
||||
// entier positifs ce sont les fun factors
|
||||
private int[] poids;
|
||||
|
||||
// pour marquer les éléments visités.
|
||||
private boolean[] marked;
|
||||
|
||||
// pour stocker la solution partielle en cours de fabrication
|
||||
private int[] psolution;
|
||||
|
||||
// valeur de la meilleur fête.
|
||||
private int best;
|
||||
|
||||
// meilleure solution jusqu'à présent
|
||||
private int[] bestParty;
|
||||
|
||||
/**
|
||||
* getter
|
||||
*
|
||||
* @return the value of the best known Party.
|
||||
*/
|
||||
public int getBest(){
|
||||
return this.best;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
*
|
||||
* @return the value of the best known Party.
|
||||
*/
|
||||
public int[] getBestParty(){
|
||||
return this.bestParty;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return a String representing the current state of the Party object
|
||||
*/
|
||||
public String toString(){
|
||||
String out = "";
|
||||
out+="poids: " + Arrays.toString(this.poids)+"\n";
|
||||
out+="graphe:\n"; //+ Arrays.deepToString(this.graphe)+"\n";
|
||||
for(int i = 0; i < this.graphe.length; i++){
|
||||
out+="\t" + Arrays.toString(graphe[i])+"\n";
|
||||
}
|
||||
out+="marked: "+ Arrays.toString(this.marked)+"\n";
|
||||
out+="psolution: " + Arrays.toString(this.psolution)+"\n";
|
||||
out+="bestParty: " + Arrays.toString(this.bestParty)+"\n";
|
||||
out+="best: "+ this.best+"\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*
|
||||
* @param graph a 0/1 (square) adjacency matrix
|
||||
* @param poids an array of int representing the weights of the vertices
|
||||
* @throws IllegalArgumentException if the matrix is not square or array of weights of inconsitent size with matrix.
|
||||
*/
|
||||
public Party(int[][] graphe, int[] poids){
|
||||
int n = graphe.length;
|
||||
if ((graphe[0].length != graphe.length) || (graphe.length != poids.length)) throw new IllegalArgumentException("graphe should be a square matrix of the same side as the length of poids.");
|
||||
|
||||
this.graphe=graphe;
|
||||
this.poids=poids;
|
||||
|
||||
this.marked = new boolean[n];
|
||||
this.psolution = new int[n];
|
||||
this.best=0;
|
||||
this.bestParty= new int[n];
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
*
|
||||
* @return the value of the current party (psolution).
|
||||
*/
|
||||
public int getCurrentPartyValue(){
|
||||
int res = 0;
|
||||
for(int i = 0; i < this.psolution.length; i++){
|
||||
res+= psolution[i]*poids[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
*
|
||||
* @param j an index in the solution that should represent the index to the left of which we have stored a partial solution.
|
||||
* @return the max value that the current party (psolution) could possibly reach (simulate adding vertices after j)
|
||||
*/
|
||||
public int getUpperBoundCurrentPartyValue(int j){
|
||||
// j should be an index of psolution
|
||||
int res = 0;
|
||||
for(int i = 0; i < this.psolution.length; i++){
|
||||
if (i<j){
|
||||
res+= psolution[i]*poids[i];
|
||||
}
|
||||
else{
|
||||
// à partir de j on compte le poids forcément.
|
||||
res+= poids[i];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to compute a first Party with a greedy method
|
||||
*
|
||||
* It sets bestParty to a bitmap representing a legal Party in a greedy fashion
|
||||
* It updates best to be the value of this computed party
|
||||
*/
|
||||
public void greedy(){
|
||||
// work here
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to search and compute the best Party using bactracking.
|
||||
* @param next represent the integer from which psolution (the current partial solution under study) should be extended
|
||||
*
|
||||
* If next is beyond psolution size, psolution is a complete candidate solution to the Party problem.
|
||||
* The method should update bestParty with this solution if it is better.
|
||||
* (you should clone the array to avoid problems).
|
||||
*
|
||||
* otherwise, if next falls within the bitmap, it will search the two cases one after the other
|
||||
* adding the vertex at index next to the psolution (case1)
|
||||
* or not adding this vertex (case2).
|
||||
* If both cases are legal / can not be removed from the search, it proceeds by caling backtrack with parameter next+1
|
||||
*/
|
||||
public void backtrack(int next){
|
||||
if (next >= psolution.length)
|
||||
{// fini de construire une solution
|
||||
|
||||
}
|
||||
else{
|
||||
// cas value=1 d'abord.
|
||||
int value =1;
|
||||
// mise à jour solution partielle si possible
|
||||
boolean ajoute = true;
|
||||
|
||||
// TO DO : tester si ajoute est OK sinon mettre ajoute à faux
|
||||
|
||||
if (ajoute){
|
||||
psolution[next]=value;
|
||||
|
||||
// TO DO : on pourrait peut-être s'arrêter?
|
||||
backtrack(next+1);
|
||||
|
||||
}
|
||||
// cas value=0 ensuite
|
||||
value=0
|
||||
|
||||
// TO DO
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
// A B C forment un triangle, E et D voisins de C.
|
||||
// poids 4, 5, 2, 6, 1.
|
||||
|
||||
int[][] graphe = {
|
||||
{ 0, 1, 1, 0, 0},
|
||||
{ 1, 0, 1, 0, 0},
|
||||
{ 1, 1, 0, 1, 1},
|
||||
{ 0, 0, 1, 0, 0},
|
||||
{ 0, 0, 1, 0, 0}
|
||||
};
|
||||
|
||||
int [] poids = {4,5,2,6,1};
|
||||
|
||||
Party p = new Party(graphe, poids);
|
||||
|
||||
p.greedy();
|
||||
System.out.println(Arrays.toString(p.getBestParty())); // Display the string.
|
||||
System.out.println(p.getBest()); // Display the best Pary
|
||||
|
||||
System.out.println(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user