/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* This file is part of the program */ /* GCG --- Generic Column Generation */ /* a Dantzig-Wolfe decomposition based extension */ /* of the branch-cut-and-price framework */ /* SCIP --- Solving Constraint Integer Programs */ /* */ /* Copyright (C) 2010-2022 Operations Research, RWTH Aachen University */ /* Zuse Institute Berlin (ZIB) */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Lesser General Public License */ /* as published by the Free Software Foundation; either version 3 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU Lesser General Public License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /**@file hypergraph_def.h * @brief miscellaneous hypergraph methods for structure detection * @author Martin Bergner */ /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ #ifndef GCG_HYPERGRAPH_DEF_H_ #define GCG_HYPERGRAPH_DEF_H_ #include "scip/scip.h" #include "hypergraph.h" namespace gcg { template Hypergraph::Hypergraph( SCIP* scip /**< SCIP data structure */ ) : name("hypergraph"),scip_(scip),graph(NULL),lastnode(0),dummynodes(0) { SCIPdebugMessage("Creating graph\n"); graph = new Graph(scip); } template Hypergraph::~Hypergraph() { if(graph != NULL) delete graph; } template int Hypergraph::computeNodeId(int i) { int nodeid; if( i < (int) nodes.size()) nodeid = nodes[i]; else nodeid = lastnode; SCIPdebugMessage("Nodeid %d is %d\n", i, nodeid); return nodeid; } template SCIP_RETCODE Hypergraph::addNode(int i,int weight) { int nodeid = lastnode; SCIPdebugMessage("Adding node %d (id=%d)\n", i, nodeid); SCIP_CALL( graph->addNode(nodeid, weight) ); nodes.push_back(nodeid); mapping.resize(nodeid+1); mapping[nodeid] = i; ++lastnode; return SCIP_OKAY; } /** adds the edge to the graph */ template SCIP_RETCODE Hypergraph::addHyperedge(std::vector &edge, int weight) { int edgenodeid = lastnode; ++lastnode; SCIPdebugMessage("Adding hyperedge %lu (id=%d)\n", hedges.size(), edgenodeid); SCIP_CALL( graph->addNode(edgenodeid, weight) ); for( size_t i = 0; i < edge.size(); ++i ) { SCIP_CALL( graph->addEdge(edgenodeid, computeNodeId(edge[i])) ); } hedges.push_back(edgenodeid); mapping.resize(edgenodeid+1); mapping[edgenodeid] = hedges.size()-1; return SCIP_OKAY; } /** adds the edge to the graph */ template SCIP_RETCODE Hypergraph::addNodeToHyperedge(int node, int hedge) { int edgenodeid = hedges[hedge]; int nodeid = nodes[node]; SCIP_CALL( graph->addEdge(edgenodeid, nodeid) ); return SCIP_OKAY; } template int Hypergraph::getNNodes() { return nodes.size(); } template int Hypergraph::getNHyperedges() { return hedges.size(); } template int Hypergraph::getNNeighbors(int i) { assert( i >= 0); return graph->getNNeighbors(i); } template std::vector Hypergraph::getNeighbors(int i) { assert(i >= 0); int nodeid = computeNodeId(i); std::vector edges = graph->getNeighbors(nodeid); std::set neighbors; for( size_t j = 0; j < edges.size(); ++j ) { std::vector tempneighbors = graph->getNeighbors(edges[j]); neighbors.insert(tempneighbors.begin(), tempneighbors.end()); } std::vector r(neighbors.begin(), neighbors.end()); for( size_t j = 0; j < r.size(); ++j) { r[j] = mapping[r[j]]; } std::vector::iterator it = std::remove(r.begin(), r.end(), nodeid); return std::vector(r.begin(), it); } template std::vector Hypergraph::getHyperedgeNodes( int i ) { std::vector hnodes = graph->getNeighbors(hedges[i]); for( size_t j = 0; j < hnodes.size(); ++j) { hnodes[j] = computeNodeId(hnodes[j]); } return hnodes; } template int Hypergraph::getNHyperedgeNodes( int i ) { return graph->getNNeighbors(hedges[i]); } template void Hypergraph::setPartition(int i, int ID) { partition.resize(getNNodes(), -1); partition[i] = ID; } /** write the hypergraph to a file */ template SCIP_RETCODE Hypergraph::writeToFile( int fd, /**< filename where the graph should be written to */ SCIP_Bool writeweights ) { FILE* file; file = fdopen(fd, "w"); if( file == NULL ) return SCIP_FILECREATEERROR; SCIPinfoMessage(scip_, file, "%ld %ld\n", nodes.size()+dummynodes, hedges.size()); for( size_t i = 0; i < hedges.size(); ++i ) { int nneighbors = graph->getNNeighbors(hedges[i]); std::vector neighbors = graph->getNeighbors(hedges[i]); if( writeweights ) { SCIPinfoMessage(scip_, file, "%d ", graph->getWeight(i)); } for( int j = 0; j < nneighbors; ++j ) { SCIPinfoMessage(scip_, file, "%d ", computeNodeId(neighbors[j])+1); } SCIPinfoMessage(scip_, file, "\n"); } return SCIP_OKAY; } /** read in the partition from a file */ template SCIP_RETCODE Hypergraph::readPartition( const char* filename ) { ifstream input(filename); if( !input.good() ) { SCIPerrorMessage("Could not open file <%s> for reading\n", filename); return SCIP_READERROR; } partition.resize(getNNodes(), -1); for( int i = 0; i < getNNodes(); ++i ) { int part = 0; if( !(input >> part) ) { SCIPerrorMessage("Could not read from file <%s>. It may be in the wrong format\n", filename); return SCIP_READERROR; } partition[i] = part; } input.close(); return SCIP_OKAY; } /** return the weight of given node */ template int Hypergraph::getWeight( int i /**< the given node */ ) { return graph->getWeight(i); } /** return the weight of given hyperedge */ template int Hypergraph::getHyperedgeWeight( int i /**< the given hyperedge */ ) { int edgenodeid = hedges[i]; return graph->getWeight(edgenodeid); } template SCIP_RETCODE Hypergraph::flush() { SCIP_CALL( graph->flush() ); return SCIP_OKAY; } } /* namespace gcg */ #endif