Commit 81968fb8 authored by Tom Lampert's avatar Tom Lampert

CPClustering integrated

parent 11ef9d37
all: cpclustering compcons
# What other files to compile
OBJS1=commonFunction.o initFunctions.o cpCluster.o branchDiameterMLCL.o diameterConstraint.o diameterConstraintMLCL.o
#branchGreedy.o
OBJS2=commonFunction.o initFunctions.o cpClusterCC.o branchDiameter.o branchDiameterMLCL.o diameterConstraint.o splitConstraint.o diameterConstraintMLCL.o
# What file to compile to./
MAINFILE=cpclustering compcons
#CXX = g++ -I/usr/local/include
CC = LD_RUN_PATH=/usr/local/lib g++ -O3 -g -DNDEBUG -Wall -std=c++11
#CC = g++
ifdef GECODEDIR
CCI=-I$(GECODEDIR)/include
CCL=-L$(GECODEDIR)/lib
endif
ifdef GECODE_HOME
CCI=-I$(GECODE_HOME)
CCL=-L$(GECODE_HOME)
endif
#linker config
LOADLIBES = -lgecodeflatzinc -lgecodedriver -lgecodesearch -lgecodeminimodel -lgecodeset -lgecodefloat -lgecodeint -lgecodekernel -lgecodesupport -lpthread -lgecodegist
cpclustering: $(OBJS1) main.o
$(CC) -o $@ $^ $(CCL) $(LOADLIBES)
fzn-gecode: $(OBJS1) fzn-gecode.o
$(CC) -o $@ $^ $(CCL) $(LOADLIBES)
compcons: $(OBJS2) mainCC.o
$(CC) -o $@ $^ $(CCL) $(LOADLIBES)
# $(CC) -o $@ $^ $(CCL) $(LOADLIBES) -rpath $(QTDIR)/lib
clean:
rm -rf *o $(MAINFILE)
%.o: %.cpp
$(CC) $(CCI) -o $@ -c $<
depends:
$(CC) -MM $(CCI) *.cpp
# output of 'make depends', to get recompilation right
branchDiameter.o: branchDiameter.cpp branchDiameter.h
branchDiameterMLCL.o: branchDiameterMLCL.cpp branchDiameterMLCL.h
branchWCSD.o: branchWCSD.cpp branchWCSD.h
commonFunction.o: commonFunction.cpp commonFunction.h
cpCluster.o: cpCluster.cpp clusterOptions.h commonFunction.h cpCluster.h \
branchDiameter.h diameterConstraint.h splitConstraint.h branchDiameterMLCL.h diameterConstraintMLCL.h
diameterConstraint.2.o: diameterConstraint.2.cpp diameterConstraint.h
diameterConstraint.o: diameterConstraint.cpp diameterConstraint.h
diameterConstraintMLCL.o: diameterConstraintMLCL.cpp diameterConstraintMLCL.h
initFunctions.o: initFunctions.cpp clusterOptions.h commonFunction.h \
initFunctions.h
main.o: main.cpp clusterOptions.h commonFunction.h initFunctions.h \
cpCluster.h
mainCC.o: mainCC.cpp clusterOptions.h commonFunction.h initFunctions.h \
cpCluster.h
splitConstraint.o: splitConstraint.cpp splitConstraint.h
wcsdConstraint.o: wcsdConstraint.cpp wcsdConstraint.h
07/06/17
cpCluster:
- ajout d'une fonction getD()
- ajout de la méthode instantiate() affecte une valeur aux points ignoré
- ajout attribut static vector<double> dmax initialisé dans le main
branchDiameterMLCL:
- status() vérifie qu'il ne reste que des points ignorables
- choice() ne prend pas en compte les points ignorable max(dist_i)<= d.min
diameterConstraintMLCL:
-ajout d'un attribut vector<int> assigned_id pour garder en mémoire les id des point assignés
- modification de la fonction propagate pour affecter les point ignoré au cluster le plus proche
Bich:
- il semble que nous avons décidé que ignorer des points sera à la
charge de branchDiameterMLCL. Si c'est le cas il ne faut pas modifier
diameterConstraint. Il a-t-il une autre raison pour le modifier ?
- affecter les points ignorés au cluster le plus proche doit être fait
dans CPCluster, pourquoi faire dans le propagateur diameterConstraint ? rappelons que le
propagateur s'actif à chaque état, or il faut attendre la fin pour
affecter les points ignorés.
- dMax en static mais en cpCluster n'est pas convainquant. A mettre
comme pour ddMax
- la fonction instantiate() dans cpCluster telle quelle n'est pas
correcte: clustDist n'est pas réinitié pour chaque nouveau point non
instantié !
================================================================================
08/06/17
CPCluster:
- correction de la fonction instantiate()
DiameterConstraintMLCL:
- suppression de l'affectation des points ignorés
externalData.h:
j'ai crée ce fichier afin de rendre accessible dmax et constrained sans modifier les paramétres des fonctions existantes
- variable externe vector<double> dmax contient la distance maximale de chaque point
- variable externe vector<bool> constrained garde en mémoire les points constraints
================================================================================
12/06/17
CPCluster:
- ajout d'une nouvelle méthodes d'affectation pour les points ignorés, affectation au centroid le plus proche avec recalcul du centroid après affectation
- ajout méthode K-medoid pour l'affectation des points ignorés
================================================================================
13/06/17
clusterOptions.h:
- ajout de l'option -pr pour choisir la méthode de propagation des résultats
================================================================================
20/06/17
main.cpp:
-ajout catch signal SIGINT (^C)
-plusieurs variables ont été rendu globales
================================================================================
21/06/17
main.cpp:
- ajout timeout option -time en milliseconds
- -pr -1 => toutes les affectation créer un fichier de résultats pour chaque méthodes d'affectation
================================================================================
11/07/17
commonFunction:
- ajout d'une fonction sort_indexes : retourne les index d'un vector trié
- ajout d'une fonction most_frequent_element : retourne la valeur la plus fréquente d'un vector
CPCluster:
- ajout de l'affectation utilisant KNN
main:
- modifier #define KNN_AFFECT_K pour changer le K de l'affectation KNN
#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/float.hh>
#include <gecode/set.hh>
#include <gecode/minimodel.hh>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <sys/resource.h>
#include <vector>
#include <math.h>
#include <algorithm>
#include "branchDiameter.h"
using namespace Gecode;
using namespace std;
/// Return choice
Gecode::Choice* branchDiameter::choice(Space&) {
int n = x.size();
unsigned int i = start;
// find first unassigned variable with smallest domain
for (int j = start+1; j < n; j++)
if (!x[j].assigned() && x[i].size() > x[j].size())
i = j;
int k = x[0].max();
// compute k = number of possible clusters
for (int i=0; i<n; i++)
if (k<x[i].max())
k = x[i].max();
k += 1; // since number of cluster= max cluster indices +1
// choose value for x[i]
int bestVal=-1;
double bestDist;
double clusDist[k];
if (closest_point) {
// compute closest point for each cluster
for (int t = 0; t < k; t++)
clusDist[t] = INT_MAX;
for (int t = 0; t < start; t++) {
int v = x[t].val();
if (x[i].in(v))
if (dd[i][t] < clusDist[v])
clusDist[v] = dd[i][t];
}
} else { // furthest point
// compute furthest point for each cluster
for (int t = 0; t < k; t++)
clusDist[t] = 0;
// for (int t = 0; t < start; t++) {
for (int t = 0; t < n; t++)
if (x[t].assigned()) {
int v = x[t].val();
if (x[i].in(v))
if (dd[i][t] > clusDist[v])
clusDist[v] = dd[i][t];
}
}
if (closest_clus) {
// take cluster of closest 'check'
bestDist = INT_MAX;
for (int c = 0; c < k; c++)
if (x[i].in(c))
if (bestDist > clusDist[c]) {
bestDist = clusDist[c];
bestVal = c;
}
} else {
// take cluster of furthest 'check'
bestDist = 0;
for (int c = 0; c < k; c++)
if (x[i].in(c))
if (bestDist <= clusDist[c]) {
bestDist = clusDist[c];
bestVal = c;
}
}
// can do all choices as var order is fixed?
return new Choice(*this,i,bestVal); // assign G[i] = minVal, G[i] != minVal
}
#ifndef BRANCH_DIAMETER
#define BRANCH_DIAMETER
#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/float.hh>
#include <gecode/set.hh>
#include <gecode/minimodel.hh>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <sys/resource.h>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace Gecode;
using namespace std;
/*
* value branching
* for each cluster, find furthest point
* then choose cluster with closest of those
*
* true false = closest clus with furthest point
* true true = closest clus with closest point
* false true = futhest clus with closets point
* false false = furthest clus with furthest point
*/
class branchDiameter : public Brancher {
protected:
/// Views of the brancher
ViewArray<Int::IntView> x; // x is the variables G
/// distance matrice
vector< vector<double> >& dd;
/// Next variable to branch on
mutable int start; // start is the first point that is unassigned
bool closest_clus;
bool closest_point;
/// %Choice
class Choice : public Gecode::Choice {
public:
/// Position of variable
int pos;
/// Value of variable
int val;
/** Initialize choice for brancher \a b, position \a pos0,
* and value \a val0.
*/
Choice(const Brancher& b, int pos0, int val0)
: Gecode::Choice(b,2), pos(pos0), val(val0) {}
/// Report size occupied
virtual size_t size(void) const {
return sizeof(Choice);
}
/// Archive into \a e
virtual void archive(Archive& e) const {
Gecode::Choice::archive(e);
e << pos << val;
}
};
/// Construct brancher
branchDiameter(Home home, ViewArray<Int::IntView>& xv, vector< vector<double> >& mat, bool clo_clu, bool clo_pnt)
: Brancher(home), x(xv), dd(mat), start(0), closest_clus(clo_clu), closest_point(clo_pnt) {}
/// Copy constructor
branchDiameter(Space& home, bool share, branchDiameter& b)
: Brancher(home, share, b), dd(b.dd), start(b.start), closest_clus(b.closest_clus), closest_point(b.closest_point) {
x.update(home, share, b.x);
}
public:
/// Check status of brancher, return true if alternatives left
virtual bool status(const Space&) const {
for (int i=start; i<x.size(); i++)
if (!x[i].assigned()) {
start = i; return true;
}
return false;
}
/// Return choice
virtual Gecode::Choice* choice(Space&); /// Return choice
virtual Choice* choice(const Space&, Archive& e) {
int pos, val;
e >> pos >> val;
return new Choice(*this, pos, val);
}
/// Perform commit for choice \a _c and alternative \a a
virtual ExecStatus commit(Space& home, const Gecode::Choice& _c, unsigned int a) {
const Choice& c = static_cast<const Choice&>(_c);
if (a == 0)
return me_failed(x[c.pos].eq(home, c.val)) ? ES_FAILED : ES_OK;
else
return me_failed(x[c.pos].nq(home, c.val)) ? ES_FAILED : ES_OK;
}
/// Copy brancher
virtual Actor* copy(Space& home, bool share) {
return new (home) branchDiameter(home, share, *this);
}
/// Post brancher
static void post(Home home, const IntVarArgs& x, vector< vector<double> >& dd,
bool clo_clu=true, bool clo_pnt=false) {
ViewArray<Int::IntView> xv(home, x);
(void) new (home) branchDiameter(home, xv, dd, clo_clu, clo_pnt);
}
/// Delete brancher and return its size
virtual size_t dispose(Space&) {
return sizeof(*this);
}
};
#endif
#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/float.hh>
#include <gecode/set.hh>
#include <gecode/minimodel.hh>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <sys/resource.h>
#include <vector>
#include <math.h>
#include <algorithm>
#include "branchDiameterMLCL.h"
#include "cpCluster.h"
#include "externalData.h"
using namespace Gecode;
using namespace std;
bool branchDiameterMLCL::status(const Space& s) const {
const CPCluster& cp = static_cast<const CPCluster&>(s);
float diameter = cp.getD().min();
for (int i=start; i<x.size(); i++)
if (!x[i].assigned() && ((dmax[i] > diameter) || constrained[i])) {
start = i; return true;
}
return false;
}
/// Return choice
Gecode::Choice* branchDiameterMLCL::choice(Space& s) {
int n = x.size();
unsigned int i = start;
float diameter = static_cast<CPCluster&>(s).getD().min();
// find first unassigned variable with smallest domain
for (int j = start+1; j < n; j++){
if (!x[j].assigned() && x[i].size() > x[j].size() &&( (dmax[j] > diameter) || constrained[j])){
i = j;
}
}
int k = x[0].max();
// compute k = number of possible clusters
for (int i=0; i<n; i++){
if (k<x[i].max())
k = x[i].max();
}
k += 1; // since number of cluster= max cluster indices +1
// choose value for x[i]
int bestVal=-1;
double bestDist;
double clusDist[k];
if (closest_point) {
// compute closest point for each cluster
for (int t = 0; t < k; t++)
clusDist[t] = INT_MAX;
for (int t = 0; t < start; t++) {
int v = x[t].val();
if (x[i].in(v))
if (dd[i][t] < clusDist[v])
clusDist[v] = dd[i][t];
}
} else { // furthest point
// compute furthest point for each cluster
for (int t = 0; t < k; t++)
clusDist[t] = 0;
// for (int t = 0; t < start; t++) {
for (int t = 0; t < n; t++)
if (x[t].assigned()) {
int v = x[t].val();
if (x[i].in(v))
if (dd[i][t] > clusDist[v])
clusDist[v] = dd[i][t];
}
}
if (closest_clus) {
// take cluster of closest 'check'
bestDist = INT_MAX;
for (int c = 0; c < k; c++)
if (x[i].in(c))
if (bestDist > clusDist[c]) {
bestDist = clusDist[c];
bestVal = c;
}
} else {
// take cluster of furthest 'check'
bestDist = 0;
for (int c = 0; c < k; c++)
if (x[i].in(c))
if (bestDist <= clusDist[c]) {
bestDist = clusDist[c];
bestVal = c;
}
}
// can do all choices as var order is fixed?
return new Choice(*this,i,bestVal); // assign G[i] = minVal, G[i] != minVal
}
#ifndef BRANCH_DIAMETER_MLCL
#define BRANCH_DIAMETER_MLCL
#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/float.hh>
#include <gecode/set.hh>
#include <gecode/minimodel.hh>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <sys/resource.h>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace Gecode;
using namespace std;
/*
* value branching
* for each cluster, find furthest point
* then choose cluster with closest of those
*
* true false = closest clus with furthest point
* true true = closest clus with closest point
* false true = futhest clus with closets point
* false false = furthest clus with furthest point
*/
class branchDiameterMLCL : public Brancher {
protected:
/// Views of the brancher
ViewArray<Int::IntView> x; // x is the variables G
/// distance matrice
vector< vector<double> >& dd;
/// Next variable to branch on
mutable int start; // start is the first point that is unassigned
bool closest_clus;
bool closest_point;
/// %Choice
class Choice : public Gecode::Choice {
public:
/// Position of variable
int pos;
/// Value of variable
int val;
/** Initialize choice for brancher \a b, position \a pos0,
* and value \a val0.
*/
Choice(const Brancher& b, int pos0, int val0)
: Gecode::Choice(b,2), pos(pos0), val(val0) {}
/// Report size occupied
virtual size_t size(void) const {
return sizeof(Choice);
}
/// Archive into \a e
virtual void archive(Archive& e) const {
Gecode::Choice::archive(e);
e << pos << val;
}
};
/// Construct brancher
branchDiameterMLCL(Home home, ViewArray<Int::IntView>& xv, vector< vector<double> >& mat, bool clo_clu, bool clo_pnt)
: Brancher(home), x(xv), dd(mat), start(0), closest_clus(clo_clu), closest_point(clo_pnt) {}
/// Copy constructor
branchDiameterMLCL(Space& home, bool share, branchDiameterMLCL& b)
: Brancher(home, share, b), dd(b.dd), start(b.start), closest_clus(b.closest_clus), closest_point(b.closest_point) {
x.update(home, share, b.x);
}
public:
/// Check status of brancher, return true if alternatives left
virtual bool status(const Space& s) const;
/// Return choice
virtual Gecode::Choice* choice(Space&); /// Return choice
virtual Choice* choice(const Space&, Archive& e) {
int pos, val;
e >> pos >> val;
return new Choice(*this, pos, val);
}
/// Perform commit for choice \a _c and alternative \a a
virtual ExecStatus commit(Space& home, const Gecode::Choice& _c, unsigned int a) {
const Choice& c = static_cast<const Choice&>(_c);
if (a == 0)
return me_failed(x[c.pos].eq(home, c.val)) ? ES_FAILED : ES_OK;
else
return me_failed(x[c.pos].nq(home, c.val)) ? ES_FAILED : ES_OK;
}
/// Copy brancher
virtual Actor* copy(Space& home, bool share) {
return new (home) branchDiameterMLCL(home, share, *this);
}
/// Post brancher
static void post(Home home, const IntVarArgs& x, vector< vector<double> >& dd,
bool clo_clu=true, bool clo_pnt=false) {
ViewArray<Int::IntView> xv(home, x);
(void) new (home) branchDiameterMLCL(home, xv, dd, clo_clu, clo_pnt);
}
/// Delete brancher and return its size
virtual size_t dispose(Space&) {
return sizeof(*this);
}
};
#endif
#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/float.hh>
#include <gecode/set.hh>
#include <gecode/minimodel.hh>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <sys/resource.h>
#include <vector>
#include <math.h>
#include <algorithm>
#include "branchWCSD.h"
using namespace Gecode;
using namespace std;
unsigned int BranchWCSD::firstSolFound=0;
/// Return choice
Gecode::Choice* BranchWCSD::choice(Space&) {
int n = x.size();
int pos = 0;
int val = 0;
int k=x[0].max();
for (int i = 0; i < n; i++) {
if (k<x[i].max())
k=x[i].max();
}
k += 1; // cluster indices from 0, # of clusters is max+1
for (int j = start; j < n; j++)
if (!x[j].assigned())
pos = j;
vector< vector<double> > contrib(n-start);
for (int i=start; i<n; i++)
contrib[i-start] = vector<double>(k,0);
// calcul contribution of each unassigned point to a cluster
for (int j = 0 ; j < n; j++)
if (x[j].assigned())
for (int i = start; i < n; i++)
if (!x[i].assigned() && x[i].in(x[j].val()))
contrib[i-start][x[j].val()] += dd[i][j];
// for first solution
if (!BranchWCSD::firstSolFound) {
double minContrib = Float::Limits::max;
for (int j = 0; j < k; j++)
for (int i = start; i < n; i++)
if (!x[i].assigned() && x[i].in(j))
if (contrib[i-start][j] < minContrib) {
minContrib = contrib[i-start][j];
val = j;
pos = i;
}
return new Choice(*this,pos,val);
}
// Strategy for next solutions
// choose point with maximum contribution to a cluster
vector<double> minContrib(n-start,Float::Limits::max);
vector<int> vals(n-start,0);
for (int j = 0; j < k; j++)
for (int i = start; i < n; i++)
if (!x[i].assigned() && x[i].in(j))
if (contrib[i-start][j] < minContrib[i-start]) {
minContrib[i-start] = contrib[i-start][j];
vals[i-start] = j;
}
// choose the unassigned point which has the maximal value
double maxVal = 0;
for (int i = start; i < n; i++)
if (!x[i].assigned() && minContrib[i-start] > maxVal) {
pos = i;
maxVal = minContrib[i-start];
}
return new Choice(*this,pos, vals[pos-start]);
}
#ifndef BRANCH_WCSD
#define BRANCH_WCSD
#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/float.hh>
#include <gecode/set.hh>
#include <gecode/minimodel.hh>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <time.h>
#include <sys/resource.h>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace Gecode;
using namespace std;
/*
Class of branching for the criterion of WCSD
Using the matrix of distance: dd[i][j]
Idea: 2 strategies
- For finding first solution: Greedy search
- after first solution: first-fail strategy