/* * Copyright (C) 2009-2011 by Benedict Paten (benedictpaten@gmail.com) * * Released under the MIT license, see LICENSE.txt */ /* * adjacencyPairsHash.c * * Created on: 24 Aug 2010 * Author: benedictpaten */ #include "sonLib.h" #include "cactus.h" #include "shared.h" const char *MATCHING_EXCEPTION = "MATCHING_EXCEPTION"; /* * Functions to assess matching */ int32_t matchingCardinality(stList *matching) { /* * Returns number of edges with weight > 0. */ int32_t totalCardinality = 0; for (int32_t i = 0; i < stList_length(matching); i++) { stIntTuple *edge = stList_get(matching, i); totalCardinality += stIntTuple_getPosition(edge, 2) > 0 ? 1 : 0; } return totalCardinality; } int32_t matchingWeight(stList *matching) { /* * Returns sum of weights. */ int32_t totalWeight = 0; for(int32_t i=0; i= 0); assert(to >= 0); assert(from != to); #endif int32_t weight = stIntTuple_getPosition(edge, 2); //If is a minimisation algorithms we invert the sign.. fprintf(fileHandle, "%i %i %i\n", from, to, negativeWeights ? -weight : weight); edgesWritten++; addEdgeToSet(seen, from, to); } for(int32_t i=0; i= 0); assert(node1 < nodeNumber); assert(node2 >= 0); assert(node2 < nodeNumber); #endif stIntTuple *edge = constructEdge(node1, node2); stIntTuple *originalEdge = stHash_search(originalEdgesHash, edge); if(originalEdge != NULL) { stList_append(chosenEdges, originalEdge); } stIntTuple_destruct(edge); } stHash_destruct(originalEdgesHash); return chosenEdges; } static stList *chooseAdjacencyPairing_externalProgram(stList *edges, int32_t nodeNumber, const char *programName) { /* * We create temp files to hold stuff. */ if(nodeNumber <= 1) { assert(stList_length(edges) == 0); return stList_construct(); } char *tempInputFile = getTempFile(), *tempOutputFile = getTempFile(); /* * We write the graph to a temp file. */ FILE *fileHandle = fopen(tempInputFile, "w"); if(strcmp(programName, "blossom5") == 0) { //Must be all connected as //generates perfect matchings. writeCliqueGraph(fileHandle, edges, nodeNumber, 1); } else { writeGraph(fileHandle, edges, nodeNumber); } fclose(fileHandle); /* * We run the external program. */ char *command = stString_print("%s -e %s -w %s >& /dev/null", programName, tempInputFile, tempOutputFile); int32_t i = st_system(command); if(i != 0) { stThrowNew(MATCHING_EXCEPTION, "Something went wrong the command %s\n", command); } free(command); /* * We get back the matching. */ fileHandle = fopen(tempOutputFile, "r"); stList *matching = readMatching(fileHandle, edges); fclose(fileHandle); st_logDebug("The adjacency matching for %i nodes with %i initial edges contains %i edges\n", nodeNumber, stList_length(edges), stList_length(matching)); /* * Get rid of the temp files.. */ st_system("rm -rf %s %s", tempInputFile, tempOutputFile); free(tempInputFile); free(tempOutputFile); return matching; } stList *chooseMatching_blossom5(stList *edges, int32_t nodeNumber) { return chooseAdjacencyPairing_externalProgram(edges, nodeNumber, "blossom5"); } stList *chooseMatching_maximumCardinalityMatching(stList *edges, int32_t nodeNumber) { return chooseAdjacencyPairing_externalProgram(edges, nodeNumber, "matchGraph.py -c"); } stList *chooseMatching_maximumWeightMatching(stList *edges, int32_t nodeNumber) { return chooseAdjacencyPairing_externalProgram(edges, nodeNumber, "matchGraph.py"); } /* * Greedy matching algorithm. */ int chooseMatching_greedyP(const void *a, const void *b) { return stIntTuple_getPosition((stIntTuple *)a, 2) - stIntTuple_getPosition((stIntTuple *)b, 2); } stList *chooseMatching_greedy(stList *edges, int32_t nodeNumber) { /* * Greedily picks the edge from the list such that each node has at most one edge. */ //First clone the list.. edges = stList_copy(edges, NULL); stSortedSet *seen = getEmptyNodeOrEdgeSetWithCleanup(); stList *matching = stList_construct(); //Sort the adjacency pairs.. stList_sort(edges, chooseMatching_greedyP); #ifdef BEN_DEBUG double strength = INT32_MAX; #endif while (stList_length(edges) > 0) { stIntTuple *edge = stList_pop(edges); #ifdef BEN_DEBUG double d = stIntTuple_getPosition(edge, 2); assert(d <= strength); strength = d; #endif if(!nodeInSet(seen, stIntTuple_getPosition(edge, 0)) && !nodeInSet(seen, stIntTuple_getPosition(edge, 1))) { addNodeToSet(seen, stIntTuple_getPosition(edge, 0)); addNodeToSet(seen, stIntTuple_getPosition(edge, 1)); stList_append(matching,edge); } } assert(stList_length(edges) == 0); stList_destruct(edges); stSortedSet_destruct(seen); return matching; }