#ifndef GCG_HYPERROWGRAPH_DEF_H_
#define GCG_HYPERROWGRAPH_DEF_H_
#include "hyperrowgraph.h"
#include "scip_misc.h"
#include "class_partialdecomp.h"
#include "class_detprobdata.h"
#include <set>
#include <algorithm>
#include <iostream>
namespace gcg
{
template <class T>
HyperrowGraph<T>::HyperrowGraph(
SCIP* scip,
Weights w
): MatrixGraph<T>(scip, w), graph(scip)
{
this->graphiface = &graph;
this->name = std::string("hyperrow");
}
template <class T>
HyperrowGraph<T>::~HyperrowGraph()
{
}
template <class T>
SCIP_RETCODE HyperrowGraph<T>::writeToFile(
int fd,
SCIP_Bool edgeweights
)
{
FILE* file;
file = fdopen(fd, "w");
if( file == NULL )
return SCIP_FILECREATEERROR;
SCIPinfoMessage(this->scip_, file, "%d %d %d\n", getNEdges(), getNNodes()+this->dummynodes, edgeweights ? 1 :0);
for( int i = 0; i < getNEdges(); ++i )
{
std::vector<int> neighbors = getHyperedgeNodes(i);
if( edgeweights )
{
SCIPinfoMessage(this->scip_, file, "%d ", graph.getWeight(i+this->nvars));
}
for( size_t j = 0; j < neighbors.size(); ++j )
{
SCIPinfoMessage(this->scip_, file, "%d ",neighbors[j]+1);
}
SCIPinfoMessage(this->scip_, file, "\n");
}
if( !fclose(file) )
return SCIP_OKAY;
else
return SCIP_WRITEERROR;
}
template <class T>
int HyperrowGraph<T>::getNEdges()
{
return this->nconss;
}
template <class T>
int HyperrowGraph<T>::getNNodes()
{
return this->nvars;
}
template <class T>
int HyperrowGraph<T>::getNNeighbors(
int i
)
{
assert(i >= 0);
assert(i < getNNodes());
return graph.getNNeighbors(i);
}
template <class T>
std::vector<int> HyperrowGraph<T>::getHyperedgeNodes(
int i
)
{
assert(i >= 0);
assert(i < getNEdges());
std::vector<int> neighbors = graph.getHyperedgeNodes(i);
return neighbors;
}
template <class T>
SCIP_RETCODE HyperrowGraph<T>::createDecompFromPartition(
DEC_DECOMP** decomp
)
{
int nblocks;
SCIP_HASHMAP* constoblock = NULL;
int* nsubscipconss = NULL;
int i;
SCIP_CONS** conss = NULL;
SCIP_Bool emptyblocks = FALSE;
std::vector<int> partition = graph.getPartition();
conss = SCIPgetConss(this->scip_);
nblocks = *(std::max_element(partition.begin(), partition.end()))+1;
SCIP_CALL( SCIPallocBufferArray(this->scip_, &nsubscipconss, nblocks) );
BMSclearMemoryArray(nsubscipconss, nblocks);
SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(this->scip_), this->nconss) );
for( i = 0; i < this->nconss; i++ )
{
std::set<int> blocks;
std::vector<int> neighbors = getHyperedgeNodes(i);
for( size_t k = 0; k < neighbors.size(); ++k )
{
if( partition[neighbors[k]] >= 0 )
blocks.insert(partition[neighbors[k]]);
}
if( blocks.size() > 1 )
{
SCIP_CALL( SCIPhashmapInsert(constoblock, conss[i], (void*) (size_t) (nblocks+1)) );
}
else
{
int block = *(blocks.begin());
SCIP_CALL( SCIPhashmapInsert(constoblock, conss[i], (void*) (size_t) (block +1)) );
++(nsubscipconss[block]);
}
}
for( i = 0; i < nblocks; ++i )
{
if( nsubscipconss[i] == 0 )
{
SCIPdebugMessage("Block %d does not have any constraints!\n", i);
emptyblocks = TRUE;
}
}
if( !emptyblocks )
{
SCIP_CALL( DECdecompCreate(this->scip_, decomp) );
SCIP_CALL( DECfilloutDecompFromConstoblock(this->scip_, *decomp, constoblock, nblocks, FALSE) );
}
else {
SCIPhashmapFree(&constoblock);
*decomp = NULL;
}
SCIPfreeBufferArray(this->scip_, &nsubscipconss);
return SCIP_OKAY;
}
template <class T>
SCIP_RETCODE HyperrowGraph<T>::createPartialdecFromPartition(
PARTIALDECOMP** firstpartialdec,
PARTIALDECOMP** secondpartialdec,
DETPROBDATA* detprobdata
)
{
int nblocks;
SCIP_HASHMAP* constoblock = NULL;
int* nsubscipconss = NULL;
int i;
SCIP_CONS** conss = NULL;
SCIP_Bool emptyblocks = FALSE;
std::vector<int> partition = graph.getPartition();
conss = SCIPgetConss(this->scip_);
nblocks = *(std::max_element(partition.begin(), partition.end()))+1;
SCIP_CALL( SCIPallocBufferArray(this->scip_, &nsubscipconss, nblocks) );
BMSclearMemoryArray(nsubscipconss, nblocks);
SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(this->scip_), this->nconss) );
for( i = 0; i < this->nconss; i++ )
{
std::set<int> blocks;
std::vector<int> neighbors = getHyperedgeNodes(i);
for( size_t k = 0; k < neighbors.size(); ++k )
{
if( partition[neighbors[k]] >= 0 )
blocks.insert(partition[neighbors[k]]);
}
if( blocks.size() > 1 )
{
SCIP_CALL( SCIPhashmapInsert(constoblock, (void*) (size_t)detprobdata->getIndexForCons(conss[i]), (void*) (size_t) (nblocks+1)) );
}
else
{
int block = *(blocks.begin());
SCIP_CALL( SCIPhashmapInsert(constoblock, (void*) (size_t)detprobdata->getIndexForCons(conss[i]), (void*) (size_t) (block +1)) );
++(nsubscipconss[block]);
}
}
for( i = 0; i < nblocks; ++i )
{
if( nsubscipconss[i] == 0 )
{
SCIPdebugMessage("Block %d does not have any constraints!\n", i);
emptyblocks = TRUE;
}
}
if( !emptyblocks )
{
bool original = detprobdata->isAssignedToOrigProb();
if( firstpartialdec != NULL )
{
(*firstpartialdec) = new PARTIALDECOMP(this->scip_, original);
SCIP_CALL((*firstpartialdec)->filloutPartialdecFromConstoblock(constoblock, nblocks));
}
if( secondpartialdec != NULL )
{
(*secondpartialdec) = new PARTIALDECOMP(this->scip_, original);
SCIP_CALL((*secondpartialdec)->filloutBorderFromConstoblock(constoblock, nblocks));
}
SCIPhashmapFree(&constoblock);
}
else {
SCIPhashmapFree(&constoblock);
if( firstpartialdec != NULL )
{
*firstpartialdec = NULL;
}
if( secondpartialdec != NULL )
{
*secondpartialdec = NULL;
}
}
SCIPfreeBufferArray(this->scip_, &nsubscipconss);
return SCIP_OKAY;
}
template <class T>
SCIP_RETCODE HyperrowGraph<T>::createPartialdecFromPartition(
PARTIALDECOMP* oldpartialdec,
PARTIALDECOMP** firstpartialdec,
PARTIALDECOMP** secondpartialdec,
DETPROBDATA* detprobdata
)
{
int nblocks;
SCIP_HASHMAP* constoblock = NULL;
int *nsubscipconss = NULL;
int i;
SCIP_Bool emptyblocks = FALSE;
if(this->nconss == 0)
{
(*firstpartialdec) = NULL;
(*secondpartialdec) = NULL;
return SCIP_OKAY;
}
std::vector<int> partition = graph.getPartition();
nblocks = *(std::max_element(partition.begin(), partition.end()))+1;
SCIP_CALL( SCIPallocBufferArray(this->scip_, &nsubscipconss, nblocks) );
BMSclearMemoryArray(nsubscipconss, nblocks);
for(int b = 0; b < nblocks; ++b)
{
nsubscipconss[b] = 0;
}
SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(this->scip_), this->nconss) );
vector<int> conssForGraph;
vector<bool> conssBool(oldpartialdec->getNConss(), false);
bool found;
for(int c = 0; c < oldpartialdec->getNOpenconss(); ++c)
{
int cons = oldpartialdec->getOpenconss()[c];
found = false;
for(int v = 0; v < oldpartialdec->getNOpenvars() && !found; ++v)
{
int var = oldpartialdec->getOpenvars()[v];
for(i = 0; i < detprobdata->getNVarsForCons(cons) && !found; ++i)
{
if(var == detprobdata->getVarsForCons(cons)[i])
{
conssBool[cons] = true;
found = true;
}
}
}
}
for(int c = 0; c < oldpartialdec->getNOpenconss(); ++c)
{
int cons = oldpartialdec->getOpenconss()[c];
if(conssBool[cons])
conssForGraph.push_back(cons);
}
for( i = 0; i < this->nconss; i++ )
{
std::set<int> blocks;
std::vector<int> neighbors = getHyperedgeNodes(i);
for( size_t k = 0; k < neighbors.size(); ++k )
{
if( partition[neighbors[k]] >= 0 )
blocks.insert(partition[neighbors[k]]);
}
if( blocks.size() > 1 )
{
SCIP_CALL( SCIPhashmapInsert(constoblock, (void*) (size_t) conssForGraph[i], (void*) (size_t) (nblocks+1)) );
}
else
{
int block = *(blocks.begin());
SCIP_CALL( SCIPhashmapInsert(constoblock, (void*) (size_t) conssForGraph[i], (void*) (size_t) (block +1)) );
++(nsubscipconss[block]);
}
}
for( i = 0; i < nblocks; ++i )
{
if( nsubscipconss[i] == 0 )
{
SCIPdebugMessage("Block %d does not have any constraints!\n", i);
emptyblocks = TRUE;
}
}
if( !emptyblocks )
{
(*firstpartialdec) = new PARTIALDECOMP(oldpartialdec);
SCIP_CALL( (*firstpartialdec)->assignPartialdecFromConstoblock(constoblock, nblocks) );
(*secondpartialdec) = new PARTIALDECOMP(oldpartialdec);
SCIP_CALL( (*secondpartialdec)->assignBorderFromConstoblock(constoblock, nblocks) );
SCIPhashmapFree(&constoblock);
}
else {
SCIPhashmapFree(&constoblock);
*firstpartialdec = NULL;
*secondpartialdec = NULL;
}
SCIPfreeBufferArray(this->scip_, &nsubscipconss);
return SCIP_OKAY;
}
template <class T>
SCIP_RETCODE HyperrowGraph<T>::createFromMatrix(
SCIP_CONS** conss,
SCIP_VAR** vars,
int nconss_,
int nvars_
)
{
int i;
int j;
SCIP_Bool success;
assert(conss != NULL);
assert(vars != NULL);
assert(nvars_ > 0);
assert(nconss_ > 0);
this->nvars = nvars_;
this->nconss = nconss_;
for( i = 0; i < this->nvars; ++i )
{
TCLIQUE_WEIGHT weight;
weight = this->weights.calculate(vars[i]);
this->graph.addNode(i, weight);
}
for( i = 0; i < this->nconss; ++i )
{
SCIP_VAR** curvars = NULL;
std::vector<int> hyperedge;
TCLIQUE_WEIGHT weight;
int ncurvars;
SCIP_CALL( SCIPgetConsNVars(this->scip_, conss[i], &ncurvars, &success) );
assert(success);
if( ncurvars == 0 )
continue;
SCIP_CALL( SCIPallocBufferArray(this->scip_, &curvars, ncurvars) );
SCIP_CALL( SCIPgetConsVars(this->scip_, conss[i], curvars, ncurvars, &success) );
assert(success);
for( j = 0; j < ncurvars; ++j )
{
SCIP_VAR* var1 = NULL;
int varIndex1;
if( SCIPgetStage(this->scip_) >= SCIP_STAGE_TRANSFORMED)
var1 = SCIPvarGetProbvar(curvars[j]);
else
var1 = curvars[j];
if( !GCGisVarRelevant(var1) )
continue;
assert(var1 != NULL);
varIndex1 = SCIPvarGetProbindex(var1);
assert(varIndex1 >= 0);
assert(varIndex1 < this->nvars);
hyperedge.insert(hyperedge.end(), varIndex1);
}
weight = this->weights.calculate(conss[i]);
this->graph.addHyperedge(hyperedge, weight);
SCIPfreeBufferArray(this->scip_, &curvars);
}
this->graph.flush();
return SCIP_OKAY;
}
template <class T>
SCIP_RETCODE HyperrowGraph<T>::createFromPartialMatrix(
DETPROBDATA* detprobdata,
PARTIALDECOMP* partialdec
){
int i;
int j;
unordered_map<int, int> oldToNewVarIndex;
TCLIQUE_WEIGHT weight;
vector<bool> varsBool(partialdec->getNVars(), false);
vector<bool> conssBool(partialdec->getNConss(), false);
vector<int> conssForGraph;
vector<int> varsForGraph;
for(int c = 0; c < partialdec->getNOpenconss(); ++c)
{
int cons = partialdec->getOpenconss()[c];
for(int v = 0; v < partialdec->getNOpenvars(); ++v)
{
int var = partialdec->getOpenvars()[v];
for(i = 0; i < detprobdata->getNVarsForCons(cons); ++i)
{
if(var == detprobdata->getVarsForCons(cons)[i])
{
varsBool[var] = true;
conssBool[cons] = true;
}
}
}
}
for(int v = 0; v < partialdec->getNOpenvars(); ++v)
{
int var = partialdec->getOpenvars()[v];
if(varsBool[var])
varsForGraph.push_back(var);
}
for(int c = 0; c < partialdec->getNOpenconss(); ++c)
{
int cons = partialdec->getOpenconss()[c];
if(conssBool[cons])
conssForGraph.push_back(cons);
}
this->nconss = (int)conssForGraph.size();
this->nvars = (int)varsForGraph.size();
for( i = 0; i < this->nvars; ++i )
{
int oldVarId = varsForGraph[i];
assert(varsBool[oldVarId]);
weight = this->weights.calculate(detprobdata->getVar(oldVarId));
oldToNewVarIndex.insert({oldVarId,i});
this->graph.addNode(i, weight);
}
for( i = 0; i < this->nconss; ++i )
{
std::vector<int> hyperedge;
int oldConsId = conssForGraph[i];
assert(conssBool[oldConsId]);
for( j = 0; j < detprobdata->getNVarsForCons(oldConsId); ++j )
{
int oldVarId = detprobdata->getVarsForCons(oldConsId)[j];
if(!varsBool[oldVarId])
continue;
hyperedge.insert(hyperedge.end(), oldToNewVarIndex[oldVarId]);
}
weight = this->weights.calculate(detprobdata->getCons(oldConsId));
this->graph.addHyperedge(hyperedge, weight);
}
this->graph.flush();
return SCIP_OKAY;
}
}
#endif