void Graph::dfs(const string &node, int &time) { adjacency_list::iterator e; neighbor_list *neighbors; if (finished) return; visited[node] = true; time = time + 1; entry_time[node] = time; if (adj_list.find(node) != adj_list.end()) { neighbors = adj_list[node]; for (neighbor_list::iterator it = neighbors->begin(); it != neighbors->end(); ++it) { if (visited.find(it->first) == visited.end()) { parent[it->first] = node; process_edge(node, it->first); dfs(it->first, time); } else { process_edge(node, it->first); } } } time = time + 1; processed[node] = true; }
void LinearizerBase::process_edge(int iv1, int iv2, int marker) { int mid = peek_vertex(iv1, iv2); if(mid != -1) { process_edge(iv1, mid, marker); process_edge(mid, iv2, marker); } else add_edge(iv1, iv2, marker); }
bfs(graph *g, int start) { queue q; /* queue of vertices to visit */ int v; /* current vertex */ int i; /* counter */ init_queue(&q); enqueue(&q,start); discovered[start] = TRUE; while (empty(&q) == FALSE) { v = dequeue(&q); process_vertex_early(v); processed[v] = TRUE; for (i=0; i<g->degree[v]; i++) if (valid_edge(g->edges[v][i]) == TRUE) { if (discovered[g->edges[v][i]] == FALSE) { enqueue(&q,g->edges[v][i]); discovered[g->edges[v][i]] = TRUE; parent[g->edges[v][i]] = v; } if (processed[g->edges[v][i]] == FALSE) process_edge(v,g->edges[v][i]); } process_vertex_late(v); } }
dfs(graph *g, int v) { int i; /* counter */ int y; /* successor vertex */ if (finished) return; /* allow for search termination */ discovered[v] = TRUE; process_vertex_early(v); for (i=0; i<g->degree[v]; i++) { y = g->edges[v][i]; if (valid_edge(g->edges[v][i]) == TRUE) { if (discovered[y] == FALSE) { parent[y] = v; dfs(g,y); } else if (processed[y] == FALSE) process_edge(v,y); } if (finished) return; } process_vertex_late(v); processed[v] = TRUE; }
void Graph::bfs_worker(int start, void(*process_vertex_early)(int v), void(*process_vertex_late)(int v), void(*process_edge)(int v, EdgeNode *p)) { queue<int> q; int v; int y; EdgeNode *p; q.push(start); discovered[start] = TRUE; while(q.empty() == FALSE){ v = q.front(); q.pop(); process_vertex_early(v); processed[v] = TRUE; p = this->edges[v]; while(p){ y = p->y; if(processed[y] == FALSE || this->directed) process_edge(v,p); if(discovered[y] == FALSE){ q.push(y); discovered[y] = TRUE; parent[y] = v; } p = p->next; } process_vertex_late(v); } }
// process all elements of the mesh for_all_active_elements(e, mesh) { sln->set_active_element(e); sln->set_quad_order(0, item); scalar* val = sln->get_values(ia, ib); if (disp) { xdisp->set_active_element(e); ydisp->set_active_element(e); } int iv[4]; for (unsigned int i = 0; i < e->nvert; i++) iv[i] = get_top_vertex(id2id[e->vn[i]->id], getval(i)); // we won't bother calculating physical coordinates from the refmap if this is not a curved element curved = e->is_curved(); cmax = e->get_diameter(); // recur to sub-elements if (e->is_triangle()) process_triangle(iv[0], iv[1], iv[2], 0, NULL, NULL, NULL, NULL); else process_quad(iv[0], iv[1], iv[2], iv[3], 0, NULL, NULL, NULL, NULL); for (unsigned int i = 0; i < e->nvert; i++) process_edge(iv[i], iv[e->next_vert(i)], e->en[i]->marker); }
void bfs(graph *g, int start) { queue q; /* queue of vertices to visit */ int v; /* current vertex */ int y; /* successor vertex */ edgenode *p; /* temporary pointer */ init_queue(&q); enqueue(&q,start); discovered[start] = TRUE; while (empty_queue(&q) == FALSE) { v = dequeue(&q); processed[v] = TRUE; p = g->edges[v]; while (p != NULL) { y = p->y; if ((processed[y] == FALSE) || g->directed) process_edge(v,y); if (discovered[y] == FALSE) { enqueue(&q,y); discovered[y] = TRUE; parent[y] = v; } p = p->next; } } }
int process_vertex(int v) { int i; bool valid_vertex=0; /* Evitamos los cálculos en el nodo si éste ha sido marcado como "congelado" (Alg. Rec.)*/ /* Igualmente, no calculamos los nodos invalidos */ /* Acumula el consumo total (Y002) por los receptores y guarda dicho valor en el nodo */ for (i=0; i< g.degree[v]; i++){ fprintf(flog,"Agregando consumo para nodo %s\n",n[v].label); n[v].utilizacion += g.consumo[v][i]; fprintf(flog,"Utilizacion = %.4f\n",n[v].utilizacion); } /* Revisa que la utilizacion no sea mayor que la capacidad cuando existe capacidad limitante */ if(n[v].flag_capacity){ // Reducimos la capacidad para evitar fugas de dinero // Usando fabs() estaba generando una alerta ?? double diff = abs(n[v].utilizacion - n[v].capacidad) / n[v].capacidad; if( diff < TOLERANCIA){ fprintf(flog,"Ajustando capacidad de nodo %d de %.2f a %.2f\n",v,n[v].capacidad,n[v].utilizacion); n[v].capacidad = n[v].utilizacion; } else { printf("Nodo %s tiene capacidad no utilizada.\nUtilizacion: %.2f\nCapacidad: %.2f\n", n[v].label, n[v].utilizacion, n[v].capacidad); } if (n[v].utilizacion > n[v].capacidad) { printf("Utilizacion %.2f excede capacidad %.2f para nodo %d con capacidad limitante\n",n[v].utilizacion,n[v].capacidad,v); exit(EXIT_FAILURE); } } else { // Nodo no tiene capacidad limitante -- su utilización es su capacidad n[v].capacidad = n[v].utilizacion; } /* Calcula tasa fija (RT01) y proporcional (RT02) para el nodo y guarda dicho valor en el nodo */ if(n[v].capacidad){ n[v].tasa_fija = (n[v].costo_primario_fijo + n[v].costo_secundario_fijo) / n[v].capacidad; } if(n[v].utilizacion) { n[v].tasa_proporcional = (n[v].costo_primario_proporcional + n[v].costo_secundario_proporcional) / n[v].utilizacion; } /* Procesamos las aristas que salen del nodo */ for (i=0; i< g.degree[v]; i++) if (valid_edge(v,i)) /* Verifica que el consumo sea mayor a cero */ process_edge(v,i); /* Calcula costos secundarios y los acumula en la estructura del nodo receptor */ fprintf(flog,"Se proceso el nodo %d (congelado=%d)\n",v,n[v].congelar_tasas); n[v].flag_tasa=1; return 0; }
zebra_symbol_type_t zebra_scanner_new_scan (zebra_scanner_t *scn) { /* finalize outstanding edge */ zebra_symbol_type_t edge = process_edge(scn, 0); /* reset color to SPACE * (actually just resets everything) */ memset(&scn->x, 0, sizeof(zebra_scanner_t) + (void*)scn - (void*)&scn->x); scn->y1_thresh = scn->y1_min_thresh; if(scn->decoder) zebra_decoder_new_scan(scn->decoder); return(edge); }
void Graph::dfs_worker(int v, void(*process_vertex_early)(int v), void(*process_vertex_late)(int v), void(*process_edge)(int v,EdgeNode *p)) { EdgeNode *p; int y; if(finished) return; discovered[v] = TRUE; entry_time[v] = ++time; process_vertex_early(v); p = this->edges[v]; while(p){ y = p->y; if(!discovered[y]){ parent[y] = v; process_edge(v,p); dfs_worker(y,process_vertex_early, process_vertex_late, process_edge); } else if( (!processed[y] && parent[v] != y) || (this->directed)){ process_edge(v,p); } if(finished) return; p = p->next; } process_vertex_late(v); exit_time[v] = ++time; processed[v] = TRUE; }
void bfs(graph *g, int start) { queue q; init_queue(&q); enqueue(&q, start); discovered[start] = true; while (empty_queue(&q) == false) { int v = dequeue(&q); process_vertex_early(v); processed[v] = true; edgenode *p = g->edges[v]; while (p != NULL) { int y = p->y; if (valid_edge(p)) { if ((!processed[y]) || g->directed) { process_edge(v, y); } if (!discovered[y]) { enqueue(&q, y); discovered[y] = true; parent[y] = v; } } p = p->next; } process_vertex_late(v); } }
void dfs(Graph &g, int v) { std::vector<EdgeNodePtr> nextEdge(g.vc+1); std::vector<VStatus> vs(g.vc+1); std::stack<int> s; s.push(v); vs[v] = DIS; process_vertex_early(v); nextEdge[v] = g.eNs[v]; while (!s.empty()) { int x = s.top(); EdgeNodePtr yp = nextEdge[x]; if (yp) { int y = yp->y; nextEdge[x] = yp->next; bool newEdge = false; if(vs[y] == UND) { nextEdge[y] = g.eNs[y]; s.push(y); vs[y] = DIS; process_vertex_early(y); } if (vs[y] != PRO || g.directed) { process_edge(x, y); } } else { s.pop(); process_vertex_late(x); vs[x] = PRO; } } }
void BreadthFirstSearch::bfs(Graph *g, int start) { Queue q; int current_v; int successor_v; edgenode *current_edges; q.enqueue(start); q.print(); discovered[start] = true; while(q.queueSize() > 0) { current_v = q.dequeue(); process_vertex_early(current_v); processed[current_v] = true; current_edges = g->edges[current_v]; while(current_edges != nullptr) { successor_v = current_edges->y; if((!processed[successor_v])) { process_edge(current_v, successor_v); } if(!discovered[successor_v]) { q.enqueue(successor_v); discovered[successor_v] = true; parent[successor_v] = current_v; } current_edges = current_edges->next; } process_vertex_late(current_v); } }
void dfs(struct graph *g, int node){ struct edge *tmp = g->edges[node]; time++; entry_time[node] = time; discovered[node] = 1; while(tmp){ int y = tmp->y; if(!discovered[y]){ parent[y] = node; process_edge(node, y); dfs(g, y); } else if(!processed[y]){ if(parent[node] != y){ printf("Sorry, %d -> %d this is not a DAG !\n", node, y); } } tmp = tmp->next; } time++; process_vertex_late(node); exit_time[node] = time; processed[node] = 1; printf("\n"); }
/************************************************* Function: build_vertexes Description: 1. Reads sequence from *.sparse.edge. 2. Builds vertexes by cutting the edge sequence's end kmers. Input: 1. v_ht: vertex hashtable 2. K_size: kmer size 3. edge_file: edge file Output: None. Return: None. *************************************************/ void build_vertexes ( vertex_hash2 * v_ht, int K_size, char * edge_file ) { FILE * fp; kmer_t2 from_kmer, to_kmer; size_t line_len, edge_len_left; int edge_len; int cvg; bool bal_ed;//回文为0 const int BUFF_LEN = 1024; char line[BUFF_LEN]; char str[32]; char to_buff[BUFF_LEN];//buffer 2k edge seq BUFF_LEN>4*K_size int processed = 0; //0表示未处理 1表示 处理完毕 2 表示已经处理了from_vertex ,to_vertex 还没有处理 size_t edge_id = 0; fp = fopen ( edge_file, "r" ); if ( !fp ) { fprintf ( stderr, "ERROR: Cannot open edge_file %s. Now exit to system...\n", edge_file ); exit ( -1 ); } vertex2 * v_tmp; edge_starter2 * e_tmp; int is_found; bool is_left; while ( fgets ( line, BUFF_LEN, fp ) != NULL ) { //debug<<"processed "<<processed<<endl; if ( line[0] == '>' ) //get one edge length, from vertex, to vertex,cvg,bal { if ( processed == 1 && bal_ed ) { edge_id++;//如果不是回文 } #ifdef _63MER_ sscanf ( line + 7, "%d,%llx %llx ,%llx %llx ,%s %d,%d", &edge_len, & ( from_kmer.kmer ) [0], & ( from_kmer.kmer ) [1], & ( to_kmer.kmer ) [0], & ( to_kmer.kmer ) [1], str, &cvg, &bal_ed ); // from_kmer to_kmer is of no use here #endif #ifdef _127MER_ sscanf ( line + 7, "%d,%llx %llx %llx %llx ,%llx %llx %llx %llx ,%s %d,%d", &edge_len, & ( from_kmer.kmer ) [0], & ( from_kmer.kmer ) [1], & ( from_kmer.kmer ) [2], & ( from_kmer.kmer ) [3], & ( to_kmer.kmer ) [0], & ( to_kmer.kmer ) [1], & ( to_kmer.kmer ) [2], & ( to_kmer.kmer ) [3], str, &cvg, &bal_ed ); // from_kmer to_kmer is of no use here #endif edge_len_left = K_size + edge_len; processed = 0; edge_id++;// current edge positive strand id //debug<<line<<"edge_id "<<edge_id<<endl; } else { if ( processed == 0 ) { line_len = strlen ( line ); if ( line[line_len - 1] == '\n' ) { line[line_len - 1] = '\0'; line_len --; } if ( edge_len_left - line_len == 0 ) //edge completely loaded { //do all process process_edge ( v_ht, K_size, line, line_len, 1, edge_id, bal_ed ); processed = 1; edge_len_left = 0; continue; } else //edge partly loaded at the first time. { if ( line_len < 2 * K_size ) //line_len < 2*K_size &&edge_len_left - line_len > 0 { fprintf ( stderr, "ERROR:it won't happen in 63mer/127mer\n" ); exit ( 1 ); } else { process_edge ( v_ht, K_size, line, line_len, 2, edge_id, bal_ed ); processed = 2; edge_len_left -= line_len; if ( edge_len_left >= 2 * K_size ) { //no need to buf the to kmer seq } else if ( edge_len_left < 2 * K_size ) { //to_buff[100];/ copy the last 2K char of line to to_buff already no '\n' strcpy ( to_buff, line + ( line_len - 2 * K_size ) ); } else { fprintf ( stderr, "ERROR: in cal the edge_len_left!!\n" ); exit ( 1 ); } } } } else if ( processed == 2 ) { //if(line[0]=='\n') continue; line_len = strlen ( line ); if ( line[line_len - 1] == '\n' ) { line[line_len - 1] = '\0'; line_len --; } edge_len_left -= line_len; if ( edge_len_left == 0 ) //load the complete edge sequence { //process the to kmer if ( line_len >= 2 * K_size ) { process_edge ( v_ht, K_size, line, line_len, 3, edge_id, bal_ed ); } else { //need to use the to_buff int buf_len = strlen ( to_buff ); strcpy ( to_buff + buf_len, line ); buf_len = strlen ( to_buff ); process_edge ( v_ht, K_size, to_buff, buf_len, 3, edge_id, bal_ed ); } processed = 1; continue; } else { if ( edge_len_left >= 2 * K_size ) { //no need to buf the to kmer seq } else if ( edge_len_left < 2 * K_size ) { //to_buff[100];/ copy the last 2K char of line to to_buff strcpy ( to_buff, line + ( line_len - 2 * K_size ) ); } else { fprintf ( stderr, "ERROR: in cal the edge_len_left!!\n" ); exit ( 1 ); } } } else { if ( line[0] == '\n' ) { continue; } //当len = 1023时 fprintf ( stderr, "ERROR: in cal the status_processed !! %d \n", processed ); exit ( 1 ); } } } fclose ( fp ); }
void Vectorizer::process_solution(MeshFunction* xsln, int xitem, MeshFunction* ysln, int yitem, double eps) { // sanity check if (xsln == NULL || ysln == NULL) error("One of the solutions is NULL in Vectorizer:process_solution()."); lock_data(); TimePeriod cpu_time; // initialization this->xsln = xsln; this->ysln = ysln; this->xitem = xitem; this->yitem = yitem; this->eps = eps; nv = nt = ne = nd = 0; del_slot = -1; Mesh* meshes[2] = { xsln->get_mesh(), ysln->get_mesh() }; if (meshes[0] == NULL || meshes[1] == NULL) { error("One of the meshes is NULL in Vectorizer:process_solution()."); } Transformable* fns[2] = { xsln, ysln }; Traverse trav; // estimate the required number of vertices and triangles // (based on the assumption that the linear mesh will be // about four-times finer than the original mesh). int nn = meshes[0]->get_num_elements() + meshes[1]->get_num_elements(); int ev = std::max(32 * nn, 10000); int et = std::max(64 * nn, 20000); int ee = std::max(24 * nn, 7500); int ed = ee; lin_init_array(verts, double4, cv, ev); lin_init_array(tris, int3, ct, et); lin_init_array(edges, int3, ce, ee); lin_init_array(dashes, int2, cd, ed); info = (int4*) malloc(sizeof(int4) * cv); // initialize the hash table int size = 0x1000; while (size*2 < cv) size *= 2; hash_table = (int*) malloc(sizeof(int) * size); memset(hash_table, 0xff, sizeof(int) * size); mask = size-1; // select the linearization quadrature Quad2D *old_quad_x, *old_quad_y; old_quad_x = xsln->get_quad_2d(); old_quad_y = ysln->get_quad_2d(); xsln->set_quad_2d((Quad2D*) &quad_lin); ysln->set_quad_2d((Quad2D*) &quad_lin); if (!xitem) error("Parameter 'xitem' cannot be zero."); if (!yitem) error("Parameter 'yitem' cannot be zero."); get_gv_a_b(xitem, xia, xib); get_gv_a_b(yitem, yia, yib); if (xib >= 6) error("Invalid value of paremeter 'xitem'."); if (yib >= 6) error("Invalid value of paremeter 'yitem'."); max = 1e-10; trav.begin(2, meshes, fns); Element** e; while ((e = trav.get_next_state(NULL, NULL)) != NULL) { xsln->set_quad_order(0, xitem); ysln->set_quad_order(0, yitem); scalar* xval = xsln->get_values(xia, xib); scalar* yval = ysln->get_values(yia, yib); for (unsigned int i = 0; i < e[0]->nvert; i++) { double fx = getvalx(i); double fy = getvaly(i); if (fabs(sqrt(fx*fx + fy*fy)) > max) max = fabs(sqrt(fx*fx + fy*fy)); } } trav.finish(); trav.begin(2, meshes, fns); // process all elements of the mesh while ((e = trav.get_next_state(NULL, NULL)) != NULL) { xsln->set_quad_order(0, xitem); ysln->set_quad_order(0, yitem); scalar* xval = xsln->get_values(xia, xib); scalar* yval = ysln->get_values(yia, yib); double* x = xsln->get_refmap()->get_phys_x(0); double* y = ysln->get_refmap()->get_phys_y(0); int iv[4]; for (unsigned int i = 0; i < e[0]->nvert; i++) { double fx = getvalx(i); double fy = getvaly(i); iv[i] = create_vertex(x[i], y[i], fx, fy); } // we won't bother calculating physical coordinates from the refmap if this is not a curved element curved = (e[0]->cm != NULL); // recur to sub-elements if (e[0]->is_triangle()) process_triangle(iv[0], iv[1], iv[2], 0, NULL, NULL, NULL, NULL, NULL); else process_quad(iv[0], iv[1], iv[2], iv[3], 0, NULL, NULL, NULL, NULL, NULL); // process edges and dashes (bold line for edge in both meshes, dashed line for edge in one of the meshes) Trf* xctm = xsln->get_ctm(); Trf* yctm = ysln->get_ctm(); double r[4] = { -1.0, 1.0, 1.0, -1.0 }; double ref[4][2] = { {-1.0,-1.0}, {1.0,-1.0}, {1.0,1.0}, {-1.0,1.0} }; for (unsigned int i = 0; i < e[0]->nvert; i++) { bool bold = false; double px = ref[i][0]; double py = ref[i][1]; // for odd edges (1, 3) we check x coordinate after ctm transformation, if it's the same (1 or -1) in both meshes => bold if (i & 1) { if ((xctm->m[0]*px + xctm->t[0] == r[i]) && (yctm->m[0]*px + yctm->t[0] == r[i])) bold = true; } // for even edges (0, 4) we check y coordinate after ctm transformation, if it's the same (-1 or 1) in both meshes => bold else { if ((xctm->m[1]*py + xctm->t[1] == r[i]) && (yctm->m[1]*py + yctm->t[1] == r[i])) bold = true; } int j = e[0]->next_vert(i); // we draw a line only if both edges lies on the boundary or if the line is from left top to right bottom if (((e[0]->en[i]->bnd) && (e[1]->en[i]->bnd)) || (verts[iv[i]][1] < verts[iv[j]][1]) || (verts[iv[i]][1] == verts[iv[j]][1] && verts[iv[i]][0] < verts[iv[j]][0])) { if (bold) process_edge(iv[i], iv[j], e[0]->en[i]->marker); else process_dash(iv[i], iv[j]); } } } trav.finish(); find_min_max(); verbose("Vectorizer created %d verts and %d tris in %0.3g s", nv, nt, cpu_time.tick().last()); //if (verbose_mode) print_hash_stats(); unlock_data(); // select old quadratrues xsln->set_quad_2d(old_quad_x); ysln->set_quad_2d(old_quad_y); // clean up ::free(hash_table); ::free(info); }
//********************************************************************************** // function: rr_active_sites // // description: Determines if request_router has acvive edge sites. // Returns 0 for no sites, # of active edge sites. //********************************************************************************** static int16_t rr_active_sites(tc_health_thread_ctxt_t * pCntx, const char * ip) { CURL * curl; CURLcode res; UrlData_t url_data; json_error_t error; int16_t ret = 0; const char * url_fmt = "http://%s/api/servers/"; char url[64]; bzero(&url_data, sizeof(url_data)); snprintf(url, sizeof(url),url_fmt, ip); url[sizeof(url)-1] = '\0'; curl = curl_easy_init(); if(NULL == curl) return 0; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, UrlCallback); curl_easy_setopt(curl, CURLOPT_NOSIGNAL,1L); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)& url_data); curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); res = curl_easy_perform(curl); if(res != CURLE_OK) { curl_easy_cleanup(curl); return 0; } curl_easy_cleanup(curl); json_t * root = json_loads(url_data.buffer, 0, &error); if(!root) return 0; void *iter = json_object_iter(root); if(!iter) { json_decref(root); return 0; } const char * key = json_object_iter_key(iter); json_t * j = json_object_iter_value(iter); json_object_del(j, "route_expression"); json_object_del(j, "route_expression_suffix"); json_object_del(j, "date"); json_object_del(j, "active_sites"); json_object_del(j, "supported_sites"); json_t * edge_cluster; json_object_foreach(j, key, edge_cluster) { evLogTrace( pCntx->pQHealthToBkgrnd, evLogLvlDebug, &(pCntx->tLogDescSys), "Processing edge_cluster %s.", key); void *iter = json_object_iter(edge_cluster); if(process_edge(json_object_iter_value(iter))) { ret = 1; break; } }
int CHOLMOD(rowcolcounts) ( /* ---- input ---- */ cholmod_sparse *A, /* matrix to analyze */ Int *fset, /* subset of 0:(A->ncol)-1 */ size_t fsize, /* size of fset */ Int *Parent, /* size nrow. Parent [i] = p if p is the parent of i */ Int *Post, /* size nrow. Post [k] = i if i is the kth node in * the postordered etree. */ /* ---- output --- */ Int *RowCount, /* size nrow. RowCount [i] = # entries in the ith row of * L, including the diagonal. */ Int *ColCount, /* size nrow. ColCount [i] = # entries in the ith * column of L, including the diagonal. */ Int *First, /* size nrow. First [i] = k is the least postordering * of any descendant of i. */ Int *Level, /* size nrow. Level [i] is the length of the path from * i to the root, with Level [root] = 0. */ /* --------------- */ cholmod_common *Common ) { double fl, ff ; Int *Ap, *Ai, *Anz, *PrevNbr, *SetParent, *Head, *PrevLeaf, *Anext, *Ipost, *Iwork ; Int i, j, r, k, len, s, p, pend, inew, stype, nf, anz, inode, parent, nrow, ncol, packed, use_fset, jj ; size_t w ; int ok = TRUE ; /* ---------------------------------------------------------------------- */ /* check inputs */ /* ---------------------------------------------------------------------- */ RETURN_IF_NULL_COMMON (FALSE) ; RETURN_IF_NULL (A, FALSE) ; RETURN_IF_NULL (Parent, FALSE) ; RETURN_IF_NULL (Post, FALSE) ; RETURN_IF_NULL (ColCount, FALSE) ; RETURN_IF_NULL (First, FALSE) ; RETURN_IF_NULL (Level, FALSE) ; RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, FALSE) ; stype = A->stype ; if (stype > 0) { /* symmetric with upper triangular part not supported */ ERROR (CHOLMOD_INVALID, "symmetric upper not supported") ; return (FALSE) ; } Common->status = CHOLMOD_OK ; /* ---------------------------------------------------------------------- */ /* allocate workspace */ /* ---------------------------------------------------------------------- */ nrow = A->nrow ; /* the number of rows of A */ ncol = A->ncol ; /* the number of columns of A */ /* w = 2*nrow + (stype ? 0 : ncol) */ w = CHOLMOD(mult_size_t) (nrow, 2, &ok) ; w = CHOLMOD(add_size_t) (w, (stype ? 0 : ncol), &ok) ; if (!ok) { ERROR (CHOLMOD_TOO_LARGE, "problem too large") ; return (FALSE) ; } CHOLMOD(allocate_work) (nrow, w, 0, Common) ; if (Common->status < CHOLMOD_OK) { return (FALSE) ; } ASSERT (CHOLMOD(dump_perm) (Post, nrow, nrow, "Post", Common)) ; ASSERT (CHOLMOD(dump_parent) (Parent, nrow, "Parent", Common)) ; /* ---------------------------------------------------------------------- */ /* get inputs */ /* ---------------------------------------------------------------------- */ Ap = A->p ; /* size ncol+1, column pointers for A */ Ai = A->i ; /* the row indices of A, of size nz=Ap[ncol+1] */ Anz = A->nz ; packed = A->packed ; ASSERT (IMPLIES (!packed, Anz != NULL)) ; /* ---------------------------------------------------------------------- */ /* get workspace */ /* ---------------------------------------------------------------------- */ Iwork = Common->Iwork ; SetParent = Iwork ; /* size nrow (i/i/l) */ PrevNbr = Iwork + nrow ; /* size nrow (i/i/l) */ Anext = Iwork + 2*((size_t) nrow) ; /* size ncol (i/i/l) (unsym only) */ PrevLeaf = Common->Flag ; /* size nrow */ Head = Common->Head ; /* size nrow+1 (unsym only)*/ /* ---------------------------------------------------------------------- */ /* find the first descendant and level of each node in the tree */ /* ---------------------------------------------------------------------- */ /* First [i] = k if the postordering of first descendent of node i is k */ /* Level [i] = length of path from node i to the root (Level [root] = 0) */ for (i = 0 ; i < nrow ; i++) { First [i] = EMPTY ; } /* postorder traversal of the etree */ for (k = 0 ; k < nrow ; k++) { /* node i of the etree is the kth node in the postordered etree */ i = Post [k] ; /* i is a leaf if First [i] is still EMPTY */ /* ColCount [i] starts at 1 if i is a leaf, zero otherwise */ ColCount [i] = (First [i] == EMPTY) ? 1 : 0 ; /* traverse the path from node i to the root, stopping if we find a * node r whose First [r] is already defined. */ len = 0 ; for (r = i ; (r != EMPTY) && (First [r] == EMPTY) ; r = Parent [r]) { First [r] = k ; len++ ; } if (r == EMPTY) { /* we hit a root node, the level of which is zero */ len-- ; } else { /* we stopped at node r, where Level [r] is already defined */ len += Level [r] ; } /* re-traverse the path from node i to r; set the level of each node */ for (s = i ; s != r ; s = Parent [s]) { Level [s] = len-- ; } } /* ---------------------------------------------------------------------- */ /* AA' case: sort columns of A according to first postordered row index */ /* ---------------------------------------------------------------------- */ fl = 0.0 ; if (stype == 0) { /* [ use PrevNbr [0..nrow-1] as workspace for Ipost */ Ipost = PrevNbr ; /* Ipost [i] = k if i is the kth node in the postordered etree. */ for (k = 0 ; k < nrow ; k++) { Ipost [Post [k]] = k ; } use_fset = (fset != NULL) ; if (use_fset) { nf = fsize ; /* clear Anext to check fset */ for (j = 0 ; j < ncol ; j++) { Anext [j] = -2 ; } /* find the first postordered row in each column of A (post,f) * and place the column in the corresponding link list */ for (jj = 0 ; jj < nf ; jj++) { j = fset [jj] ; if (j < 0 || j > ncol || Anext [j] != -2) { /* out-of-range or duplicate entry in fset */ ERROR (CHOLMOD_INVALID, "fset invalid") ; return (FALSE) ; } /* flag column j as having been seen */ Anext [j] = EMPTY ; } /* fset is now valid */ ASSERT (CHOLMOD(dump_perm) (fset, nf, ncol, "fset", Common)) ; } else { nf = ncol ; } for (jj = 0 ; jj < nf ; jj++) { j = (use_fset) ? (fset [jj]) : jj ; /* column j is in the fset; find the smallest row (if any) */ p = Ap [j] ; pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; ff = (double) MAX (0, pend - p) ; fl += ff*ff + ff ; if (pend > p) { k = Ipost [Ai [p]] ; for ( ; p < pend ; p++) { inew = Ipost [Ai [p]] ; k = MIN (k, inew) ; } /* place column j in link list k */ ASSERT (k >= 0 && k < nrow) ; Anext [j] = Head [k] ; Head [k] = j ; } } /* Ipost no longer needed for inverse postordering ] * Head [k] contains a link list of all columns whose first * postordered row index is equal to k, for k = 0 to nrow-1. */ } /* ---------------------------------------------------------------------- */ /* compute the row counts and node weights */ /* ---------------------------------------------------------------------- */ if (RowCount != NULL) { for (i = 0 ; i < nrow ; i++) { RowCount [i] = 1 ; } } for (i = 0 ; i < nrow ; i++) { PrevLeaf [i] = EMPTY ; PrevNbr [i] = EMPTY ; SetParent [i] = i ; /* every node is in its own set, by itself */ } if (stype != 0) { /* ------------------------------------------------------------------ */ /* symmetric case: LL' = A */ /* ------------------------------------------------------------------ */ /* also determine the number of entries in triu(A) */ anz = nrow ; for (k = 0 ; k < nrow ; k++) { /* j is the kth node in the postordered etree */ j = initialize_node (k, Post, Parent, ColCount, PrevNbr) ; /* for all nonzeros A(i,j) below the diagonal, in column j of A */ p = Ap [j] ; pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { i = Ai [p] ; if (i > j) { /* j is a descendant of i in etree(A) */ anz++ ; process_edge (j, i, k, First, PrevNbr, ColCount, PrevLeaf, RowCount, SetParent, Level) ; } } /* update SetParent: UNION (j, Parent [j]) */ finalize_node (j, Parent, SetParent) ; } Common->anz = anz ; } else { /* ------------------------------------------------------------------ */ /* unsymmetric case: LL' = AA' */ /* ------------------------------------------------------------------ */ for (k = 0 ; k < nrow ; k++) { /* inode is the kth node in the postordered etree */ inode = initialize_node (k, Post, Parent, ColCount, PrevNbr) ; /* for all cols j whose first postordered row is k: */ for (j = Head [k] ; j != EMPTY ; j = Anext [j]) { /* k is the first postordered row in column j of A */ /* for all rows i in column j: */ p = Ap [j] ; pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ; for ( ; p < pend ; p++) { i = Ai [p] ; /* has i already been considered at this step k */ if (PrevNbr [i] < k) { /* inode is a descendant of i in etree(AA') */ /* process edge (inode,i) and set PrevNbr[i] to k */ process_edge (inode, i, k, First, PrevNbr, ColCount, PrevLeaf, RowCount, SetParent, Level) ; } } } /* clear link list k */ Head [k] = EMPTY ; /* update SetParent: UNION (inode, Parent [inode]) */ finalize_node (inode, Parent, SetParent) ; } } /* ---------------------------------------------------------------------- */ /* finish computing the column counts */ /* ---------------------------------------------------------------------- */ for (j = 0 ; j < nrow ; j++) { parent = Parent [j] ; if (parent != EMPTY) { /* add the ColCount of j to its parent */ ColCount [parent] += ColCount [j] ; } } /* ---------------------------------------------------------------------- */ /* clear workspace */ /* ---------------------------------------------------------------------- */ Common->mark = EMPTY ; /* CHOLMOD(clear_flag) (Common) ; */ CHOLMOD_CLEAR_FLAG (Common) ; ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, 0, Common)) ; /* ---------------------------------------------------------------------- */ /* flop count and nnz(L) for subsequent LL' numerical factorization */ /* ---------------------------------------------------------------------- */ /* use double to avoid integer overflow. lnz cannot be NaN. */ Common->aatfl = fl ; Common->lnz = 0. ; fl = 0 ; for (j = 0 ; j < nrow ; j++) { ff = (double) (ColCount [j]) ; Common->lnz += ff ; fl += ff*ff ; } Common->fl = fl ; PRINT1 (("rowcol fl %g lnz %g\n", Common->fl, Common->lnz)) ; return (TRUE) ; }