Пример #1
0
Graph *
geo_hier(long seed,
	int nlevels,	/* number of levels (=size of following array) */
	int edgemeth,	/* method of attaching edges */
	int aux,	/* auxiliary parameter for edge method (threshold) */
	geo_parms *pp)	/* array of parameter structures, one per level */
{
Graph *newG, *tG, *GG, *srcG, *dstG;
long *numv;		/* array of sizes of lower-level graphs */
geo_parms *curparms, workparms[MAXLEVEL];
register i,k,indx;
long dst;
int temp,total,lowsize,otherend,blen,level;
long maxP[MAXLEVEL], maxDiam[MAXLEVEL], wt[MAXLEVEL];
Vertex *np,*vp,*up,*base;
Arc *ap;
char vnamestr[MAXNAMELEN];


     if (seed)		/* convention: zero seed means don't use */
	gb_init_rand(seed);

     if (nlevels < 1 || nlevels > MAXLEVEL) {
	gb_trouble_code = bad_specs+HIER_TRBL;
	return NULL;
     }

     /* 1 <= nlevels <= MAXLEVEL */

     /* copy the parameters so we can modify them, and caller doesn't
      * see the changes.
      */
     for (level=0; level<nlevels; level++)
	bcopy((char *)&pp[level],&workparms[level],sizeof(geo_parms));

     level = 0;

     gb_trouble_code = 0;
     
     tG = NULL;
     do {
	gb_recycle(tG);
        tG = geo(0L,workparms);
     } while (tG != NULL && !isconnected(tG));

     if (tG==NULL)
	return tG;

     maxDiam[0] = fdiam(tG);
     maxP[0] = maxDiam[0];
     wt[0] = 1;

     for (i=1; i<nlevels; i++)
       maxDiam[i] = -1;

     curparms = workparms;

     while (++level < nlevels) {
       long tdiam;

	curparms++;	/* parameters for graphs @ next level */

        /* spread out the numbers of nodes per graph at this level */
	numv = (long *) calloc(tG->n,sizeof(long));
	lowsize = curparms->n;
        randomize(numv,tG->n,curparms->n,3*tG->n);

	/* create a subordinate graph for each vertex in the "top" graph,
         * and add it into the new graph as a whole.
	 * We construct the subgraphs all at once to ensure that each
	 * has a unique address.
	 */
	for (i=0,vp=tG->vertices; i<tG->n; i++,vp++) {
	    curparms->n = numv[i];
	    do {
		newG = geo(0L,curparms);
		if (newG==NULL) return NULL;
	    } while (!isconnected(newG));
	    vp->sub = newG;
	    tdiam = fdiam(newG);
	    if (tdiam>maxDiam[level])
	      maxDiam[level] = tdiam;
	}

	/* do some calculations before "flattening" the top Graph */

	total = 0;

	for (i=0; i<tG->n; i++) {	/* translate node numbers */
	    temp = numv[i];		
	    numv[i]= total;
	    total += temp;
	}

	if (total != tG->n*lowsize) {
	    fprintf(stderr,"bad size of new graph!\n");
	    fprintf(stderr,"total %d tG->n %ld lowsize %d\n",total,tG->n,lowsize);
	    gb_trouble_code = impossible+HIER_TRBL;
	    return NULL;
	}

	/* now create what will become the "new" top-level graph */
	newG = gb_new_graph(total);
	if (newG==NULL) {
	    gb_trouble_code += HIER_TRBL;
	    return NULL;
	}

	/* resolution of the new graph */
	newG->Gscale = tG->Gscale * curparms->scale;

       /* compute edge weights for this level */

       wt[level] = maxP[level-1] + 1;
       maxP[level] = (maxDiam[level]*wt[level])
	 + (maxDiam[level-1]*maxP[level-1]);

       for (i=0,vp=tG->vertices; i<tG->n; i++,vp++) {
	 strcpy(vnamestr,vp->name);	/* base name for all "offspring" */
	 blen = strlen(vnamestr);
	 vnamestr[blen] = '.';
	    
	 GG = tG->vertices[i].sub;
	 base = newG->vertices + numv[i];	/* start of this node's */
	 for (k=0,np=base,up=GG->vertices; k<GG->n; k++,np++,up++) {

	   /* add the node's edges */
	   for (ap=up->arcs; ap; ap=ap->next)  {
	     otherend = ap->tip - GG->vertices;
	     if (k < otherend)
	       gb_new_edge(np,base+otherend,ap->len);
	     
	   }

	   /* now set the new node's position */
	   np->xpos = tG->vertices[i].xpos * curparms->scale + up->xpos;
	   np->ypos = tG->vertices[i].ypos * curparms->scale + up->ypos;

	   /* give the "new" node a name by catenating top & bot names */
	   strcpy(vnamestr+blen+1,up->name);
	   np->name = gb_save_string(vnamestr);

	 } /* loop over GG's vertices */
       }  /* loop over top-level vertices */

       /*
	* Now we have to transfer the top-level edges to new graph.
	* This is done by one of three methods:
	*    0: choose a random node in each subgraph
	*    1: attach to the smallest-degree non-leaf node in each
	*    2: attach to smallest-degree node
	*    3: attach to first node with degree less than aux
	*/
       for (i=0; i<tG->n; i++) {
	 Vertex *srcp, *dstp;
	 Graph *srcG, *dstG;

	 srcG = tG->vertices[i].sub;

	 if (srcG == NULL) {	/* paranoia */
	   gb_trouble_code = impossible+HIER_TRBL+1;
	   return NULL;
	 }

	 for (ap=tG->vertices[i].arcs; ap; ap=ap->next) {

	   dst = ap->tip - tG->vertices;

	   if (i > dst)	/* consider each edge only ONCE */
	     continue;

	   dstG = ap->tip->sub;

	   if (dstG == NULL) {	/* paranoia */
	     gb_trouble_code = impossible+HIER_TRBL+1;
	     return NULL;
	   }

	   /* choose endpoints of the top-level edge */

	   switch (edgemeth) {
	   case 0:	/* choose random node in each */
	     srcp = srcG->vertices + gb_next_rand()%srcG->n;
	     dstp = dstG->vertices + gb_next_rand()%dstG->n;
	     break;

	   case 1:	/* find nonleaf node of least degree in each */
	     /* This causes problems with graph size < 3 */
	     if (srcG->n > 2)
	       srcp = find_small_deg(srcG,NOLEAF);
	     else
	       srcp = find_small_deg(srcG,LEAFOK);
	     if (dstG->n > 2)
	       dstp = find_small_deg(dstG,NOLEAF);
	     else
	       dstp = find_small_deg(dstG,LEAFOK);
	     break;

	   case 2: /* find node of smallest degree */
	     srcp = find_small_deg(srcG,LEAFOK);
	     dstp = find_small_deg(dstG,LEAFOK);
	     break;

	   case 3: /* first node w/degree < aux */
	     srcp = find_thresh_deg(srcG,aux);
	     dstp = find_thresh_deg(dstG,aux);
	   default:
	     gb_trouble_code = bad_specs+HIER_TRBL;
	     return NULL;

	   }	/* switch on edgemeth */

	   /* pointer arithmetic: isn't it fun?
	      printf("Copying edge from %d to %d\n",
	      numv[i]+(srcp - srcG->vertices),
	      numv[dst] + (dstp - dstG->vertices));
	      */
	   if (srcp==NULL || dstp==NULL) {
	     gb_trouble_code = impossible + HIER_TRBL+2;
	     return NULL;
	   }
		
	   srcp = newG->vertices + numv[i] + (srcp - srcG->vertices);
	   dstp = newG->vertices + numv[dst] + (dstp - dstG->vertices);

	   gb_new_edge(srcp,dstp,idist(srcp,dstp));

	 } /* for each arc */
       } /* for each vertex of top graph */

        /* now make the "new" graph the "top" graph and recycle others */
       for (i=0,vp=tG->vertices; i<tG->n; i++,vp++)
	 gb_recycle(vp->sub);

       gb_recycle(tG);

       tG = newG;

       free(numv);
     }	/* while more levels */

/* Finally, go back and add the policy weights,
 * based upon the computed max diameters
 * and Max Path lengths.
 */
   for (i=0; i<tG->n; i++)
     for (ap=tG->vertices[i].arcs; ap; ap=ap->next) {
       dst = ap->tip - tG->vertices;
       if (i > dst)	/* consider each edge only ONCE */
	 continue;

       assert(i != dst); /* no self loops */

       /* i < dst: it is safe to refer to ap's mate by ap+1.  */
       level = edge_level(&tG->vertices[i],&tG->vertices[dst],nlevels);
       ap->policywt = (ap+1)->policywt = wt[level];

     }

/* construct the utility and id strings for the new graph.
 * Space constraints will restrict us to keeping about 4 levels'
 * worth of info.
 */
  {
    char buf[ID_FIELD_SIZE+1];
    register char *cp;
    int len, nextlen, left;

    strcpy(tG->util_types,GEO_UTIL);	/* same for all geo graphs,	*/
					/* defined in geo.h		*/
    cp = tG->id;
    sprintf(cp,"geo_hier(%ld,%d,%d,%d,[",seed,nlevels,edgemeth,aux);
    len = strlen(cp);
    left = ID_FIELD_SIZE - len;
    cp += len;
    
    for (i=0; (i < nlevels) && (left > 0); i++) {
      nextlen = printparms(buf,&pp[i]);
      strncpy(cp,buf,left);
      left -= nextlen;
      cp += nextlen;
    }
    if (left > 0) {
      sprintf(buf,"])");
      nextlen = strlen(buf);
      strncpy(cp,buf,left);
    }
  }

  return tG;
}	/* geo_hier() */
Пример #2
0
int main()
{
/*36:*/
#line 716 "./gb_graph.w"

g= gb_new_graph(2L);
if(g==NULL){
fprintf(stderr,"Oops, I couldn't even create a trivial graph!\n");
return-4;
}
u= g->vertices;v= u+1;
u->name= gb_save_string("vertex 0");
v->name= gb_save_string("vertex 1");

/*:36*/
#line 30 "./gb_graph.w"
;
/*18:*/
#line 327 "./gb_graph.w"

if(gb_alloc(0L,s)!=NULL||gb_trouble_code!=2){
fprintf(stderr,"Allocation error 2 wasn't reported properly!\n");return-2;
}
for(;g->vv.I<100;g->vv.I++)if(gb_alloc(100000L,s)){
g->uu.I++;
printf(".");
fflush(stdout);
}
if(g->uu.I<100&&gb_trouble_code!=3){
fprintf(stderr,"Allocation error 1 wasn't reported properly!\n");return-1;
}
if(g->uu.I==0){
fprintf(stderr,"I couldn't allocate any memory!\n");return-3;
}
gb_free(s);
printf("Hey, I allocated %ld00000 bytes successfully. Terrific...\n",g->uu.I);

gb_trouble_code= 0;

/*:18*/
#line 31 "./gb_graph.w"
;
/*38:*/
#line 735 "./gb_graph.w"

if(strncmp(u->name,v->name,7)){
fprintf(stderr,"Something is fouled up in the string storage machinery!\n");
return-5;
}
gb_new_edge(v,u,-1L);
gb_new_edge(u,u,1L);
gb_new_arc(v,u,-1L);
if((edge_trick&(siz_t)(u->arcs))||
(edge_trick&(siz_t)(u->arcs->next->next))||
!(edge_trick&(siz_t)(v->arcs->next)))
printf("Warning: The \"edge trick\" failed!\n");
if(v->name[7]+g->n!=v->arcs->next->tip->name[7]+g->m-2){

fprintf(stderr,"Sorry, the graph data structures aren't working yet.\n");
return-6;
}

/*:38*/
#line 32 "./gb_graph.w"
;
printf("OK, the gb_graph routines seem to work!\n");
return 0;
}
Пример #3
0
Graph * 
geo(long seed, geo_parms *pp)
{
double p,d,L,radius,r;
u_char *occ;
register int scale;
unsigned nbytes, index, x, y;
u_long units,pertrange;
int mallocd;
register i,j;
Graph *G;
Vertex *up,*vp;
char namestr[128];

    gb_trouble_code = 0;

    if (seed)			/* zero seed means "already init'd */
	gb_init_rand(seed);

    scale = pp->scale;

    L = sqrt(2.0) * scale;

    gb_trouble_code = 0;
    if ((pp->alpha <= 0.0) || (pp->alpha > 1.0)) gb_trouble_code=bad_specs+1;
    if (pp->gamma < 0.0) 		gb_trouble_code=bad_specs+GEO_TRBL;
    if (pp->beta < 0.0)			gb_trouble_code=bad_specs+GEO_TRBL;
    if (pp->n > (scale * scale))	gb_trouble_code=bad_specs+GEO_TRBL;
    if (gb_trouble_code)
	return NULL;

    radius = pp->gamma * L;	/* comes in as a fraction of diagonal */

#define posn(x,y)	((x)*scale)+(y)
#define bitset(v,i)	(v[(i)/NBBY]&(1<<((i)%NBBY)))
#define setbit(v,i)	v[(i)/NBBY] |= (1<<((i)%NBBY))

/* create a new graph structure */
   
    if ((G=gb_new_graph(pp->n)) == NULL)
	return NULL;

    nbytes = ((scale*scale)%NBBY ? (scale*scale/NBBY)+1 : (scale*scale)/NBBY);

    if (nbytes < STACKMAX) {	/* small amount - just do it in the stack */
        occ = (u_char *) alloca(nbytes);
        mallocd = 0;
    } else {
        occ = (u_char *) malloc(nbytes);
        mallocd = 1;
    }

    for (i=0; i<nbytes; i++) occ[i] = 0;


/* place each of n points in the plane */

    for (i=0,vp = G->vertices; i<pp->n; i++,vp++) {
	sprintf(namestr,"%d",i);	/* name is just node number */
	vp->name = gb_save_string(namestr);
        do {
            vp->xpos = gb_next_rand()%scale;         /* position: 0..scale-1 */
            vp->ypos = gb_next_rand()%scale;         /* position: 0..scale-1 */
	    index = posn(vp->xpos,vp->ypos);
        } while (bitset(occ,index));
        setbit(occ,index);
    }

/* Now go back and add the edges */
	
    for (i=0,up = G->vertices; i<(pp->n)-1; i++,up++)
	for (j=i+1, vp = &G->vertices[i+1]; j<pp->n; j++,vp++) { 
	    d = distance(up,vp);
            switch (pp->method) {
	    case RG2:		/* Waxman's */
		d = randfrac()*L;
		/* fall through */
            case RG1:		/* Waxman's */
		p = pp->alpha * exp(-d/(L*pp->beta));
		break;
	    case RANDOM:	/* the classic */
		p = pp->alpha;
		break;
	    case EXP:	
		p = pp->alpha * exp(-d/(L-d));
		break;
            case DL:		/* Doar-Leslie */
		p = pp->alpha * (pp->gamma/pp->n) * exp(-d/(L*pp->beta));
		break;
	    case LOC:		/* Locality model, two probabilities */
		if (d <= radius) p = pp->alpha;
		else p = pp->beta;	
		break;
	    default:
		die("Bad edge method in geo()!");
	    }
	    if (randfrac() < p) 
		gb_new_edge(up,vp,(int)rint(d));
		
	}

/* Fill in the "id" string to say how the graph was created */

    G->Gscale = scale;
    sprintf(G->id,"geo(%ld,", seed);
    i = strlen(G->id);
    i += printparms(G->id+i,pp);
    G->id[i] = ')';
    G->id[i+1] = (char) 0;
    strcpy(G->util_types,GEO_UTIL);

/* clean up */
    if (mallocd) free(occ);

    return G;
}