Пример #1
0
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;
}
Пример #2
0
	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);
}
Пример #3
0
	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);
}
Пример #4
0
	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);
}
Пример #5
0
	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);
}
Пример #6
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;
}
Пример #7
0
	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);
}
Пример #8
0
	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));
}