/*------------------------------------------------------------------------*/ VINDEX add_vertex(GRAPH* g, void *user) { VINDEX new_vertex; MEM_POOL *m = GRAPH_m(g); if (GRAPH_vfree(g) == -1) grow_vertex(g); new_vertex = GRAPH_vfree(g); /* get the free vertex */ /* set free vertex to next free vertex */ GRAPH_vfree(g) = VERTEX_from(&GRAPH_v_i(g,new_vertex)); /* no edges yet */ VERTEX_from(&GRAPH_v_i(g,new_vertex)) = INVALID_EINDEX; VERTEX_to(&GRAPH_v_i(g,new_vertex)) = INVALID_EINDEX; /* add user information */ VERTEX_user(&GRAPH_v_i(g,new_vertex)) = user; /* no from and to counts */ VERTEX_fcnt(&GRAPH_v_i(g,new_vertex)) = 0; VERTEX_tcnt(&GRAPH_v_i(g,new_vertex)) = 0; /* no level yet */ VERTEX_level(&GRAPH_v_i(g,new_vertex)) = -1; /* increment vertex count */ GRAPH_vcnt(g)++; return new_vertex; }
void grow_new_granule(int *c, int m, int min_bound, int max_bound, double (*cost_func)(int *)){ int i; int simplexen = 1; int granules = 1; // Start by growing a new simplex by allowing each vertex to move // outward from the center (the local minimum). A vertex continues // moving so long as it is moving uphill. For this new simplex, the // allowed vertex movements are arbitrary (but must be orthogonal). int *movemask = calloc(m,sizeof(*movemask)); int **new_c = malloc((m+1) * sizeof(*new_c)); int **secondary_c = malloc((m+1) * sizeof(*secondary_c)); for(i=0;i<(m+1);i++){ new_c[i] = malloc(m * sizeof(**new_c)); memcpy(new_c[i],c,sizeof(*c)*m); // set up orthogonal move mask for this vertex memset(movemask,0,sizeof(*movemask)*m); if(i>0)movemask[i-1]=-1; if(i<m)movemask[i]=1; // grow vertex to maximum grow_vertex(new_c[i], m, movemask, min_bound, max_bound, cost_func); } // this primary simplex almost certainly does not fill its // convergence zone; recursively spawn secondary simplexes with one // unconstrained vertex from the center of each face of this // simplex. The new vertex must grow outward (reflect the simplex // through each face). secondary_c[0] = malloc(m * sizeof(**new_c)); for(i=0;i<(m+1);i++){ // build a new d-1-tope 'plane'; all the points in the current // simplex minus the i'th one. // fill in the fixed verticies [1 through m] for(j=1;j<m;j++) if(j<=i) secondary_c[j] = new_c[j-1]; else secondary_c[j] = new_c[j]; // first vertex is the unconstrained one center_of_tope(secondary_c[0], secondary_c+1, m); // set movemask; must be strictly away from local minimum movemask_away(c, movemask, m); // grow granule grow_secondary_granule(secondary_c, m, movemask, min_bound, max_bound, cost_func, simplexen); } // Each vertex is sitting on a ridge. Pop over the ridge and // walk gradient down to a minimum. If it's a new minimum, grow a // new granule. // this is here and not above to allow each granule to fill out // completely before beginning work on another. for(i=0;i<(m+1);i++){ // re-set up orthogonal move mask for this vertex memset(movemask,0,sizeof(*movemask)*m); if(i>0)movemask[i-1]=-1; if(i<m)movemask[i]=1; //crest_walk_and_recurse(new_c[i], m, movemask, min_bound, max_bound, cost_func, granules); free(new_c[i]); } free(movemask); free(new_c); }
void grow_secondary_granule(int *minimumc, int **c, int m, int *movemask, int min_bound, int max_bound, double (*cost_func)(int *), int *simplexen, int *granules){ int i; // grow the single free vertex int movement = grow_vertex(c[0], m, movemask, min_bound, max_bound, cost_func); if(movement<=1){ // 1 is roundoff error slack // we cannot grow a new simplex; the simplex facet is pressed flat // against a convergence ridge. // this is the correct point to crest the ridge and walk the granule // down the other side looking for a new minimum. If it is indeed a new // minimum, grow a new granule. for(i=0;i<m;i++) c[0][i] += movemask[i]; double cost = gradient_walk(c[0], m, min_bound, max_bound, cost_func); int min_num = lookup_minimum(c[0]); if(min_num!=-1){ log_minimum(c[0],cost); grow_new_granule(c[0]); // enter recursion } return; } // continue recursively spawning secondary simplexes with one // unconstrained vertex from the center of each face of this // simplex. The new vertex must grow outward (reflect the simplex // through each face). int **secondary_c = malloc((m+1) * sizeof(*secondary_c)); secondary_c[0] = malloc(m * sizeof(**new_c)); for(i=0;i<(m+1);i++){ // build a new d-1-tope 'plane'; all the points in the current // simplex minus the i'th one. // fill in the fixed verticies [1 through m] for(j=1;j<m;j++) if(j<=i) secondary_c[j] = new_c[j-1]; else secondary_c[j] = new_c[j]; // first vertex is the unconstrained one center_of_tope(secondary_c[0], secondary_c+1, m); // set movemask [reverse of the i'th vertex's movemask] memset(movemask,0,sizeof(*movemask)*m); if(i>0)movemask[i-1]=1; if(i<m)movemask[i]=-1; grow_secondary_granule(secondary_c, m, movemask, min_bound, max_bound, cost_func, simplexen); } // Each vertex is sitting on a ridge. Pop over the ridge and // walk gradient down to a minimum. If it's a new minimum, grow a // new granule. // this is here and not above to allow each granule to fill out // completely before beginning work on another. for(i=0;i<(m+1);i++){ // re-set up orthogonal move mask for this vertex memset(movemask,0,sizeof(*movemask)*m); if(i>0)movemask[i-1]=-1; if(i<m)movemask[i]=1; //crest_walk_and_recurse(new_c[i], m, movemask, min_bound, max_bound, cost_func, granules); free(new_c[i]); } free(movemask); free(new_c); }