static stop_t *make_stops (const float *tab, int n, const float *vals, int nval, int *nstop_out) { int i; stop_t *stops = NEWA (stop_t, nval + 1); for (i = 0; i < nval; i++) { stop_t *stop = stops + i; stop->val = vals[i]; stop->no = i; stop->n_gt = stop->n_eq = 0; } { /* lower sentinel to count values below the lowest val and NaNs */ stop_t *stop = stops + nval; stop->val = -1e30; /* -1.0/0.0 does not work ?? */ stop->no = -1; stop->n_gt = stop->n_eq = 0; } qsort (stops, nval + 1, sizeof (stop_t), &cmp_stops_for_increasing); for(i=1;i<nval+1;i++) assert(stops[i-1].val<=stops[i].val); assert (stops[0].no == -1 || !isfinite(stops[0].val)); /* handle duplicate vals */ int nstop = nval + 1; i = 1; while (i < nstop) { if (stops[i].val == stops[i - 1].val) { int copied_no = stops[i].no; /* shift array */ memmove (stops + i, stops + i + 1, (nstop - i - 1) * sizeof (stop_t)); nstop--; stops[nstop].no = copied_no; stops[nstop].copy_from_no = stops[i - 1].no; } else i++; } for (i = 0; i < n; i++) { float v = tab[i]; /* bisection, property: stops[t0].val <= v < stops[t1].val * NaNs will be counted in stops[0].n_gt */ int t0 = 0, t1 = nstop; while (t0 + 1 != t1) { int med = (t0 + t1) / 2; if (stops[med].val <= v) t0 = med; else t1 = med; } if (stops[t0].val < v) stops[t0].n_gt++; else /* NaN's and other weird values here... */ stops[t0].n_eq++; } *nstop_out = nstop; return stops; }
void plot_full_sets_grouped ( bitmap_t * fset_mask, /* IN - subset of full-sets to plot */ struct cinfo * cip, /* IN - compatibility info */ enum plot_size plot_size /* IN - size of plot to produce */ ) { int i; int j; int n; int nleft; int kmasks; int nmasks; int nplot; bitmap_t * left; bitmap_t * tmask; int * plist; struct full_set * fsp; struct pset * pts; char * cp1; char * cp2; char fsnums [110]; char fsnum [8]; char title [120]; n = cip -> num_edges; nmasks = cip -> num_edge_masks; kmasks = cip -> num_vert_masks; left = NEWA (nmasks, bitmap_t); tmask = NEWA (kmasks, bitmap_t); plist = NEWA (n, int); /* Make a local copy of all full sets left to plot. */ for (i = 0; i < nmasks; i++) { left [i] = fset_mask [i]; } nleft = n; while (nleft > 0) { begin_plot (plot_size); for (i = 0; i < kmasks; i++) { tmask [i] = 0; } nplot = 0; cp1 = &fsnums [sizeof (fsnums)]; *--cp1 = '\0'; for (i = n - 1; i >= 0; i--) { if (NOT BITON (left, i)) continue; /* Skip full set "i" if not disjoint */ /* with all others in this plot... */ fsp = cip -> full_trees [i]; pts = fsp -> terminals; for (j = 0; j < pts -> n; j++) { if (BITON (tmask, pts -> a [j].pnum)) break; } if (j < pts -> n) continue; (void) sprintf (fsnum, "%lu", (int32u) i); for (cp2 = fsnum; *cp2 NE '\0'; cp2++) { } /* Stop if label does not fit! */ if ((cp2 - fsnum) + 2 > (cp1 - fsnums)) break; while (cp2 > fsnum) { *--cp1 = *--cp2; } *--cp1 = ' '; *--cp1 = ','; plist [nplot++] = i; CLRBIT (left, i); --nleft; fsp = cip -> full_trees [i]; fst_comment (fsp); draw_fst (fsp, cip); pts = fsp -> terminals; for (j = 0; j < pts -> n; j++) { SETBIT (tmask, pts -> a [j].pnum); } } (void) printf ("\tPlot_Terminals\n"); (void) sprintf (title, "FST%s %s.", (nplot > 1) ? "s" : "", cp1 + 2); end_plot (title); } page_break (); free ((char *) plist); free ((char *) tmask); free ((char *) left); }
static void compute_grid_graph ( bitmap_t * tmap, /* IN - valid set of terminals */ bitmap_t * fset_mask, /* IN - valid FSTs */ struct cinfo * cip /* IN - compatibility info */ ) { int i; int j; int k; int nverts; int nverts2; int v1; int spi; int32u * gridp; coord_t coord; dist_t prev_coord; int prev_index; struct pset * tmp; char buf1 [128]; char buf2 [128]; nverts = cip -> num_verts; grid.nt = nverts; grid.ns = 0; grid.x_coord = NEWA (nverts, coord_t); grid.y_coord = NEWA (nverts, coord_t); grid.xindex = NEWA (nverts, int); grid.yindex = NEWA (nverts, int); /* Compute map giving index of each terminal in sequence when */ /* sorted by increasing X coordinate. */ tmp = NEW_PSET (nverts); tmp -> n = nverts; for (i = 0; i < nverts; i++) { tmp -> a [i] = cip -> pts -> a [i]; } sort_x_inc (tmp); prev_coord = INF_DISTANCE; prev_index = -1; for (i = 0; i < nverts; i++) { coord = tmp -> a [i].x; grid.x_coord [i] = coord; j = tmp -> a [i].pnum; if (coord NE prev_coord) { prev_index = i; } grid.xindex [j] = prev_index; prev_coord = coord; } /* Compute map giving index of each terminal in sequence when */ /* sorted by increasing Y coordinate. */ tmp -> n = nverts; for (i = 0; i < nverts; i++) { tmp -> a [i] = cip -> pts -> a [i]; } sort_y_inc (tmp); prev_coord = INF_DISTANCE; prev_index = -1; for (i = 0; i < nverts; i++) { coord = tmp -> a [i].y; grid.y_coord [i] = tmp -> a [i].y; j = tmp -> a [i].pnum; if (coord NE prev_coord) { prev_index = i; } grid.yindex [j] = prev_index; prev_coord = coord; } free ((char *) tmp); /* Allocate and zero matrix to hold the grid... */ nverts2 = (nverts + 1) * nverts; grid.gridp = NEWA (nverts2, int32u); for (i = 0; i < nverts2; i++) { grid.gridp [i] = 0; } grid.gridp += nverts; /* Set vertex number for each terminal in the grid... */ for (i = 0; i < nverts; i++) { if (NOT BITON (tmap, i)) { /* Should not have any duplicate terminals! */ fatal ("compute_grid_graph: Bug 1."); } j = grid.xindex [i]; k = grid.yindex [i]; grid.gridp [k * nverts + j] = i + 1; } draw_full_sets_on_grid (fset_mask, cip); identify_steiner_points (); /* Count every edge... */ count_edges = TRUE; number_of_edges = 0; gridp = grid.gridp; for (i = 0; i < nverts; i++) { for (j = 0; j < nverts; j++, gridp++) { v1 = (*gridp & GMASK); if (v1 EQ 0) continue; if ((*gridp & RIGHT_EDGE) NE 0) { edge_right (gridp, v1, i, j, 0, cip); } if ((*gridp & UP_EDGE) NE 0) { edge_up (gridp, v1, i, j, 0, cip); } if ((j > 0) AND ((gridp [-1] & RIGHT_EDGE) NE 0)) { edge_left (gridp, v1, i, j, 0, cip); } if ((i > 0) AND ((gridp [-nverts] & UP_EDGE) NE 0)) { edge_down (gridp, v1, i, j, 0, cip); } } } /* Output total number of vertices, plus number of terminals. */ if (Print_ORLibrary_Format) { printf ("%d %d\n", nverts + grid.ns, number_of_edges); } if (Print_SteinLib_Format) { printf ("33d32945 STP File, STP Format Version 1.00\n" "Section Comment\n" "Name \"%s\"\n" "Creator \"GeoSteiner\"\n" "Remark \"Reduced graph from FST generator\"\n" "End\n\n" "Section Graph\n" "Nodes %d\n" "Edges %d\n", cip -> description, nverts + grid.ns, number_of_edges); } /* Output every edge... */ count_edges = FALSE; gridp = grid.gridp; for (i = 0; i < nverts; i++) { for (j = 0; j < nverts; j++, gridp++) { v1 = (*gridp & GMASK); if (v1 EQ 0) continue; if ((*gridp & RIGHT_EDGE) NE 0) { edge_right (gridp, v1, i, j, 0, cip); } if ((*gridp & UP_EDGE) NE 0) { edge_up (gridp, v1, i, j, 0, cip); } if ((j > 0) AND ((gridp [-1] & RIGHT_EDGE) NE 0)) { edge_left (gridp, v1, i, j, 0, cip); } if ((i > 0) AND ((gridp [-nverts] & UP_EDGE) NE 0)) { edge_down (gridp, v1, i, j, 0, cip); } } } /* Write terminals (and coordinates in STP-format) */ if (Print_ORLibrary_Format) { printf ("%d\n", nverts); for (i = 0; i < nverts; i++) { printf ("%d\n", i+1); } } if (Print_SteinLib_Format) { printf ("End\n\n" "Section Terminals\n" "Terminals %d\n", nverts); for (i = 0; i < nverts; i++) { printf ("T %d\n", i+1); } printf ("End\n\n" "Section Coordinates\n"); /* Output coordinates of each terminal... */ for (i = 0; i < nverts; i++) { coord_to_string (buf1, cip -> pts -> a [i].x, &(cip -> scale)); coord_to_string (buf2, cip -> pts -> a [i].y, &(cip -> scale)); printf ("DD %d %s %s\n", i+1, buf1, buf2); } /* Output coordinates of each steiner point... */ spi = nverts+1; gridp = grid.gridp; for (i = 0; i < nverts; i++) { for (j = 0; j < nverts; j++, gridp++) { if ((*gridp & GMASK) > nverts) { coord_to_string (buf1, grid.x_coord [j], &(cip -> scale)); coord_to_string (buf2, grid.y_coord [i], &(cip -> scale)); printf ("DD %d %s %s\n", spi, buf1, buf2); spi++; } } } printf ("End\n\n" "EOF\n"); } free ((char *) (grid.gridp - nverts)); free ((char *) grid.yindex); free ((char *) grid.xindex); free ((char *) grid.y_coord); free ((char *) grid.x_coord); }
struct constraint * add_cutset_to_list ( bitmap_t * cutset, /* IN - new cutset to add */ struct constraint * cutlist, /* IN - list to add to */ double * x, /* IN - current LP solution */ bitmap_t * vert_mask, /* IN - set of valid terminals */ bitmap_t * edge_mask, /* IN - set of valid hyperedges */ struct cinfo * cip /* IN - compatibility info */ ) { int i; int j; int nedges; int nmasks; int num_in_cut; int count; int * vp1; int * vp2; struct constraint * p; struct constraint ** hookp; bitmap_t * cut_edges; double z; nedges = cip -> num_edges; nmasks = cip -> num_edge_masks; cut_edges = NEWA (nmasks, bitmap_t); memset (cut_edges, 0, nmasks * sizeof (*cut_edges)); count = 0; z = 0.0; for (i = 0; i < cip -> num_edges; i++) { if (NOT BITON (edge_mask, i)) continue; num_in_cut = 0; vp1 = cip -> edge [i]; vp2 = cip -> edge [i + 1]; while (vp1 < vp2) { j = *vp1++; if (BITON (cutset, j)) { ++num_in_cut; } } if (num_in_cut <= 0) { /* this hyperedge resides entirely */ /* outside of the cut... doesn't span! */ continue; } if (num_in_cut >= cip -> edge_size [i]) { /* this hyperedge resides entirely */ /* within the cut... doesn't span! */ continue; } SETBIT (cut_edges, i); ++count; z += x [i]; } /* Check for an all-zero cutset. These occasionally */ /* happen because of numeric issues... */ if (count <= 0) { /* Empty cutset! OOOPS! */ #if 1 tracef (" %% WARNING! empty cutset!\n"); #endif free ((char *) cut_edges); return (cutlist); } if (z >= 1.0 - FUZZ) { #if 1 tracef (" %% WARNING! bogus cutset!\n"); #endif free ((char *) cut_edges); return (cutlist); } /* If this new cutset is a superset of an existing one, */ /* then there is nothing to add, and nothing to delete. */ for (p = cutlist; p NE NULL; p = p -> next) { if (is_subset (p -> mask, cut_edges, nmasks)) { free (cut_edges); return (cutlist); } } /* Delete all current cutsets which have this new one */ /* as a subset. */ hookp = &cutlist; while ((p = *hookp) NE NULL) { if (p -> type NE CT_CUTSET) { hookp = &(p -> next); } else if (is_subset (cut_edges, p -> mask, nmasks)) { *hookp = p -> next; free ((char *) (p -> mask)); free ((char *) p); } else { hookp = &(p -> next); } } p = NEW (struct constraint); p -> next = NULL; p -> iteration = 0; p -> type = CT_CUTSET; p -> mask = cut_edges; *hookp = p; return (cutlist); }
int main ( int argc, char ** argv ) { int i; int nedges; int nmasks; int fpsave; bitmap_t * edge_mask; bitmap_t * all_fsets_mask; bitmap_t * no_fsets_mask; int count; char tbuf [20]; char title [128]; struct cinfo cinfo; fpsave = set_floating_point_double_precision (); setbuf (stdout, NULL); decode_params (argc, argv); init_tables (); read_phase_1_data (&cinfo); edge_mask = cinfo.initial_edge_mask; convert_cpu_time (cinfo.p1time, tbuf); printf (" %% Phase 1: %s seconds\n", tbuf); /* Prepare for plotting all terminals. */ define_Plot_Terminals (cinfo.pts, &cinfo.scale); nedges = cinfo.num_edges; nmasks = cinfo.num_edge_masks; all_fsets_mask = NEWA (nmasks, bitmap_t); no_fsets_mask = NEWA (nmasks, bitmap_t); for (i = 0; i < nmasks; i++) { all_fsets_mask [i] = 0; no_fsets_mask [i] = 0; } for (i = 0; i < nedges; i++) { SETBIT (all_fsets_mask, i); } if (Print_Points) { if ((cinfo.description NE NULL) AND (cinfo.description [0] NE '\0')) { strcpy (title, cinfo.description); } else { sprintf (title, "%lu points", (int32u) cinfo.num_verts); } overlay_plot_subset (title, no_fsets_mask, &cinfo, BIG_PLOT); } if (Print_Full_Sets) { plot_full_sets (all_fsets_mask, &cinfo, SMALL_PLOT); } if (Print_Grouped_Full_Sets) { plot_full_sets_grouped (all_fsets_mask, &cinfo, SMALL_PLOT); } if (Print_Overlaid_Full_Sets) { sprintf (title, "All FSTs: %lu points, %s seconds", (int32u) cinfo.num_verts, tbuf); overlay_plot_subset (title, edge_mask, &cinfo, BIG_PLOT); } restore_floating_point_precision (fpsave); exit (0); }
color_image_t * color_image_png_load( FILE* fp, const char* file_name ) { // read the header png_byte header[8]; fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "error: %s is not a PNG.\n", file_name); fclose(fp); return 0; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "error: png_create_read_struct returned 0.\n"); fclose(fp); return 0; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fp); return 0; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return 0; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // init png reading png_init_io(png_ptr, fp); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data; image_data = NEWA(png_byte, rowbytes * temp_height); assert(image_data!=NULL); // row_pointers is for pointing to image_data for reading the png with libpng png_bytep * row_pointers = NEWA(png_bytep, temp_height); assert(row_pointers!=NULL); // set the individual row_pointers to point at the correct offsets of image_data unsigned int i; for (i = 0; i <temp_height; i++) row_pointers[i] = image_data + i * rowbytes; // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); // copy into color image color_image_t* image = color_image_new(temp_width,temp_height); if( color_type==0 ) { assert((unsigned)rowbytes == temp_width || !"error: not a proper gray png image"); for(i=0; i<temp_width*temp_height; i++) image->c1[i] = image->c2[i] = image->c3[i] = image_data[i]; } else if( color_type == 2 ) { assert((unsigned)rowbytes == 3*temp_width || !"error: not a proper color png image"); for(i=0; i<temp_width*temp_height; i++) { image->c1[i] = image_data[3*i+0]; image->c2[i] = image_data[3*i+1]; image->c3[i] = image_data[3*i+2]; } } else assert(!"error: unknown PNG color type" ); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(row_pointers); return image; }
struct constraint * sec_flow_separator ( struct comp ** comp_hookp, /* IN/OUT - congested component(s) */ double * x, /* IN - the LP solution to separate */ bitmap_t * edge_mask, /* IN - subset of valid edges */ struct bbinfo * bbip, /* IN - branch-and-bound info */ struct constraint * cp /* IN - existing constraints */ ) { int i; int j; int t; int kmasks; struct comp * comp; struct cinfo * cip; int * ip1; int * ip2; double z; bitmap_t * S; bitmap_t * RS; cip = bbip -> cip; #if 0 plot_lp_solution ("LP solution to separate", x, cip, BIG_PLOT); #endif S = NEWA (2 * cip -> num_vert_masks, bitmap_t); RS = S + cip -> num_vert_masks; for (;;) { comp = *comp_hookp; if (comp EQ NULL) break; if (comp -> num_verts <= 0) { /* Free up this component... */ *comp_hookp = comp -> next; comp -> next = NULL; free_congested_component (comp); continue; } if (comp -> num_verts EQ 1) { /* Because of the total-degree constraint, this */ /* cannot happen unless something is very wrong! */ fatal ("sec_flow_separator: Bug 1."); } if (comp -> num_verts <= SEC_ENUM_LIMIT) { /* We have whittled this component down to */ /* something small. Use brute force on the */ /* rest... */ cp = enumerate_all_subtours (comp, cp, bbip); /* Free up this component... */ *comp_hookp = comp -> next; comp -> next = NULL; free_congested_component (comp); continue; } /* Find the LEAST congested vertex. this is the one */ /* we are going to try to force into the solution, */ /* since that is the one we would like to delete from */ /* the set afterward... */ t = find_least_congested_vertex (NULL, comp); #if 0 tracef (" %% -------------------------" "-------------------------\n" " %% separating comp with %d verts, %d edges," " forcing vertex %d\n" " %% -------------------------" "-------------------------\n", comp -> num_verts, comp -> num_edges, comp -> rverts [t] [0]); #endif /* Find worst SEC violation involving vertex t. */ z = do_flow_problem (comp, t, S); #if 0 #if 0 kmasks = cip -> num_vert_masks; for (i = 0; i < kmasks; i++) { RS [i] = 0; } for (i = 0; i < comp -> num_verts; i++) { if (NOT BITON (S, i)) continue; ip1 = comp -> rverts [i]; ip2 = comp -> rverts [i + 1]; while (ip1 < ip2) { j = *ip1++; SETBIT (RS, j); } } print_mask (" %% S =", RS, cip -> num_verts); #else print_mask (" %% S =", S, comp -> num_verts); #endif tracef (" %% f(S) = %-24.15g\n", z); #endif if (z < (1.0 - FUZZ)) { /* Add new violated constraint to the list... */ cp = check_component_subtour (S, comp, cp, x, edge_mask, bbip); } /* We have found the worst violation (if any) involving */ /* vertex t. We can now eliminate t from further */ /* consideration... */ *comp_hookp = delete_vertex_from_component (t, comp); } free ((char *) S); return (cp); }
static void build_SEC_flow_formulation ( struct comp * comp, /* IN - congested component */ int t, /* IN - vertex to force */ struct sec_flow_info * flowp /* OUT - SEC flow formulation */ ) { int i; int j; int k; int nverts; int nedges; int nmasks; int num_arcs; int num_nodes; int e; int arc_num; int num_used_edges; int first_edge_node; int * used_edges; bitmap_t * unused_edge_mask; struct flow_prob * prob; int * ip1; int * ip2; int * ep1; int * ep2; int * vp1; int * vp2; int * outlist; int * inlist; int * srcp; int * dstp; double * capp; int * counts; int ** ptrs; double sum; nverts = comp -> num_verts; nedges = comp -> num_edges; /* Compute a list of all component edges that */ /* DO NOT contain the vertex "t". */ nmasks = BMAP_ELTS (nedges); unused_edge_mask = NEWA (nmasks, bitmap_t); for (i = 0; i < nmasks; i++) { unused_edge_mask [i] = 0; } num_used_edges = nedges; ep1 = comp -> vedges [t]; ep2 = comp -> vedges [t + 1]; while (ep1 < ep2) { e = *ep1++; SETBIT (unused_edge_mask, e); --num_used_edges; } used_edges = NEWA (num_used_edges, int); ep1 = used_edges; for (i = 0; i < nedges; i++) { if (BITON (unused_edge_mask, i)) continue; *ep1++ = i; } free ((char *) unused_edge_mask); if (ep1 NE (used_edges + num_used_edges)) { /* lost count somewhere? */ fatal ("build_SEC_flow_formulation: Bug 1."); } /* Tally up the total number of nodes and arcs needed */ /* for the flow graph. For the sake of simplicity, we */ /* include a node for t, but there will be no arcs */ /* associated with it... */ /* One node per vertex. One source and one sink */ /* node. One node per USED edge. */ num_nodes = nverts + 2 + num_used_edges; /* One arc per vertex, one arc per USED edge, */ /* plus one arc for each vertex of every USED edge. */ num_arcs = nverts + num_used_edges; for (i = 0; i < num_used_edges; i++) { e = used_edges [i]; num_arcs += (comp -> everts [e + 1] - comp -> everts [e]); } /* Start filling in the flow problem instance... */ prob = &(flowp -> prob); prob -> num_nodes = num_nodes; prob -> num_arcs = num_arcs; /* Assign node numbers for the source and sink nodes... */ prob -> source = nverts; prob -> sink = nverts + 1; first_edge_node = nverts + 2; /* Now that we know how big the directed flow graph is, */ /* allocate storage for the various data structures... */ prob -> out = NEWA (num_nodes + 1, int *); prob -> in = NEWA (num_nodes + 1, int *); prob -> arc_src = NEWA (num_arcs, int); prob -> arc_dst = NEWA (num_arcs, int); prob -> capacity = NEWA (num_arcs, double); outlist = NEWA (num_arcs, int); inlist = NEWA (num_arcs, int); /* Generate the arcs from the source node to each USED edge. */ srcp = prob -> arc_src; dstp = prob -> arc_dst; capp = prob -> capacity; arc_num = 0; for (i = 0; i < num_used_edges; i++) { e = used_edges [i]; j = first_edge_node + i; *srcp++ = prob -> source; *dstp++ = j; *capp++ = comp -> x [e]; ++arc_num; /* Generate the arcs from each edge node to the */ /* corresponding vertex nodes. These all have weight */ /* 2, which is essentially infinite. */ vp1 = comp -> everts [e]; vp2 = comp -> everts [e + 1]; while (vp1 < vp2) { k = *vp1++; *srcp++ = j; *dstp++ = k; *capp++ = 2.0; ++arc_num; } } free ((char *) used_edges); /* Now generate one arc from each vertex node to the sink */ /* node. These all have weight (Bi - 1), where Bi is the */ /* congestion level of vertex i. */ for (i = 0; i < nverts; i++) { sum = -1.0; ep1 = comp -> vedges [i]; ep2 = comp -> vedges [i + 1]; while (ep1 < ep2) { e = *ep1++; sum += comp -> x [e]; } *srcp++ = i; *dstp++ = prob -> sink; *capp++ = sum; ++arc_num; } if (arc_num NE num_arcs) { fatal ("build_SEC_flow_formulation: Bug 2."); } /* We have now specified the directed flow graph as a */ /* list of directed arcs. Time to construct the */ /* adjacency lists -- for each node we build a list of */ /* outgoing and incoming arc numbers. Do the outgoing */ /* lists first... */ counts = NEWA (num_nodes, int); ptrs = NEWA (num_nodes, int *); for (i = 0; i < num_nodes; i++) { counts [i] = 0; } for (i = 0; i < num_arcs; i++) { ++(counts [prob -> arc_src [i]]); } ip1 = outlist; for (i = 0; i < num_nodes; i++) { ptrs [i] = ip1; prob -> out [i] = ip1; ip1 += counts [i]; } prob -> out [i] = ip1; for (i = 0; i < num_arcs; i++) { j = prob -> arc_src [i]; ip1 = ptrs [j]++; *ip1 = i; } /* Now do the incoming arc lists... */ for (i = 0; i < num_nodes; i++) { counts [i] = 0; } for (i = 0; i < num_arcs; i++) { ++(counts [prob -> arc_dst [i]]); } ip1 = inlist; for (i = 0; i < num_nodes; i++) { ptrs [i] = ip1; prob -> in [i] = ip1; ip1 += counts [i]; } prob -> in [i] = ip1; for (i = 0; i < num_arcs; i++) { k = prob -> arc_dst [i]; ip1 = ptrs [k]++; *ip1 = i; } /* Free temporary memory used to build things... */ free ((char *) counts); free ((char *) ptrs); /* Initialize the buffers used to hold flow solutions */ /* and temporary data... */ create_flow_solution_data (prob, &(flowp -> soln)); create_flow_temp_data (prob, &(flowp -> temp)); }