int main () { int i, data; int v_id[V_COUNT]; DfsVertex *dfs_vs[V_COUNT]; Graph graph; DfsVertex *dfs_vertex; List ordered; ListElmt *element; graph_init (&graph, &match, NULL); for (i = 0; i < V_COUNT; i++) { v_id[i] = i; if ((dfs_vertex = (DfsVertex *) malloc (sizeof(DfsVertex))) == NULL) return -1; dfs_vertex->data = &v_id[i]; dfs_vertex->color = white; dfs_vs[i] = dfs_vertex; graph_ins_vertex (&graph, (void *) dfs_vertex); /* printf ("vertex[%d] addr=%d\n", i, (void *) &vertex[i]); */ } printf ("graph vcount=%d\n", graph_vcount (&graph)); /* Graph as in figure 11.8 Network hops. */ /* graph_ins_edge (&graph, (void *) dfs_vs[0], (void *) dfs_vs[1]); */ graph_ins_edge (&graph, (void *) dfs_vs[0], (void *) dfs_vs[2]); graph_ins_edge (&graph, (void *) dfs_vs[2], (void *) dfs_vs[1]); graph_ins_edge (&graph, (void *) dfs_vs[1], (void *) dfs_vs[3]); /* graph_ins_edge (&graph, (void *) dfs_vs[2], (void *) dfs_vs[4]); */ graph_ins_edge (&graph, (void *) dfs_vs[3], (void *) dfs_vs[4]); graph_ins_edge (&graph, (void *) dfs_vs[4], (void *) dfs_vs[5]); graph_ins_edge (&graph, (void *) dfs_vs[1], (void *) dfs_vs[6]); printf ("graph ecount=%d\n", graph_ecount (&graph)); dfs (&graph, &ordered); printf ("size of ordered list=%d\n", list_size (&ordered)); for (element = list_head (&ordered); element != NULL; element = list_next (element)) { dfs_vertex = (list_data (element)); printf ("vertex id=%d,\tcolour=%d\n", *(int *) dfs_vertex->data, (int) dfs_vertex->color); } list_destroy (&ordered); graph_destroy (&graph); return 0; }
/** * 测试最小生成树 */ void test_mini_span_tree_from_graph() { Student s[] = { *studn_get_init(1, "a", 0, 22, 11), *studn_get_init(2, "b", 0, 22, 11), *studn_get_init(3, "c", 0, 22, 11), *studn_get_init(4, "d", 0, 22, 11), *studn_get_init(5, "e", 0, 22, 11), *studn_get_init(6, "f", 0, 22, 11), }; MstVertex m[] = { /*0*/*mst_vertex_get_init((void *)(&s[0]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[1]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[2]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[3]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[4]), 0, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 0, (int (*)(const void *, const void *))studn_match, NULL), /*a点延伸出去的边的连接节点*/ /*6*/*mst_vertex_get_init((void *)(&s[1]), 7, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[2]), 4, (int (*)(const void *, const void *))studn_match, NULL), /*b点延伸出去的边的连接节点*/ /*8*/*mst_vertex_get_init((void *)(&s[0]), 7, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[2]), 6, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[3]), 2, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 4, (int (*)(const void *, const void *))studn_match, NULL), /*c点延伸出去的边的连接节点*/ /*12*/*mst_vertex_get_init((void *)(&s[0]), 4, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[1]), 6, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[4]), 9, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 8, (int (*)(const void *, const void *))studn_match, NULL), /*d点延伸出去的边的连接节点*/ /*16*/*mst_vertex_get_init((void *)(&s[1]), 2, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 7, (int (*)(const void *, const void *))studn_match, NULL), /*e点延伸出去的边的连接节点*/ /*18*/*mst_vertex_get_init((void *)(&s[2]), 9, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[5]), 1, (int (*)(const void *, const void *))studn_match, NULL), /*f点延伸出去的边的连接节点*/ /*20*/*mst_vertex_get_init((void *)(&s[1]), 4, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[2]), 8, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[3]), 7, (int (*)(const void *, const void *))studn_match, NULL), *mst_vertex_get_init((void *)(&s[4]), 1, (int (*)(const void *, const void *))studn_match, NULL), }; Graph graph; graph_init(&graph, (int (*)(const void *, const void *))mst_vertex_match, NULL); int i; //插入所有的节点 for (i = 0; i < 6; ++i) { graph_ins_vertex(&graph, &m[i]); } printf("%s\n", "insert vertex success"); //插入所有的边 graph_ins_edge(&graph, &m[0], &m[6]); graph_ins_edge(&graph, &m[0], &m[7]); graph_ins_edge(&graph, &m[1], &m[8]); graph_ins_edge(&graph, &m[1], &m[9]); graph_ins_edge(&graph, &m[1], &m[10]); graph_ins_edge(&graph, &m[1], &m[11]); graph_ins_edge(&graph, &m[2], &m[12]); graph_ins_edge(&graph, &m[2], &m[13]); graph_ins_edge(&graph, &m[2], &m[14]); graph_ins_edge(&graph, &m[2], &m[15]); graph_ins_edge(&graph, &m[3], &m[16]); graph_ins_edge(&graph, &m[3], &m[17]); graph_ins_edge(&graph, &m[4], &m[18]); graph_ins_edge(&graph, &m[4], &m[19]); graph_ins_edge(&graph, &m[5], &m[20]); graph_ins_edge(&graph, &m[5], &m[21]); graph_ins_edge(&graph, &m[5], &m[22]); graph_ins_edge(&graph, &m[5], &m[23]); List span; mst(&graph, m, &span, (int (*)(const void *, const void *))mst_vertex_match); list_resetIterator(&span); while (list_hasNext(&span)) { list_moveToNext(&span); MstVertex *vertex = NULL; list_iterator(&span, (void **)(&vertex)); Student *s = (Student *)vertex->data; printf("key : %.0f", vertex->key); if (vertex->parent != NULL) { Student *sP = (Student *)(vertex->parent->data); printf(", parentid:%d, ", sP->_id); } studn_print(s); } return; }
int main(int argc, char **argv) { Graph graph; MstVertex *mst_start, *mst_vertex, mst_vertex1, *mst_vertex2; PathVertex *pth_start, *pth_vertex, pth_vertex1, *pth_vertex2; TspVertex *tsp_start, *tsp_vertex; List span, paths, vertices, tour; ListElmt *element; double distance, total, x, y; int i; /***************************************************************************** * * * Compute a minimum spanning tree. * * * *****************************************************************************/ graph_init(&graph, match_mst, free); fprintf(stdout, "Computing a minimum spanning tree\n"); for (i = 0; i < MSTVCT; i++) { if ((mst_vertex = (MstVertex *) malloc(sizeof(MstVertex))) == NULL) return 1; if (i == 0) mst_start = mst_vertex; mst_vertex->data = MstTestV[i]; if (graph_ins_vertex(&graph, mst_vertex) != 0) return 1; } for (i = 0; i < MSTECT; i++) { if ((mst_vertex2 = (MstVertex *) malloc(sizeof(MstVertex))) == NULL) return 1; mst_vertex1.data = MstTestE[i].vertex1; mst_vertex2->data = MstTestE[i].vertex2; mst_vertex2->weight = MstTestE[i].weight; if (graph_ins_edge(&graph, &mst_vertex1, mst_vertex2) != 0) return 1; } print_graph_mst(&graph); if (mst(&graph, mst_start, &span, match_mst) != 0) return 1; for (element = list_head(&span); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); fprintf(stdout, "vertex=%s, parent=%s\n", (char *) mst_vertex->data, mst_vertex->parent != NULL ? (char *) mst_vertex->parent->data : "*"); } list_destroy(&span); graph_destroy(&graph); /***************************************************************************** * * * Compute shortest paths. * * * *****************************************************************************/ graph_init(&graph, match_pth, free); fprintf(stdout, "Computing shortest paths\n"); for (i = 0; i < PTHVCT; i++) { if ((pth_vertex = (PathVertex *) malloc(sizeof(PathVertex))) == NULL) return 1; if (i == 0) pth_start = pth_vertex; pth_vertex->data = PthTestV[i]; if (graph_ins_vertex(&graph, pth_vertex) != 0) return 1; } for (i = 0; i < PTHECT; i++) { if ((pth_vertex2 = (PathVertex *) malloc(sizeof(PathVertex))) == NULL) return 1; pth_vertex1.data = PthTestE[i].vertex1; pth_vertex2->data = PthTestE[i].vertex2; pth_vertex2->weight = PthTestE[i].weight; if (graph_ins_edge(&graph, &pth_vertex1, pth_vertex2) != 0) return 1; } print_graph_pth(&graph); if (shortest(&graph, pth_start, &paths, match_pth) != 0) return 1; for (element = list_head(&paths); element != NULL; element = list_next(element)) { pth_vertex = list_data(element); fprintf(stdout, "vertex=%s, parent=%s, d=%.1lf\n", (char *) pth_vertex->data, pth_vertex->parent != NULL ? (char *) pth_vertex->parent->data : "*", pth_vertex->d); } list_destroy(&paths); graph_destroy(&graph); /***************************************************************************** * * * Solve the traveling-salesman problem. * * * *****************************************************************************/ /*list_init(&vertices, free); fprintf(stdout, "Solving a traveling-salesman problem\n"); for (i = 0; i < TSPVCT; i++) { if ((tsp_vertex = (TspVertex *)malloc(sizeof(TspVertex))) == NULL) return 1; if (i == 0) tsp_start = tsp_vertex; tsp_vertex->data = TspTestV[i].vertex; tsp_vertex->x = TspTestV[i].x; tsp_vertex->y = TspTestV[i].y; if (list_ins_next(&vertices, list_tail(&vertices), tsp_vertex) != 0) return 1; } print_list_tsp(&vertices); if (tsp(&vertices, tsp_start, &tour, match_tsp) != 0) return 1; total = 0; for (element = list_head(&tour); element != NULL; element = list_next(element)) { tsp_vertex = list_data(element); if (!list_is_head(&tour, element)) { distance = sqrt(pow(tsp_vertex->x-x, 2.0) + pow(tsp_vertex->y-y, 2.0)); total = total + distance; } x = tsp_vertex->x; y = tsp_vertex->y; if (!list_is_head(&tour, element)) { fprintf(stdout, "vertex=%s, distance=%.2lf\n", (char *)tsp_vertex-> data, distance); } else fprintf(stdout, "vertex=%s\n", (char *)tsp_vertex->data); } fprintf(stdout, "total=%.2lf\n", total); list_destroy(&vertices); list_destroy(&tour);*/ return 0; }
int main(int argc, char **argv) { Graph graph; DfsVertex *task, task1, *task2; List list; ListElmt *element; char data1[STRSIZ]; int i; /***************************************************************************** * Initialize the graph. * *****************************************************************************/ graph_init(&graph, match_task, destroy_task); /***************************************************************************** * Insert some tasks. * *****************************************************************************/ if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "a"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "b"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "c"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "d"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "e"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "f"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "g"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "h"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; if ((task = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task->data, "i"); fprintf(stdout, "Inserting vertex %s\n", (char *)task->data); if (graph_ins_vertex(&graph, task) != 0) return 1; print_graph(&graph); /***************************************************************************** * Insert some dependencies. * *****************************************************************************/ task1.data = data1; if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "a"); strcpy((char *)task2->data, "b"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "a"); strcpy((char *)task2->data, "c"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "b"); strcpy((char *)task2->data, "i"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "c"); strcpy((char *)task2->data, "i"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "e"); strcpy((char *)task2->data, "f"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "e"); strcpy((char *)task2->data, "h"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "f"); strcpy((char *)task2->data, "c"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "f"); strcpy((char *)task2->data, "h"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); if ((task2 = (DfsVertex *) malloc(sizeof(DfsVertex))) == NULL) return 1; if ((task2->data = malloc(STRSIZ)) == NULL) return 1; strcpy((char *)task1.data, "g"); strcpy((char *)task2->data, "h"); fprintf(stdout, "Inserting edge %s to %s\n", (char *)task1.data, (char *) task2->data); if (graph_ins_edge(&graph, &task1, task2) != 0) return 1; print_graph(&graph); /***************************************************************************** * Perform depth-first search. * *****************************************************************************/ fprintf(stdout, "Generating the depth-first search listing\n"); if (dfs(&graph, &list) != 0) return 1; i = 0; for (element = list_head(&list); element != NULL; element = list_next(element)) { task = list_data(element); fprintf(stdout, "list[%03d]=%s (color=%d)\n", i, (char *)task->data, task->color); i++; } /***************************************************************************** * Destroy the linked list. * *****************************************************************************/ fprintf(stdout, "Destroying the list\n"); list_destroy(&list); /***************************************************************************** * Destroy the graph. * *****************************************************************************/ fprintf(stdout, "Destroying the graph\n"); graph_destroy(&graph); return 0; }
int gridSteinerFH(Graph *grid_graph, AdjList**** Edge2Adj, int width, int height, CoordData *term, int no_terminals, double *L,int net_num, int *edge_count_OUT, int **SteinerTree_OUT, int l, int K) { int i,j; /* globals */ int GRID_WIDTH, GRID_HEIGHT, NO_TERMINALS; Graph ND; /* distance network of terminals */ /*used to generate grid graph */ PathVertex *path_vertex; sPathData *sPath_vertex; CoordData *coord; /* used in shortest paths computations */ PathVertex **terminals; /* a (1D) array of terminal (pointers) */ List *tempPaths, /* tempporary */ **sPaths; /* 2d array of shortest path lists */ ListElmt *element; /* temp, used to traverse a list */ /* used in computing MST of ND */ MstVertex *mst_start, *mst_vertex, *mst_vertex1, *mst_vertex2; List TD; /* spanning tree of ND */ /* used in final steps of algorithm */ Graph NTD; /* complete distance network */ List T; /* spanning tree of NTD (eventually the steiner tree)*/ int isSteiner; /* boolean flag */ double tree_cost; /* total cost of the steiner tree (unused, this is computed after*/ GRID_WIDTH = width; GRID_HEIGHT = height; NO_TERMINALS = no_terminals; mst_start = NULL; /*-----------------------------------------------*/ /* If the number of terminals is two, then we */ /* only need to perform one call of Dijkstra to */ /* get the Steiner Tree */ /*-----------------------------------------------*/ if (NO_TERMINALS == 2) { PathVertex *v1,*v2; /* the two terminals*/ CoordData *c1,*c2; /* coordinates of the two terminals*/ List P; /* P-Array in Dijkstra's*/ ListElmt *e; /* list counter*/ List T; /* steiner tree*/ double tree_cost; int j; int first_edge,last_edge; PathVertex *u; u = NULL; /* allocate vertices */ v1 = (PathVertex*) malloc(sizeof(PathVertex)); v2 = (PathVertex*) malloc(sizeof(PathVertex)); c1 = (CoordData*) malloc(sizeof(CoordData)); c2 = (CoordData*) malloc(sizeof(CoordData)); /* set terminal data */ c1->x = term[0].x; c1->y = term[0].y; c1->z = term[0].z; c2->x = term[1].x; c2->y = term[1].y; c2->z = term[1].z; v1->data = c1; v2->data = c2; /* compute shortest path from v1 */ if (shortest(grid_graph, v1 , &P, match_coord,GRID_WIDTH,GRID_HEIGHT) != 0) return 1; /* initialize the tree */ list_init(&T,NULL); /* find the end vertex (v2)*/ for (e = list_head(&P); e != NULL; e = list_next(e)) if ( match_coord(v2,list_data(e))) u = (PathVertex*)list_data(e); first_edge = 1; last_edge = 0; /* follow the end vertex back to the start vertex*/ while (u->parent != NULL) { int ux,uy,uz,upx,upy,upz; AdjList *a; ListElmt *ee; /*current vertex*/ ux = ((CoordData*)((PathVertex*)u)->data)->x; uy = ((CoordData*)((PathVertex*)u)->data)->y; uz = ((CoordData*)((PathVertex*)u)->data)->z; /*connecting vertex (parent)*/ upx = ((CoordData*)((PathVertex*)u->parent)->data)->x; upy = ((CoordData*)((PathVertex*)u->parent)->data)->y; upz = ((CoordData*)((PathVertex*)u->parent)->data)->z; /* get the index of the edge that connects (ux,uy,uz) and its parent*/ a = Edge2Adj[ux][uy][uz]; for (ee = list_head(&a->adjacent); ee != NULL; ee = list_next(ee)) { PathVertex *v; int *i; int vx,vy,vz; v = (PathVertex*)list_data(ee); vx = ((CoordData*)v->data)->x; vy = ((CoordData*)v->data)->y; vz = ((CoordData*)v->data)->z; /* found it*/ if (( vx == upx ) && ( vy == upy ) && ( vz == upz )) { /*don't insert if its a via*/ if (first_edge) { first_edge = 0; if (v->index > ((grid_graph->ecount / 2) - (grid_graph->vcount/2))) continue; } /*check if its the last edge*/ if (u->parent != NULL) if (u->parent->parent == NULL) last_edge = 1; /* don't insert if its a via*/ if (last_edge) if (v->index > ((grid_graph->ecount / 2) - (grid_graph->vcount/2))) continue; i = (int*) malloc(sizeof(int)); tree_cost += v->weight; *i = v->index; list_ins_next(&T, list_tail(&T),i); } } /* next */ u = u->parent; } /* count total edges*/ *edge_count_OUT = list_size(&T); /* write the solution (including vias)*/ if ((*(SteinerTree_OUT) = (int*) malloc(sizeof(int)*(list_size(&T))))==NULL) { printf("gsFH.h : SteinerTree_OUT mem allocation error\n"); fflush(stdout); exit(1); } e = list_head(&T); for (j = 0; ((j < list_size(&T))&&(e!=NULL)); j++,e=list_next(e)) (*SteinerTree_OUT)[j] = *((int*)list_data(e)); /* free up some temps*/ free(v1->data); free(v1); free(v2->data); free(v2); list_destroy(&P); list_destroy(&T); return 0; } /*--------------------------------------------------------*/ /* General case of 3 or more terminals begins here. The */ /* above code for 2 terminals or less can be removed */ /* without affecting the block solution. However, it is */ /* faster with the special case */ /*--------------------------------------------------------*/ /* Create Path Vertices out of the original terminal set */ if ((terminals = (PathVertex**) malloc(sizeof(PathVertex*)*NO_TERMINALS))==NULL) { printf("gsFH.h : terminals mem allocation error\n"); fflush(stdout); exit(1); } for (i = 0; i < NO_TERMINALS; i++) { int x,y,z; x = term[i].x; y = term[i].y; z = term[i].z; path_vertex = (PathVertex*) malloc(sizeof(PathVertex)); coord = (CoordData*) malloc(sizeof(CoordData)); if ((path_vertex == NULL)||(coord == NULL)) { printf("gsFH.h : terminal[i] mem allocation error\n"); fflush(stdout); exit(1); } coord->x = x; coord->y = y; coord->z = z; path_vertex->data = coord; terminals[i] = path_vertex; } /* inialize an array of list pointers used in extracting shortest paths from Dijkstra */ sPaths = (List**) malloc(sizeof(List*)*NO_TERMINALS); if (sPaths == NULL) { printf("gsFH.h : sPaths mem allocation error\n"); fflush(stdout); exit(1); } if ((tempPaths = (List*) malloc(sizeof(List)*NO_TERMINALS))==NULL) { printf("gsFH.h : tempPaths mem allocation error\n"); fflush(stdout); exit(1); } for (i = 0; i < NO_TERMINALS; i++) if ((sPaths[i] = (List*) malloc(sizeof(List)*NO_TERMINALS))==NULL) { printf("gsFH.h : sPaths[i] mem allocation error\n"); fflush(stdout); exit(1); } /*--------------------------------------------------------------------------------------*/ /* COMPUTE THE SHORTEST PATHS */ /* Shortest paths are computed using O(EV^2) version of Dijkstras Algorithm */ /*--------------------------------------------------------------------------------------*/ /* for each terminal (stored as a path vertex), find the shortest path */ /* The shortest path for terminal[i] is stored in the List pointed to by */ /* paths[i]. */ for (i = 0; i < NO_TERMINALS; i++) { if (shortest(grid_graph, terminals[i], &tempPaths[i], match_coord,GRID_WIDTH,GRID_HEIGHT) != 0) return 1; /* copy out the shortest path data, if we don't do this, it will get overwritten*/ for (j = 0; j < NO_TERMINALS; j++) if (i != j) copy_sPath(&tempPaths[i], &(sPaths[i][j]), (CoordData*)((PathVertex*)terminals[j])->data); } /*--------------------------------------------------------------------------------------------------*/ /* Generate complete distance network ND */ /*--------------------------------------------------------------------------------------------------*/ /* initialize the graph */ graph_init(&ND, match_coord, (void*)mst_vertex_free); /* insert the verticies. Verticies consist of all the terminals */ for (i = 0; i < NO_TERMINALS; i++) { /* allocate space for a MST vertex */ if ((mst_vertex = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("Error allocating space for mst_vertex\n"); printf("Terminating..\n"); return 1; } /* if it's the first, make it the start. It doesn't matter which one is the start */ if (i == 1) mst_start = mst_vertex; /* set the data */ if ((coord = (CoordData*) malloc(sizeof(CoordData)))==NULL) { printf("gsFH.h : coord mem allocation error\n"); fflush(stdout); exit(1); } coord->x = ((CoordData*)(((PathVertex*)terminals[i])->data))->x; coord->y = ((CoordData*)(((PathVertex*)terminals[i])->data))->y; coord->z = ((CoordData*)(((PathVertex*)terminals[i])->data))->z; mst_vertex->data = coord; /* insert */ if (graph_ins_vertex(&ND, mst_vertex) != 0) { printf("Error inserting vertex into mst_graph\n"); printf("Terminating...\n"); return 1; } } /* now we must insert the edges into the distance network graph ND. We do this by accessing the shortest path lists (sPath) computed in the previous step */ for (i = 0; i < NO_TERMINALS; i++) { int ux,uy,uz; ux = ((CoordData*)((PathVertex*)terminals[i])->data)->x; uy = ((CoordData*)((PathVertex*)terminals[i])->data)->y; uz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; for (j = 0; j < NO_TERMINALS; j++) { int vx,vy,vz; /* shouldn't be an edge from a terminal to itself */ if (i != j) { double weight; CoordData *v1,*v2; int eCode; vx = ((CoordData*)((PathVertex*)terminals[j])->data)->x; vy = ((CoordData*)((PathVertex*)terminals[j])->data)->y; vz = ((CoordData*)((PathVertex*)terminals[j])->data)->z; /* now we must find how far away vx is from vy. we do this by looking for at the head element in sPath[i][j] */ element = list_head(&(sPaths[i][j])); sPath_vertex = list_data(element); weight = ((sPathData*)sPath_vertex)->d; /* allocate an edge */ if ((v1 = (CoordData*) malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : v1 mem allocation error\n"); fflush(stdout); exit(1); } if ((v2 = (CoordData*) malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : v2 mem allocation error\n"); fflush(stdout); exit(1); } v1->x = ux; v1->y = uy; v1->z = uz; v2->x = vx; v2->y = vy; v2->z = vz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data =v1; mst_vertex2->data = v2; mst_vertex2->weight = weight; if ((eCode = graph_ins_edge(&ND, mst_vertex1, mst_vertex2)) != 0) { printf("Error inserting edge into ND\n"); printf("graph_ins_edge returned the value %d\n",eCode); return 1; } free(mst_vertex1->data); free(mst_vertex1); }/* endif i!=j */ }/* endfor j */ }/* endfor i */ /*--------------------------------------------------------------------------------------------------*/ /* Copmute TD (Min Span Tree of ND) */ /*--------------------------------------------------------------------------------------------------*/ if (mst(&ND, mst_start,&TD, match_coord) != 0) { printf("Error computing minimum spanning tree\n"); return 1; } /* set leaves */ /* initialize */ for ( element = list_head(&TD); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (element = list_head(&TD); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /*--------------------------------------------------------------------------------------------------*/ /* Find N[TD] */ /*--------------------------------------------------------------------------------------------------*/ graph_init(&NTD,match_coord,(void*)mst_vertex_free); /* for each edge in TD */ for (element = list_head(&TD); element != NULL; element = list_next(element)) { MstVertex *nextVertex; int v,p; p = -1; v = -1; nextVertex = list_data(element); /* if it is not the root */ if (nextVertex->parent != NULL) { int vx,vy,vz,px,py,pz; ListElmt *currentV, *nextV; int done; vx = ((CoordData*)((MstVertex*)nextVertex)->data)->x; vy = ((CoordData*)((MstVertex*)nextVertex)->data)->y; vz = ((CoordData*)((MstVertex*)nextVertex)->data)->z; px = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->x; py = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->y; pz = ((CoordData*)(MstVertex*)(nextVertex->parent)->data)->z; /* find terminal index of nextVertex and nextVertex->parent */ for (i = 0; i < NO_TERMINALS; i++) { int tx,ty,tz; tx = ((CoordData*)((PathVertex*)terminals[i])->data)->x; ty = ((CoordData*)((PathVertex*)terminals[i])->data)->y; tz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; if ((tx == vx)&&(ty == vy)&&(tz == vz)) v = i; if ((tx == px)&&(ty == py)&&(tz == pz)) p = i; } /* now, we must step through the list of sPathData elements found in sPaths[p][v]. For each element in the list, we must insert vertices for the vertex and parent, then make an edge with the appropriate weight and insert it */ currentV = list_head(&(sPaths[p][v])); nextV = list_next(currentV); done = 0; while ( !done ) { MstVertex *u,*v, *mst_vertex1, *mst_vertex2; CoordData *uc,*vc; sPathData *currentVData, *nextVData; int cvx,cvy,cvz,nvx,nvy,nvz; double weight; /*---------------------------------------*/ /* insert vertices u and v into NTD */ /*---------------------------------------*/ /* make a vertex for currentV and nextV */ u = (MstVertex*) malloc(sizeof(MstVertex)); v = (MstVertex*) malloc(sizeof(MstVertex)); uc = (CoordData*) malloc(sizeof(CoordData)); vc = (CoordData*) malloc(sizeof(CoordData)); if ((u == NULL)||(uc==NULL)||(v==NULL)||(vc==NULL)) { printf("gsFH.h : error allocating vertex for NTD\n"); fflush(stdout); exit(1); } /* get vertices from the sPaths list */ currentVData = list_data(currentV); nextVData = list_data(nextV); /* get vertex data */ cvx = ((CoordData*)((sPathData*)currentVData)->vertex)->x; cvy = ((CoordData*)((sPathData*)currentVData)->vertex)->y; cvz = ((CoordData*)((sPathData*)currentVData)->vertex)->z; nvx = ((CoordData*)((sPathData*)nextVData)->vertex)->x; nvy = ((CoordData*)((sPathData*)nextVData)->vertex)->y; nvz = ((CoordData*)((sPathData*)nextVData)->vertex)->z; /* set vertex data */ uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; u->data = uc; v->data = vc; /* calculate weight between u and v */ weight = currentVData->d - nextVData->d; /* try and insert u, if it exists, then delete the memory we allocated for it */ if ( graph_ins_vertex(&NTD, u) == 1 ) { free(uc); free(u); } else { /* doesnt' matter which one is the start */ mst_start = u; } /* try and insert v, if it exists, then delete the memorr we allocated for it */ if ( graph_ins_vertex(&NTD, v) == 1) { free(vc); free(v); } /* now the vertices u and v are in the graph. we now have to make an edge for uv */ /* make edge going forward */ if ((uc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : uc mem allocation error\n"); fflush(stdout); exit(1); } if ((vc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : vc mem allocation error\n"); fflush(stdout); exit(1); } uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*)malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data = uc; mst_vertex2->data = vc; mst_vertex2->weight = weight; /* try and insert, if it exists, free previously allocated mem */ if ( graph_ins_edge(&NTD, mst_vertex1, mst_vertex2) == 1) { free(vc); free(mst_vertex2); } /* free the label */ free(mst_vertex1->data); free(mst_vertex1); /* make edge going backward */ if ((uc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : uc mem allocation error\n"); fflush(stdout); exit(1); } if ((vc = (CoordData*)malloc(sizeof(CoordData))) == NULL) { printf("gsFH.h : vc mem allocation error\n"); fflush(stdout); exit(1); } uc->x = cvx; uc->y = cvy; uc->z = cvz; vc->x = nvx; vc->y = nvy; vc->z = nvz; if ((mst_vertex1 = (MstVertex*) malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((mst_vertex2 = (MstVertex*)malloc(sizeof(MstVertex))) == NULL) { printf("gsFH.h : mst_Vertex2 mem allocation error\n"); fflush(stdout); exit(1); } mst_vertex1->data = vc; mst_vertex2->data = uc; mst_vertex2->weight = weight; /* try and insert, if it exists, free previously allocated mem */ if ( graph_ins_edge(&NTD, mst_vertex1, mst_vertex2) == 1) { free(uc); free(mst_vertex2); } /* free the label */ free(mst_vertex1->data); free(mst_vertex1); /* follow pointers */ currentV = list_next(currentV); nextV = list_next(nextV); /* check to see if we're finished */ if (nextV == NULL) done = 1; } } } /*----------------------------------------------------------------------------------------------------------*/ /* Compute T (minimum spanning tree of NTD) */ /*----------------------------------------------------------------------------------------------------------*/ /* call minimum spanning tree subroutine */ if (mst(&NTD, mst_start,&T, match_coord) != 0) { printf("Error computing minimum spanning tree\n"); return 1; } /* set leaves */ for ( element = list_head(&T); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (element = list_head(&T); element != NULL; element = list_next(element)) { mst_vertex = list_data(element); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /*--------------------------------------------------------------------------------------*/ /* Compute Steiner Tree Sk */ /*--------------------------------------------------------------------------------------*/ isSteiner = 0; /* we remove all leaves that arent' terminals, when all leaves are terminals then we have a Steiner Tree */ while (!isSteiner) { ListElmt *prev; /* assume we have it */ isSteiner = 1; /* check if each leaf is a terminal */ prev = list_head(&T); element = list_next(prev); while (element != NULL) { int mx,my,mz; mst_vertex = list_data(element); mx = ((CoordData*)((MstVertex*)mst_vertex)->data)->x; my = ((CoordData*)((MstVertex*)mst_vertex)->data)->y; mz = ((CoordData*)((MstVertex*)mst_vertex)->data)->z; if (mst_vertex->is_leaf) { int found; found = 0; for (i = 0; i < NO_TERMINALS; i++) { int tx,ty,tz; tx = ((CoordData*)((PathVertex*)terminals[i])->data)->x; ty = ((CoordData*)((PathVertex*)terminals[i])->data)->y; tz = ((CoordData*)((PathVertex*)terminals[i])->data)->z; if ( (tx==mx)&&(ty==my)&&(tz==mz)) found = 1; } /* remove it if we can't find it */ if (!found) { MstVertex *junk; ListElmt *e; isSteiner = 0; /* not done yet */ list_rem_next(&T, prev, (void**)(&junk)); /*reset leaves */ /* initialize */ for ( e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /* start over at beginning of list */ prev = list_head(&T); element = list_next(prev); } else { prev = list_next(prev); element = list_next(element); } } else { prev = list_next(prev); element = list_next(element); } } } /* we can further eliminate vias that connect to a terminal leaf. These are not neccessary*/ isSteiner = 0; while (!isSteiner) { ListElmt *prev; /* assume we have it */ isSteiner = 1; /* check if each leaf is a terminal */ prev = list_head(&T); element = list_next(prev); while (element != NULL) { int mx,my,mz; mst_vertex = list_data(element); mx = ((CoordData*)((MstVertex*)mst_vertex)->data)->x; my = ((CoordData*)((MstVertex*)mst_vertex)->data)->y; mz = ((CoordData*)((MstVertex*)mst_vertex)->data)->z; if (mst_vertex->is_leaf) { int remove; int px,py; remove = 0; px = ((CoordData*)((MstVertex*)mst_vertex->parent)->data)->x; py = ((CoordData*)((MstVertex*)mst_vertex->parent)->data)->y; if ((px == mx)&&(py == my)) remove = 1; /* remove it if neccessary */ if (remove) { MstVertex *junk; ListElmt *e; isSteiner = 0; /* not done yet */ list_rem_next(&T, prev, (void**)(&junk)); /*reset leaves */ /* initialize */ for ( e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); mst_vertex->is_leaf = 1; } /* for each node, set the parent is_leaf to 0. Then, all leaves will remain */ for (e = list_head(&T); e != NULL; e = list_next(e)) { mst_vertex = list_data(e); if (mst_vertex->parent != NULL) mst_vertex->parent->is_leaf = 0; } /* start over at beginning of list */ prev = list_head(&T); element = list_next(prev); } else { prev = list_next(prev); element = list_next(element); } } else { prev = list_next(prev); element = list_next(element); } } } /* get the total cost of the tree */ tree_cost = 0; for (element = list_head(&T); element != NULL; element = list_next(element)) { CoordData *u, *v; mst_vertex = list_data(element); if (( mst_vertex->parent == NULL)) continue; else { double temp; u = (CoordData*)mst_vertex->data; v = (CoordData*)mst_vertex->parent->data; /* look up cost of edge uv */ temp = find_edge_weight(grid_graph,u,v); tree_cost += temp; } } *edge_count_OUT = list_size(&T)-1; if ((*(SteinerTree_OUT) = (int*) malloc(sizeof(int)*(list_size(&T)-1)))==NULL) { printf("gsFH.h : SteinerTree_OUT mem allocation error\n"); fflush(stdout); exit(1); } i = 0; for ( element = list_head(&T); element != NULL; element = list_next(element)) { int vx,vy,vz,px,py,pz; int tx,ty,tz; AdjList *a; ListElmt *e; int edge_index; double edge_weight; mst_vertex = list_data(element); vx = ((CoordData*)mst_vertex->data)->x; vy = ((CoordData*)mst_vertex->data)->y; vz = ((CoordData*)mst_vertex->data)->z; if (mst_vertex->parent != NULL) { px = ((CoordData*)mst_vertex->parent->data)->x; py = ((CoordData*)mst_vertex->parent->data)->y; pz = ((CoordData*)mst_vertex->parent->data)->z; edge_weight = mst_vertex->weight; } else { px = -1; py = -1; pz = -1; } a = (AdjList*)Edge2Adj[vx][vy][vz]; tx = ((CoordData*)((PathVertex*)(a->vertex))->data)->x; ty = ((CoordData*)((PathVertex*)(a->vertex))->data)->y; tz = ((CoordData*)((PathVertex*)(a->vertex))->data)->z; for ( e = list_head(&(a->adjacent)); e != NULL; e = list_next(e) ) { PathVertex *p; p = (PathVertex*)list_data(e); tx = ((CoordData*)p->data)->x; ty = ((CoordData*)p->data)->y; tz = ((CoordData*)p->data)->z; if ((tx == px)&&(ty == py)&&(tz == pz)) { /*found*/ edge_index = p->index; (*SteinerTree_OUT)[i] = edge_index; i++; } } } /*-------------------------------------------------------------------------------------*/ /* Clean Up */ /*-------------------------------------------------------------------------------------*/ /* free our list of temporary paths*/ for (i = 0; i < NO_TERMINALS; i++) list_destroy(&tempPaths[i]); free(tempPaths); /* destroy distance network*/ graph_destroy(&ND); /* deystroy all the shortest path lists*/ for (i = 0; i < NO_TERMINALS; i++) for (j = 0; j < NO_TERMINALS; j++) if ( i != j ) list_destroy(&sPaths[i][j]); /* destroy the pointers to the shortest path lists*/ for (i = 0; i < NO_TERMINALS; i++) free(sPaths[i]); free(sPaths); /* destroy the minimum spanning tree*/ list_destroy(&TD); /* destroy grid spanning tree*/ graph_destroy(&NTD); /* destroy the terminal list*/ for (i = 0; i < NO_TERMINALS; i++) { path_vertex_free(terminals[i]); } free(terminals); /*destroy the steiner tree*/ list_destroy(&T); return 0; }
int main(int argc, char **argv) { Graph graph; AdjList *adjlist; ListElmt *element; char *data, data1[STRSIZ], *data2; int retval, size, i; /***************************************************************************** * * * Initialize the graph. * * * *****************************************************************************/ graph_init(&graph, match_str, free); /***************************************************************************** * * * Perform some graph operations. * * * *****************************************************************************/ if ((data = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data, "a"); fprintf(stdout, "Inserting vertex %s\n", data); if (graph_ins_vertex(&graph, data) != 0) return 1; if ((data = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data, "b"); fprintf(stdout, "Inserting vertex %s\n", data); if (graph_ins_vertex(&graph, data) != 0) return 1; if ((data = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data, "c"); fprintf(stdout, "Inserting vertex %s\n", data); if (graph_ins_vertex(&graph, data) != 0) return 1; if ((data = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data, "d"); fprintf(stdout, "Inserting vertex %s\n", data); if (graph_ins_vertex(&graph, data) != 0) return 1; if ((data = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data, "e"); fprintf(stdout, "Inserting vertex %s\n", data); if (graph_ins_vertex(&graph, data) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "a"); strcpy(data2, "b"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "a"); strcpy(data2, "c"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "b"); strcpy(data2, "c"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "b"); strcpy(data2, "d"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "c"); strcpy(data2, "b"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "c"); strcpy(data2, "c"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "c"); strcpy(data2, "d"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "d"); strcpy(data2, "a"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "e"); strcpy(data2, "c"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "e"); strcpy(data2, "d"); fprintf(stdout, "Inserting edge %s to %s\n", data1, data2); if (graph_ins_edge(&graph, data1, data2) != 0) return 1; print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "a"); strcpy(data2, "c"); data = data2; fprintf(stdout, "Removing edge %s to %s\n", data1, data2); if (graph_rem_edge(&graph, data1, (void **)&data) != 0) return 1; free(data); print_graph(&graph); strcpy(data1, "c"); strcpy(data2, "c"); data = data2; fprintf(stdout, "Removing edge %s to %s\n", data1, data2); if (graph_rem_edge(&graph, data1, (void **)&data) != 0) return 1; free(data); print_graph(&graph); strcpy(data1, "e"); strcpy(data2, "c"); data = data2; fprintf(stdout, "Removing edge %s to %s\n", data1, data2); if (graph_rem_edge(&graph, data1, (void **)&data) != 0) return 1; free(data); print_graph(&graph); strcpy(data1, "a"); strcpy(data2, "b"); data = data2; fprintf(stdout, "Removing edge %s to %s\n", data1, data2); if (graph_rem_edge(&graph, data1, (void **)&data) != 0) return 1; free(data); print_graph(&graph); strcpy(data1, "d"); strcpy(data2, "a"); data = data2; fprintf(stdout, "Removing edge %s to %s\n", data1, data2); if (graph_rem_edge(&graph, data1, (void **)&data) != 0) return 1; free(data); print_graph(&graph); free(data2); strcpy(data1, "a"); data = data1; fprintf(stdout, "Removing vertex %s\n", data1); if (graph_rem_vertex(&graph, (void **)&data) != 0) return 1; free(data); print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "f"); strcpy(data2, "a"); retval = graph_ins_edge(&graph, data1, data2); fprintf(stdout,"Inserting an invalid edge from %s to %s...Value=%d (-1=OK)\n", data1, data2, retval); if (retval != 0) free(data2); print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "c"); strcpy(data2, "b"); retval = graph_ins_edge(&graph, data1, data2); fprintf(stdout,"Inserting an existing edge from %s to %s...Value=%d (1=OK)\n", data1, data2, retval); if (retval != 0) free(data2); print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "f"); strcpy(data2, "a"); data = data2; retval = graph_rem_edge(&graph, data1, (void **)&data); fprintf(stdout, "Removing an invalid edge from %s to %s...Value=%d (-1=OK)\n", data1, data2, retval); if (retval == 0) free(data); free(data2); print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "c"); strcpy(data2, "e"); data = data2; retval = graph_rem_edge(&graph, data1, (void **)&data); fprintf(stdout, "Removing an invalid edge from %s to %s...Value=%d (-1=OK)\n", data1, data2, retval); if (retval == 0) free(data); free(data2); print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data2, "c"); retval = graph_ins_vertex(&graph, data2); fprintf(stdout, "Inserting an existing vertex %s...Value=%d (1=OK)\n", data1, retval); if (retval != 0) free(data2); print_graph(&graph); if ((data2 = (char *)malloc(STRSIZ)) == NULL) return 1; strcpy(data1, "b"); strcpy(data2, "d"); retval = graph_is_adjacent(&graph, data1, data2); fprintf(stdout, "Testing graph_is_adjacent (%s, %s)...Value=%d (1=OK)\n", data1, data2, retval); strcpy(data1, "a"); strcpy(data2, "e"); retval = graph_is_adjacent(&graph, data1, data2); fprintf(stdout, "Testing graph_is_adjacent (%s, %s)...Value=%d (0=OK)\n", data1, data2, retval); strcpy(data1, "e"); strcpy(data2, "d"); retval = graph_is_adjacent(&graph, data1, data2); fprintf(stdout, "Testing graph_is_adjacent (%s, %s)...Value=%d (1=OK)\n", data1, data2, retval); strcpy(data1, "c"); strcpy(data2, "a"); retval = graph_is_adjacent(&graph, data1, data2); fprintf(stdout, "Testing graph_is_adjacent (%s, %s)...Value=%d (0=OK)\n", data1, data2, retval); free(data2); strcpy(data1, "c"); if (graph_adjlist(&graph, data1, &adjlist) != 0) return 1; fprintf(stdout, "Vertices adjacent to %s: ", data1); i = 0; size = set_size(&adjlist->adjacent); element = list_head(&adjlist->adjacent); while (i < size) { i++; if (i > 1) fprintf(stdout, ", "); fprintf(stdout, "%s", (char *)list_data(element)); element = list_next(element); } fprintf(stdout, "\n"); /***************************************************************************** * * * Destroy the graph. * * * *****************************************************************************/ fprintf(stdout, "Destroying the graph\n"); graph_destroy(&graph); return 0; }
/*-------------------------------------------------------------*/ int gen_gridgraph(Graph *grid_graph, int GRID_WIDTH, int GRID_HEIGHT) { PathVertex *path_vertex, *path_start, *path_vertex1, *path_vertex2; CoordData *coord; int i,j; int index; printf("Creating Grid Graph\n"); /* initialize a grid graph */ graph_init(grid_graph, match_coord, (void*)path_vertex_free); printf("\tInitialized grid graph..\n"); /* insert vertices into grid graph */ printf("\tInserting verticies"); for (i = 0; i < GRID_WIDTH; i++) { printf("."); fflush(stdout); for (j = 0; j < GRID_HEIGHT; j++) { /* allocate a vertex */ if ((path_vertex = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("\t\tError allocating (%d,%d) PathVertex\nTerminating...\n",i,j); fflush(stdout); exit(1); } /* allocate a coordinate */ if ((coord = (CoordData*) malloc(sizeof(CoordData))) == NULL) { printf("\t\tError allocating (%d,%d) CoordData\nTerminating...\n",i,j); fflush(stdout); exit(1); } /* set values to coord */ coord->x = i; coord->y = j; coord->z = 0; /* insert coord as data to path vertex */ path_vertex->data = coord; if ((i == 1)&&(j==2)) path_start = path_vertex; /*insert it into the graph */ if (graph_ins_vertex(grid_graph, path_vertex) != 0) { printf("\t\tError inserting vertex (%d,%d)\nTerminating...\n",i,j); return 1; } } } /*done inserting vertices*/ printf("Finished\n"); /* for each vertex we check if there is a vertex to the left, right, above and below. In this way, it only consumes O(n) time where n is the number of vertices */ /* insert edges into grid graph */ printf("\tInserting edges"); index = 1; for (i = 0; i < GRID_WIDTH; i++) { printf("."); fflush(stdout); for (j = 0; j < GRID_HEIGHT; j++) { /* check to the left */ if (i - 1 >= 0) { CoordData *u,*v; /* allocate the vertices (for in the edges)*/ u = (CoordData*)malloc(sizeof(CoordData)); v = (CoordData*)malloc(sizeof(CoordData)); if (u == NULL) { printf("gsFH.h : u mem allocation error\n"); fflush(stdout); exit(1); } if (v == NULL) { printf("gsFH.h : v mem allocation error\n"); fflush(stdout); exit(1); } /* set vertex data */ u->x = i; u->y = j; u->z = 0; v->x = i-1; v->y = j; v->z = 0; if ((path_vertex1 = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("gsFH.h : path_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((path_vertex2 = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("gsFH.h : path_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } path_vertex1->data = u; path_vertex2->data = v; path_vertex2->weight = 1; if (graph_ins_edge(grid_graph, path_vertex1, path_vertex2) != 0) return 1; free(path_vertex1->data); free(path_vertex1); } /* check to the right */ if (i + 1 < GRID_WIDTH) { CoordData *u,*v; /* allocate the vertices (for in the edges)*/ u = (CoordData*)malloc(sizeof(CoordData)); v = (CoordData*)malloc(sizeof(CoordData)); if (u == NULL) { printf("gsFH.h : u mem allocation error\n"); fflush(stdout); exit(1); } if (v == NULL) { printf("gsFH.h : v mem allocation error\n"); fflush(stdout); exit(1); } /* set vertex data */ u->x = i; u->y = j; u->z = 0; v->x = i+1; v->y = j; v->z = 0; if ((path_vertex1 = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("gsFH.h : path_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((path_vertex2 = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("gsFH.h : path_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } path_vertex1->data = u; path_vertex2->data = v; path_vertex2->weight = 1; if (graph_ins_edge(grid_graph, path_vertex1, path_vertex2) != 0) return 1; free(path_vertex1->data); free(path_vertex1); } /* check up */ if (j - 1 >= 0) { CoordData *u,*v; /* allocate the vertices (for in the edges)*/ u = (CoordData*)malloc(sizeof(CoordData)); v = (CoordData*)malloc(sizeof(CoordData)); if (u == NULL) { printf("gsFH.h : u mem allocation error\n"); fflush(stdout); exit(1); } if (v == NULL) { printf("gsFH.h : v mem allocation error\n"); fflush(stdout); exit(1); } /* set vertex data */ u->x = i; u->y = j; u->z = 0; v->x = i; v->y = j-1; v->z = 0; if ((path_vertex1 = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("gsFH.h : path_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((path_vertex2 = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("gsFH.h : path_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } path_vertex1->data = u; path_vertex2->data = v; path_vertex2->weight = 1; if (graph_ins_edge(grid_graph, path_vertex1, path_vertex2) != 0) return 1; free(path_vertex1->data); free(path_vertex1); } /* check down */ if (j + 1 < GRID_HEIGHT) { CoordData *u,*v; /* allocate the vertices (for in the edges)*/ u = (CoordData*)malloc(sizeof(CoordData)); v = (CoordData*)malloc(sizeof(CoordData)); if (u == NULL) { printf("gsFH.h : u mem allocation error\n"); fflush(stdout); exit(1); } if (v == NULL) { printf("gsFH.h : v mem allocation error\n"); fflush(stdout); exit(1); } /* set vertex data */ u->x = i; u->y = j; u->z = 0; v->x = i; v->y = j+1; v->z = 0; if ((path_vertex1 = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("gsFH.h : path_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } if ((path_vertex2 = (PathVertex*) malloc(sizeof(PathVertex))) == NULL) { printf("gsFH.h : path_vertex1 mem allocation error\n"); fflush(stdout); exit(1); } path_vertex1->data = u; path_vertex2->data = v; path_vertex2->weight = 1; if (graph_ins_edge(grid_graph, path_vertex1, path_vertex2) != 0) return 1; free(path_vertex1->data); free(path_vertex1); } } }/* finished inserting edges */ printf("Finished\n"); return 0; }
/*-------------------------------------------------------------*/ void grid2VL(Graph *G, Graph *H, int width, int height) { ListElmt *elmt; int index,via; printf("Creating Virtual Layer Graph\n"); graph_init(H, match_coord, (void*)path_vertex_free); // original edges enumrated from 1, vias enumerated after original edges. // also, since our graph is undirected, we have to half edges for each edge in undirected graph, // thus we start vias from ecount/2 index = 1; via = (G->ecount / 2) + 1; // for each vertex in G, there will be two vertices in H. (One per layer) printf("\tInserting vertices and vias into multi-layer graph...."); fflush(stdout); for (elmt = list_head(&G->adjlists); elmt != NULL; elmt = list_next(elmt)) { PathVertex *v0,*v1,*v; // v = vertex from g, v1,v2 = new vertices to insert in H CoordData *v0c,*v1c; v = ((AdjList*)list_data(elmt))->vertex; // insert both verticies v0 = (PathVertex*) malloc(sizeof(PathVertex)); v0c = (CoordData*) malloc(sizeof(CoordData)); v1 = (PathVertex*) malloc(sizeof(PathVertex)); v1c = (CoordData*) malloc(sizeof(CoordData)); if ( (v0 == NULL)||(v0c == NULL)||(v1 == NULL)||v1c == NULL) { printf("gsFH.h : vertex mem allocation error (grid2VL)\n"); fflush(stdout); exit(1); } v0->data = v0c; v1->data = v1c; // horizontal vertex v0c->x = ((CoordData*)((PathVertex*)v)->data)->x; v0c->y = ((CoordData*)((PathVertex*)v)->data)->y; v0c->z = 0; // vertical vertex v1c->x = ((CoordData*)((PathVertex*)v)->data)->x; v1c->y = ((CoordData*)((PathVertex*)v)->data)->y; v1c->z = 1; graph_ins_vertex(H,v0); graph_ins_vertex(H,v1); // now we insert the via between v0 and v1 v0 = (PathVertex*) malloc(sizeof(PathVertex)); v0c = (CoordData*) malloc(sizeof(CoordData)); v1 = (PathVertex*) malloc(sizeof(PathVertex)); v1c = (CoordData*) malloc(sizeof(CoordData)); if ( (v0 == NULL)||(v0c == NULL)||(v1 == NULL)||v1c == NULL) { printf("gsFH.h : vertex mem allocation error (grid2VL)\n"); fflush(stdout); exit(1); } v0->data = v0c; v1->data = v1c; // set the weights to 1, temporarily v1->weight = 1; // set via index v1->index = via; // horizontal vertex v0c->x = ((CoordData*)((PathVertex*)v)->data)->x; v0c->y = ((CoordData*)((PathVertex*)v)->data)->y; v0c->z = 0; // vertical vertex v1c->x = ((CoordData*)((PathVertex*)v)->data)->x; v1c->y = ((CoordData*)((PathVertex*)v)->data)->y; v1c->z = 1; // forward edge graph_ins_edge(H,v0,v1); free(v0c); free(v0); v0 = (PathVertex*) malloc(sizeof(PathVertex)); v0c = (CoordData*) malloc(sizeof(CoordData)); v1 = (PathVertex*) malloc(sizeof(PathVertex)); v1c = (CoordData*) malloc(sizeof(CoordData)); if ( (v0 == NULL)||(v0c == NULL)||(v1 == NULL)||v1c == NULL) { printf("gsFH.h : vertex mem allocation error (grid2VL)\n"); fflush(stdout); exit(1); } v0->data = v0c; v1->data = v1c; // set the weights to 1, temporarily v0->weight = 1; // via index v0->index = via; // horizontal vertex v0c->x = ((CoordData*)((PathVertex*)v)->data)->x; v0c->y = ((CoordData*)((PathVertex*)v)->data)->y; v0c->z = 0; // vertical vertex v1c->x = ((CoordData*)((PathVertex*)v)->data)->x; v1c->y = ((CoordData*)((PathVertex*)v)->data)->y; v1c->z = 1; // forward edge graph_ins_edge(H,v1,v0); free(v1c); free(v1); // next via via++; } printf("Finished\n"); fflush(stdout); printf("\tInserting edges into multi-layer graph.."); fflush(stdout); // now we insert edges into the multi layer graph for (elmt = list_head(&G->adjlists); elmt != NULL; elmt = list_next(elmt)) { PathVertex *v0,*v1,*v,*next; // v = vertex from g, v1,v2 = new vertices to insert in H CoordData *v0c,*v1c; ListElmt *e; int vx,vy,vz; //printf("."); //fflush(stdout); v = ((AdjList*)list_data(elmt))->vertex; vx = ((CoordData*)((PathVertex*)v)->data)->x; vy = ((CoordData*)((PathVertex*)v)->data)->y; vz = ((CoordData*)((PathVertex*)v)->data)->z; // go through each vertex adjacent to v for (e = list_head(&((AdjList*)list_data(elmt))->adjacent); e != NULL; e = list_next(e)) { int nx, ny, nz; double weight; int layer; int exists; next = list_data(e); nx = ((CoordData*)((PathVertex*)next)->data)->x; ny = ((CoordData*)((PathVertex*)next)->data)->y; nz = ((CoordData*)((PathVertex*)next)->data)->z; weight = (double)((PathVertex*)next)->weight; // find out if it's a horizontal or vertical edge if (vx == nx) layer = 1; else if (vy == ny) layer = 0; else assert(0); // insert forward edge from v0 to v1 v0 = (PathVertex*) malloc(sizeof(PathVertex)); v1 = (PathVertex*) malloc(sizeof(PathVertex)); v0c = (CoordData*) malloc(sizeof(CoordData)); v1c = (CoordData*) malloc(sizeof(CoordData)); if ( (v0 == NULL)||(v0c == NULL)||(v1 == NULL)||v1c == NULL) { printf("gsFH.h : vertex mem allocation error (grid2VL)\n"); fflush(stdout); exit(1); } v0c->x = vx; v0c->y = vy; v0c->z = layer; v1c->x = nx; v1c->y = ny; v1c->z = layer; v0->data = v0c; v1->data = v1c; v1->weight = weight; v1->index = index; graph_ins_edge(H,v0,v1); // free the lookup variable free(v0c); free(v0); // insert the backedge v1 to v0 v0 = (PathVertex*) malloc(sizeof(PathVertex)); v1 = (PathVertex*) malloc(sizeof(PathVertex)); v0c = (CoordData*) malloc(sizeof(CoordData)); v1c = (CoordData*) malloc(sizeof(CoordData)); if ( (v0 == NULL)||(v0c == NULL)||(v1 == NULL)||v1c == NULL) { printf("gsFH.h : vertex mem allocation error (grid2VL)\n"); fflush(stdout); exit(1); } v0c->x = vx; v0c->y = vy; v0c->z = layer; v1c->x = nx; v1c->y = ny; v1c->z = layer; v0->data = v0c; v1->data = v1c; v0->weight = weight; v0->index = index; exists = graph_ins_edge(H,v1,v0); if (!exists) { ((PathVertex*)next)->index = index; // set index in orginal graph G index++; } // free the lookup variable free(v1c); free(v1); } } printf("finished\n"); fflush(stdout); }