Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

892 lines
23 KiB

  1. /******************************************************************************
  2. *
  3. * LHMain.c
  4. *
  5. * Author: Nicholas Harvey
  6. *
  7. * Implements all LHMatch API functions and other functions that are common to
  8. * all LHMatch algorithms.
  9. *
  10. ******************************************************************************/
  11. /***** Header Files *****/
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <memory.h>
  15. #include <assert.h>
  16. #include "LHMatchInt.h"
  17. /***** Constants *****/
  18. /* MIN_ADJ_LIST: The minimum size of a Vertex's adjacency list */
  19. #define MIN_ADJ_LIST 4
  20. /***** Globals *****/
  21. #ifdef DBG
  22. int gDebugPrint=0;
  23. #endif
  24. /***** CheckGraph *****/
  25. /* Verify that a graph structure we were passed is okay */
  26. Graph* CheckGraph( LHGRAPH graph ) {
  27. Graph* g = (Graph*) graph;
  28. if( g==NULL || g->magic1!=MAGIC1 || g->magic2!=MAGIC2 ) {
  29. return NULL;
  30. }
  31. return g;
  32. }
  33. /***** AddVtxToBucket *****/
  34. void AddVtxToBucket(Graph *g, Vertex *v, int b) {
  35. v->fLink = g->Buckets[b];
  36. v->bLink = NULL;
  37. if(g->Buckets[b]) g->Buckets[b]->bLink=v;
  38. g->Buckets[b] = v;
  39. }
  40. /***** RemoveVtxFromBucket *****/
  41. void RemoveVtxFromBucket(Graph *g, Vertex *v, int b) {
  42. if(v->fLink) {
  43. v->fLink->bLink = v->bLink;
  44. }
  45. if(v->bLink) {
  46. v->bLink->fLink = v->fLink;
  47. } else {
  48. g->Buckets[b] = v->fLink;
  49. }
  50. }
  51. /***** DestroyBuckets *****/
  52. void DestroyBuckets(Graph *g) {
  53. free(g->Buckets);
  54. g->Buckets = NULL;
  55. }
  56. /***** InitializeLHSBuckets *****/
  57. static int InitializeLHSBuckets(Graph *g) {
  58. Vertex *vtx=g->lVtx;
  59. int i, maxLHSDegree, numLHSVtx=g->numLHSVtx;
  60. /* Find degree of LHS vertices */
  61. maxLHSDegree=0;
  62. for(i=0;i<numLHSVtx;i++) {
  63. maxLHSDegree = INTMAX(maxLHSDegree, vtx[i].degree);
  64. }
  65. /* Inititalize array of buckets */
  66. g->Buckets = (Vertex**) calloc(maxLHSDegree+1, sizeof(Vertex*));
  67. if( NULL==g->Buckets ) {
  68. return LH_MEM_ERR;
  69. }
  70. /* Add LHS vertices to their buckets */
  71. for(i=0;i<numLHSVtx;i++) {
  72. if( vtx[i].degree>0 ) {
  73. AddVtxToBucket(g, &vtx[i], vtx[i].degree);
  74. }
  75. }
  76. return maxLHSDegree;
  77. }
  78. /***** OrderedGreedyAssignment *****/
  79. /* Use a greedy approach to find an initial assignment. Examine LHS
  80. * vertices in order of their degree. */
  81. int OrderedGreedyAssignment(Graph *g) {
  82. int b,j, maxLHSDegree;
  83. Vertex *u, *r,*bestR;
  84. maxLHSDegree = InitializeLHSBuckets(g);
  85. if( maxLHSDegree<0 ) {
  86. /* Error occurred */
  87. return maxLHSDegree;
  88. }
  89. /* Examine each bucket */
  90. for(b=1;b<=maxLHSDegree;b++) {
  91. /* And each LHS vertex in the bucket */
  92. for( u=g->Buckets[b]; u; u=u->fLink ) {
  93. /* If u has already been matched, skip it */
  94. if( NULL!=u->matchedWith ) continue;
  95. /* Find right-hand neighbour with lowest matching-degree */
  96. bestR = u->adjList[0];
  97. for(j=1;j<u->degree;j++) {
  98. r=u->adjList[j];
  99. #ifdef WORST_GREEDY
  100. if(r->numMatched>bestR->numMatched)
  101. bestR=r;
  102. #else
  103. if(r->numMatched<bestR->numMatched)
  104. bestR=r;
  105. #endif
  106. }
  107. /* Assign LHS vertex to lowest matching-degree RHS vertex */
  108. u->matchedWith = bestR;
  109. u->numMatched = 1;
  110. bestR->numMatched++;
  111. }
  112. }
  113. DestroyBuckets(g);
  114. return LH_SUCCESS;
  115. }
  116. /***** GreedyAssignment *****/
  117. /* Simple Greedy Assignment */
  118. void GreedyAssignment(Graph *g) {
  119. int i,j;
  120. Vertex *r,*bestR,*vtx=g->lVtx;
  121. /* For each LHS vertex */
  122. for(i=0;i<g->numLHSVtx;i++) {
  123. /* Find right-hand neighbour with lowest matching-degree */
  124. bestR = vtx[i].adjList[0];
  125. for(j=1;j<vtx[i].degree;j++) {
  126. r=vtx[i].adjList[j];
  127. if(r->numMatched<bestR->numMatched)
  128. bestR=r;
  129. }
  130. /* Assign LHS vertex to lowest matching-degree RHS vertex */
  131. vtx[i].matchedWith = bestR;
  132. vtx[i].numMatched = 1;
  133. bestR->numMatched++;
  134. }
  135. }
  136. /***** InitializeRHSBuckets *****/
  137. /* Insert all RHS vertices into buckets. Their matched-degree
  138. * (i.e. numMatched) determines what bucket they live in. */
  139. int InitializeRHSBuckets(Graph *g) {
  140. Vertex *vtx=g->rVtx;
  141. int i, maxRHSLoad, numRHSVtx=g->numRHSVtx;
  142. /* Find maximum M-degree of RHS vertices */
  143. maxRHSLoad=0;
  144. for(i=0;i<numRHSVtx;i++) {
  145. maxRHSLoad = INTMAX(maxRHSLoad, vtx[i].numMatched);
  146. }
  147. g->maxRHSLoad = maxRHSLoad;
  148. /* Allocate array of buckets */
  149. g->Buckets = (Vertex**) calloc(maxRHSLoad+1, sizeof(Vertex*));
  150. if( NULL==g->Buckets ) {
  151. return LH_MEM_ERR;
  152. }
  153. /* Add RHS vertices to their buckets */
  154. for(i=0;i<numRHSVtx;i++) {
  155. if( vtx[i].degree>0 ) {
  156. AddVtxToBucket( g, &vtx[i], vtx[i].numMatched );
  157. }
  158. }
  159. return LH_SUCCESS;
  160. }
  161. /***** InitializeQueue *****/
  162. int InitializeQueue(Graph *g) {
  163. g->Qsize=0;
  164. g->Queue=(Vertex**) malloc((g->numLHSVtx+g->numRHSVtx)*sizeof(Vertex*));
  165. if(NULL==g->Queue) {
  166. return LH_MEM_ERR;
  167. }
  168. return LH_SUCCESS;
  169. }
  170. /***** DestroyQueue *****/
  171. void DestroyQueue(Graph *g) {
  172. free(g->Queue);
  173. g->Queue=NULL;
  174. g->Qsize=0;
  175. }
  176. /***** ClearVertex *****/
  177. /* Clear one vertex */
  178. static void ClearVertex(Vertex *v) {
  179. v->parent = NULL;
  180. v->fLink = NULL;
  181. v->bLink = NULL;
  182. }
  183. /***** ClearAlgState *****/
  184. /* Clears all the internal algorithm state from the graph.
  185. * Note: Does not affect the edges or the matching */
  186. void ClearAlgState(Graph *g) {
  187. int i;
  188. /* Clear state that is stored in the graph structure */
  189. g->maxRHSLoad = 0;
  190. g->minRHSLoad = 0;
  191. g->Qsize = 0;
  192. /* Clear state that is stored in the vertices */
  193. for(i=0;i<g->numLHSVtx;i++) {
  194. ClearVertex(&(g->lVtx[i]));
  195. }
  196. for(i=0;i<g->numRHSVtx;i++) {
  197. ClearVertex(&(g->rVtx[i]));
  198. }
  199. }
  200. /***** DumpGraph *****/
  201. void DumpGraph(Graph *g) {
  202. int i,j,m=0;
  203. /* Count # edges */
  204. for(i=0;i<g->numLHSVtx;i++) {
  205. m+=g->lVtx[i].degree;
  206. }
  207. printf("--- Dumping graph---\n");
  208. printf("|lhs|=%d, |rhs|=%d |edge|=%d\n", g->numLHSVtx, g->numRHSVtx, m);
  209. /* Dump each LHS vertex and its list of neighbours */
  210. for(i=0;i<g->numLHSVtx;i++) {
  211. printf("LHS Vtx %02d: Match=%d, Deg=%d, Nbr=[ ",
  212. i,
  213. g->lVtx[i].matchedWith ? g->lVtx[i].matchedWith->id : -1,
  214. g->lVtx[i].degree );
  215. for(j=0;j<g->lVtx[i].degree;j++) {
  216. printf("%d ", g->lVtx[i].adjList[j]->id);
  217. }
  218. printf("]\n");
  219. }
  220. /* Dump each RHS vertex and its list of neighbours */
  221. for(i=0;i<g->numRHSVtx;i++) {
  222. printf("RHS Vtx %02d: NumMatch=%d, Deg=%d, Nbr=[ ",
  223. i+g->numLHSVtx, g->rVtx[i].numMatched, g->rVtx[i].degree );
  224. for(j=0;j<g->rVtx[i].degree;j++) {
  225. printf("%d ", g->rVtx[i].adjList[j]->id);
  226. }
  227. printf("]\n");
  228. }
  229. printf("--- Finished dumping graph---\n");
  230. }
  231. /***** DumpLoad *****/
  232. void DumpLoad(Graph *g) {
  233. int i;
  234. printf("--- Dumping load ---\n");
  235. for(i=0;i<g->numRHSVtx;i++) {
  236. printf("RHS Vtx %02d: |M-nbrs|=%d\n",g->rVtx[i].id,g->rVtx[i].numMatched);
  237. }
  238. printf("--- Finished dumping load ---\n");
  239. }
  240. /***** LHCreateGraph *****/
  241. /*
  242. * Description:
  243. *
  244. * Create a graph structure on which which to compute the matching.
  245. *
  246. * Parameters:
  247. *
  248. * IN numLHSVtx The number of vertices on the left-hand side of
  249. * the bipartite graph. Must be > 0.
  250. *
  251. * IN numRHSVtx The number of vertices on the right-hand side of
  252. * the bipartite graph. Must be > 0.
  253. *
  254. * OUT pGraph On successful completion, pGraph will contain a
  255. * valid graph structure.
  256. *
  257. * Return Value:
  258. *
  259. * Error Code
  260. */
  261. int LHCreateGraph( int numLHSVtx, int numRHSVtx, LHGRAPH* pGraph ) {
  262. Graph *g;
  263. int i;
  264. /* Check parameters */
  265. if( numLHSVtx<=0 || numRHSVtx<=0 || NULL==pGraph) {
  266. return LH_PARAM_ERR;
  267. }
  268. /* Allocate the graph structure */
  269. g = (Graph*) calloc( 1, sizeof(Graph) );
  270. if( NULL==g ) {
  271. return LH_MEM_ERR;
  272. }
  273. /* Allocate the LHS vertices */
  274. g->lVtx = (Vertex*) calloc( numLHSVtx, sizeof(Vertex) );
  275. if( NULL==g->lVtx ) {
  276. free(g);
  277. return LH_MEM_ERR;
  278. }
  279. /* Allocate the RHS vertices */
  280. g->rVtx = (Vertex*) calloc( numRHSVtx, sizeof(Vertex) );
  281. if( NULL==g->rVtx ) {
  282. free(g->lVtx);
  283. free(g);
  284. return LH_MEM_ERR;
  285. }
  286. /* Initialize the vertices */
  287. for(i=0;i<numLHSVtx;i++) {
  288. g->lVtx[i].id = i;
  289. }
  290. for(i=0;i<numRHSVtx;i++) {
  291. g->rVtx[i].id = i+numLHSVtx;
  292. }
  293. /* Initialize the graph structure */
  294. g->numLHSVtx = numLHSVtx;
  295. g->numRHSVtx = numRHSVtx;
  296. g->magic1 = MAGIC1;
  297. g->magic2 = MAGIC2;
  298. /* Return the graph */
  299. *pGraph = g;
  300. return LH_SUCCESS;
  301. }
  302. /***** GrowAdjList *****/
  303. int GrowAdjList( Vertex *v, int newSize ) {
  304. Vertex **newAdjList;
  305. /* If we have no list, make the initial allocation */
  306. if( 0==v->adjListSize ) {
  307. v->adjList = (Vertex**) malloc( sizeof(Vertex*)*MIN_ADJ_LIST );
  308. if( NULL==v->adjList ) {
  309. return LH_MEM_ERR;
  310. }
  311. v->adjListSize = MIN_ADJ_LIST;
  312. }
  313. /* Check to see if we already have enough space in the list */
  314. while( newSize>v->adjListSize ) {
  315. /* Not enough: double the size of the list */
  316. newAdjList = (Vertex**) realloc( v->adjList, sizeof(Vertex*)*(v->adjListSize*2) );
  317. if( NULL==newAdjList ) {
  318. return LH_MEM_ERR;
  319. }
  320. v->adjList = newAdjList;
  321. v->adjListSize *= 2;
  322. }
  323. return LH_SUCCESS;
  324. }
  325. /***** LHAddEdge *****/
  326. /*
  327. * Description:
  328. *
  329. * Add an edge to the graph connecting lhsVtx and rhsVtx
  330. *
  331. * Parameters:
  332. *
  333. * IN graph A graph successfully created by LHGraphCreate.
  334. *
  335. * IN lhsVtx The ID of the left-hand vertex. Legal values are
  336. * 0 <= lhsVtx < numLHSVtx
  337. *
  338. * IN rhsVtx The ID of the right-hand vertex. Legal values are
  339. * 0 <= rhsVtx < numRHSVtx
  340. *
  341. * Return Value:
  342. *
  343. * Error Code
  344. */
  345. int LHAddEdge( LHGRAPH graph, int lhsVtx, int rhsVtx ) {
  346. Graph *g;
  347. Vertex *lv, *rv;
  348. int i;
  349. /* Check parameters */
  350. g = CheckGraph(graph);
  351. if( NULL==g ) {
  352. return LH_PARAM_ERR;
  353. }
  354. if( lhsVtx<0 || lhsVtx>=g->numLHSVtx ) {
  355. return LH_PARAM_ERR;
  356. }
  357. if( rhsVtx<0 || rhsVtx>=g->numRHSVtx ) {
  358. return LH_PARAM_ERR;
  359. }
  360. /* Get pointers to the two vertices */
  361. lv = &g->lVtx[lhsVtx];
  362. rv = &g->rVtx[rhsVtx];
  363. /* Check if edge already exists */
  364. for( i=0; i<lv->degree; i++ ) {
  365. if( lv->adjList[i]==rv ) {
  366. return LH_EDGE_EXISTS;
  367. }
  368. }
  369. /* Increase the size of the adjacency lists */
  370. if( LH_SUCCESS!=GrowAdjList(lv,lv->degree+1) ) {
  371. return LH_MEM_ERR;
  372. }
  373. if( LH_SUCCESS!=GrowAdjList(rv,rv->degree+1) ) {
  374. return LH_MEM_ERR;
  375. }
  376. /* Update the adjacency lists */
  377. lv->adjList[ lv->degree++ ] = rv;
  378. rv->adjList[ rv->degree++ ] = lv;
  379. return LH_SUCCESS;
  380. }
  381. /***** LHSetMatchingEdge *****/
  382. /*
  383. * Description:
  384. *
  385. * Set the edge connecting lhsVtx and rhsVtx in the graph to be
  386. * a matching edge. The edge (lhsVtx,rhsVtx) must have already been
  387. * created with a call to LHVtxAddEdge.
  388. *
  389. * Left-hand vertices may only have one matching edge. If lhsVtx
  390. * already has a matching edge, that edge will be demoted from a
  391. * matching edge to a normal edge. Right-hand vertices may have
  392. * multiple matching edges.
  393. *
  394. * Parameters:
  395. *
  396. * IN graph A graph successfully created by LHGraphCreate.
  397. *
  398. * IN lhsVtx The ID of the left-hand vertex. Legal values are
  399. * 0 <= lhsVtx < numLHSVtx
  400. *
  401. * IN rhsVtx The ID of the right-hand vertex. Legal values are
  402. * 0 <= rhsVtx < numRHSVtx
  403. *
  404. * Return Value:
  405. *
  406. * Error Code
  407. */
  408. int LHSetMatchingEdge( LHGRAPH graph, int lhsVtx, int rhsVtx ) {
  409. Graph *g;
  410. Vertex *lv,*rv;
  411. int i;
  412. /* Check parameters */
  413. g = CheckGraph(graph);
  414. if( NULL==g ) {
  415. return LH_PARAM_ERR;
  416. }
  417. if( lhsVtx<0 || lhsVtx>=g->numLHSVtx ) {
  418. return LH_PARAM_ERR;
  419. }
  420. if( rhsVtx<0 || rhsVtx>=g->numRHSVtx ) {
  421. return LH_PARAM_ERR;
  422. }
  423. /* Get pointers to the two vertices */
  424. lv = &g->lVtx[lhsVtx];
  425. rv = &g->rVtx[rhsVtx];
  426. /* Verify that the edge exists */
  427. for(i=0;i<lv->degree;i++) {
  428. if(lv->adjList[i]==rv) {
  429. break;
  430. }
  431. }
  432. if(i==lv->degree) {
  433. /* Edge does not exist */
  434. return LH_PARAM_ERR;
  435. }
  436. /* Check if the edge is already a matching edge */
  437. if( rv==lv->matchedWith ) {
  438. /* lv and rv are already matched */
  439. return LH_SUCCESS;
  440. }
  441. /* If lv is already matched with another vertex, that vertex must be updated */
  442. if( NULL!=lv->matchedWith ) {
  443. lv->matchedWith->numMatched--;
  444. }
  445. /* Match lv with rv */
  446. lv->matchedWith=rv;
  447. rv->numMatched++;
  448. return LH_SUCCESS;
  449. }
  450. /***** LHGetDegree *****/
  451. /*
  452. * Description:
  453. *
  454. * Get the degree (number of neighbours) of a vertex.
  455. *
  456. * Parameters:
  457. *
  458. * IN graph A graph successfully created by LHGraphCreate.
  459. *
  460. * IN vtxID The ID of the vertex to examine.
  461. *
  462. * IN left If the vertex to examine is a left-vertex, this
  463. * parameter should be TRUE. If the vertex is a right-
  464. * vertex, this parameter should be FALSE.
  465. *
  466. * Return Value:
  467. *
  468. * >=0 The number of neighbours
  469. *
  470. * <0 Error Code
  471. */
  472. int LHGetDegree( LHGRAPH graph, int vtxID, char left ) {
  473. Graph *g;
  474. int degree;
  475. /* Check parameters */
  476. g = CheckGraph(graph);
  477. if( NULL==g ) {
  478. return LH_PARAM_ERR;
  479. }
  480. if( vtxID<0 ) {
  481. return LH_PARAM_ERR;
  482. }
  483. if( left && vtxID>=g->numLHSVtx ) {
  484. return LH_PARAM_ERR;
  485. }
  486. if( !left && vtxID>=g->numRHSVtx ) {
  487. return LH_PARAM_ERR;
  488. }
  489. /* Find the degree of the specified vertex */
  490. if( left ) {
  491. degree = g->lVtx[vtxID].degree;
  492. } else {
  493. degree = g->rVtx[vtxID].degree;
  494. }
  495. assert( degree>=0 );
  496. return degree;
  497. }
  498. /***** LHGetMatchedDegree *****/
  499. /*
  500. * Description:
  501. *
  502. * Get the matched-degree (number of matched neighbours) of a
  503. * right-hand vertex.
  504. *
  505. * Parameters:
  506. *
  507. * IN graph A graph successfully created by LHGraphCreate.
  508. *
  509. * IN vtxID The ID of the right hand vertex to examine.
  510. *
  511. * Return Value:
  512. *
  513. * >=0 The number of neighbours
  514. *
  515. * <0 Error Code
  516. */
  517. int LHGetMatchedDegree( LHGRAPH graph, int vtxID) {
  518. Graph *g;
  519. int degree;
  520. /* Check parameters */
  521. g = CheckGraph(graph);
  522. if( NULL==g ) {
  523. return LH_PARAM_ERR;
  524. }
  525. if( vtxID<0 ) {
  526. return LH_PARAM_ERR;
  527. }
  528. if( vtxID>=g->numRHSVtx ) {
  529. return LH_PARAM_ERR;
  530. }
  531. /* Find the degree of the specified vertex */
  532. degree = g->rVtx[vtxID].numMatched;
  533. assert( degree>=0 );
  534. return degree;
  535. }
  536. /***** LHGetNeighbour *****/
  537. /*
  538. * Description:
  539. *
  540. * Get the n'th neighbour of the vertex specified by vtxID.
  541. *
  542. * Parameters:
  543. *
  544. * IN graph A graph successfully created by LHGraphCreate.
  545. *
  546. * IN vtxID The ID of the vertex to examine.
  547. *
  548. * IN left If the vertex to examine is a left-vertex, this
  549. * parameter should be TRUE. If the vertex is a right-
  550. * vertex, this parameter should be FALSE.
  551. *
  552. * IN n The index of the neighbour to retrieve. Legal values
  553. * are 0 <= n < Degree(vtxID).
  554. *
  555. * Return Value:
  556. *
  557. * >=0 The vertex ID of the n'th neighbour. If 'left' is TRUE,
  558. * this ID refers to a right-hand vertex. Conversely, if
  559. * 'left' is FALSE, this ID refers to a left-hand vertex.
  560. *
  561. * <0 Error Code
  562. */
  563. int LHGetNeighbour( LHGRAPH graph, int vtxID, char left, int n ) {
  564. Graph *g;
  565. int degree;
  566. Vertex* v;
  567. /* Leverage the LHGetDegree function to do most of the input validation */
  568. g = CheckGraph(graph);
  569. degree = LHGetDegree( graph, vtxID, left );
  570. if( degree < 0 ) {
  571. return degree;
  572. }
  573. /* Check parameter n */
  574. if( n<0 || n>=degree ) {
  575. return LH_PARAM_ERR;
  576. }
  577. if( left ) {
  578. v = g->lVtx[vtxID].adjList[n];
  579. assert(v);
  580. /* Transform internal ID to external ID */
  581. return (v->id - g->numLHSVtx);
  582. } else {
  583. v = g->rVtx[vtxID].adjList[n];
  584. assert(v);
  585. return v->id;
  586. }
  587. }
  588. /***** LHFindLHMatching *****/
  589. /*
  590. * Description:
  591. *
  592. * Find an optimal matching in the graph.
  593. *
  594. * Parameters:
  595. *
  596. * IN graph A graph successfully created by LHGraphCreate,
  597. * to which edges have been added using LHAddEdge.
  598. *
  599. * IN alg Specifies which algorithm to use. For most purposes,
  600. * LH_ALG_DEFAULT is fine.
  601. *
  602. * Return Value:
  603. *
  604. * Error Code
  605. */
  606. int LHFindLHMatching( LHGRAPH graph, LHALGTYPE alg ) {
  607. Graph *g;
  608. g = CheckGraph(graph);
  609. if( NULL==g ) {
  610. return LH_PARAM_ERR;
  611. }
  612. ClearAlgState(g);
  613. switch( alg ) {
  614. case LH_ALG_ONLINE:
  615. return LHAlgOnline(g);
  616. break;
  617. case LH_ALG_BFS:
  618. return LHAlgBFS(g);
  619. break;
  620. default:
  621. /* Invalid algorithm selection */
  622. return LH_PARAM_ERR;
  623. }
  624. }
  625. /***** LHGetMatchedVtx *****/
  626. /*
  627. * Description:
  628. *
  629. * Determine which vertex on the right-hand side is matched to a
  630. * given vertex on the left-hand side.
  631. *
  632. * Parameters:
  633. *
  634. * IN graph A graph successfully created by LHGraphCreate,
  635. * to which edges have been added using LHAddEdge.
  636. *
  637. * IN lhsVtx The left-hand vertex to query.
  638. *
  639. * Return Value:
  640. *
  641. * >=0 The index of the right-hand vertex that is matched
  642. * with lhsVtx.
  643. *
  644. * <0 Error Code. If LH_MATCHING_ERR is returned, then
  645. * lhsVtx is not matched with any right-hand vertex.
  646. */
  647. int LHGetMatchedVtx( LHGRAPH graph, int lhsVtx ) {
  648. Graph *g;
  649. Vertex *lv,*rv;
  650. /* Check parameters */
  651. g = CheckGraph(graph);
  652. if( NULL==g ) {
  653. return LH_PARAM_ERR;
  654. }
  655. if( lhsVtx<0 || lhsVtx>=g->numLHSVtx ) {
  656. return LH_PARAM_ERR;
  657. }
  658. /* Get pointer to left-hand vertex */
  659. lv = &(g->lVtx[lhsVtx]);
  660. /* Find matching partner */
  661. rv = lv->matchedWith;
  662. if( rv==NULL ) {
  663. return LH_MATCHING_ERR;
  664. }
  665. /* Transform internal ID to external ID */
  666. return (rv->id - g->numLHSVtx);
  667. }
  668. /***** LHGetStatistics *****/
  669. /*
  670. * Description:
  671. *
  672. * Obtain statistics about the current matching.
  673. *
  674. * Parameters:
  675. *
  676. * IN graph A graph for which an optimal LH Matching has
  677. * been computed using LHFindLHMatching().
  678. *
  679. * Return Value:
  680. *
  681. * Error Code
  682. */
  683. int LHGetStatistics( LHGRAPH graph, LHSTATS *stats ) {
  684. Graph *g;
  685. int i, m=0, mrv=0, trmd=0, cost=0;
  686. /* Check parameters */
  687. g = CheckGraph(graph);
  688. if( NULL==g || NULL==stats ) {
  689. return LH_PARAM_ERR;
  690. }
  691. /* Loop over all right-hand vertices */
  692. for(i=0;i<g->numRHSVtx;i++) {
  693. m+=g->rVtx[i].degree;
  694. if(g->rVtx[i].numMatched>0) mrv++;
  695. trmd+=g->rVtx[i].numMatched;
  696. cost+=g->rVtx[i].numMatched*(g->rVtx[i].numMatched+1)/2;
  697. }
  698. stats->numEdges = m;
  699. stats->numMatchingEdges = trmd;
  700. stats->matchingCost = cost;
  701. stats->bipMatchingSize = mrv;
  702. return LH_SUCCESS;
  703. }
  704. /***** LHClearMatching *****/
  705. /*
  706. * Description:
  707. *
  708. * Clear the current matching.
  709. *
  710. * Parameters:
  711. *
  712. * IN graph A graph successfully created by LHGraphCreate,
  713. * to which edges have been added using LHAddEdge.
  714. *
  715. * Return Value:
  716. *
  717. * Error Code
  718. */
  719. int LHClearMatching( LHGRAPH graph ) {
  720. Graph *g;
  721. int i;
  722. /* Check parameters */
  723. g = CheckGraph(graph);
  724. if( NULL==g ) {
  725. return LH_PARAM_ERR;
  726. }
  727. /* Clear left-hand vertices */
  728. for( i=0; i<g->numLHSVtx; i++ ) {
  729. g->lVtx[i].matchedWith=NULL;
  730. }
  731. /* Clear right-hand vertices */
  732. for( i=0; i<g->numRHSVtx; i++ ) {
  733. g->rVtx[i].numMatched=0;
  734. }
  735. return LH_SUCCESS;
  736. }
  737. /***** LHDestroyGraph *****/
  738. /*
  739. * Description:
  740. *
  741. * Destroy the current graph.
  742. *
  743. * Parameters:
  744. *
  745. * IN graph A graph successfully created by LHGraphCreate.
  746. *
  747. * Return Value:
  748. *
  749. * Error Code
  750. */
  751. int LHDestroyGraph( LHGRAPH graph ) {
  752. Graph *g;
  753. int i;
  754. /* Check parameters */
  755. g = CheckGraph(graph);
  756. if( NULL==g ) {
  757. return LH_PARAM_ERR;
  758. }
  759. /* Free each vertex's adjacency list */
  760. for(i=0;i<g->numLHSVtx;i++) {
  761. free( g->lVtx[i].adjList );
  762. }
  763. for(i=0;i<g->numRHSVtx;i++) {
  764. free( g->rVtx[i].adjList );
  765. }
  766. /* Free all other lists */
  767. if( g->lVtx ) free( g->lVtx );
  768. if( g->rVtx ) free( g->rVtx );
  769. if( g->Buckets ) free( g->Buckets );
  770. if( g->Queue ) free( g->Queue );
  771. /* Clear and free the graph itself */
  772. memset(graph,0,sizeof(Graph));
  773. free(graph);
  774. return LH_SUCCESS;
  775. }