/* spanning_tree: * Construct spanning forest of g as subgraph */ static Agraph_t *spanning_tree(Agraph_t * g) { Agnode_t *n; Agraph_t *tree; char gname[SMALLBUF]; static int id = 0; sprintf(gname, "_span_%d", id++); tree = agsubg(g, gname); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { aginsert(tree, n); DISTONE(n) = 0; DISTTWO(n) = 0; UNSET_VISITED(n); } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (!VISITED(n)) { TPARENT(n) = NULL; dfs(g, n, tree); } } return tree; }
static inline int VisitSegment (short nSegment, int bAutomap) { if (nSegment < 0) return 0; if (bAutomap) { if (automap.m_bDisplay) { if (!(automap.m_bFull || automap.m_visible [nSegment])) return 0; if (!gameOpts->render.automap.bSkybox && (SEGMENTS [nSegment].m_nType == SEGMENT_IS_SKYBOX)) return 0; } else automap.m_visited [0][nSegment] = gameData.render.mine.bSetAutomapVisited; } if (VISITED (nSegment)) return 0; VISIT (nSegment); return 1; }
/* dfs: * Simple depth first search, adding traversed edges to tree. */ static void dfs(Agraph_t * g, Agnode_t * n, Agraph_t * tree) { Agedge_t *e; Agnode_t *neighbor; SET_VISITED(n); for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) { neighbor = e->head; if (neighbor == n) neighbor = e->tail; if (!VISITED(neighbor)) { /* add the edge to the dfs tree */ aginsert(tree, e); TPARENT(neighbor) = n; dfs(g, neighbor, tree); } } }
/* findUnvisited: * Look for unvisited node n in visited block (i.e., some nodes in * the block have been visited) with neighbor not in block. Note * that therefore neighbor is unvisited. Set neighbor's parent to n * and return neighbor. * Guaranteed blp is non-empty. * */ static Agnode_t *findUnvisited(blocklist_t * blp) { Agnode_t *retn = NULL; FIX:finish Agnode_t * n; Agnode_t *newn; graph_t *clust_subg; edge_t *e; block_t *bp; block_t *prev = NULL; for (bp = blp->first; prev != blp->last; bp = bp->next) { prev = bp; clust = bp->sub_graph; if (DONE(bp)) continue; if (PARTIAL(bp)) { for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) { if (!VISITED(n)) { for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) { newn = e->head; if (newn == n) newn = e->tail; if ((BLOCK(newn) != bp)) { retn = newn; return; } } /* mark n visited */ } } /* mark bp done */ } else { } } return retn; }
/* %start-doc actions SmartDisperse The @code{SmartDisperse([All|Selected])} action is a special-purpose optimization for dispersing elements. Run with @code{:SmartDisperse()} or @code{:SmartDisperse(Selected)} (you can also say @code{:SmartDisperse(All)}, but that's the default). %end-doc */ static int smartdisperse (int argc, char **argv, Coord x, Coord y) { char *function = ARG(0); NetListType *Nets; char *visited; // PointerListType stack = { 0, 0, NULL }; int all; // int changed = 0; // int i; if (! function) { all = 1; } else if (strcmp(function, "All") == 0) { all = 1; } else if (strcmp(function, "Selected") == 0) { all = 0; } else { AFAIL (smartdisperse); } Nets = ProcNetlist (&PCB->NetlistLib); if (! Nets) { Message (_("Can't use SmartDisperse because no netlist is loaded.\n")); return 0; } /* remember which elements we finish with */ visited = calloc (PCB->Data->ElementN, sizeof(*visited)); /* if we're not doing all, mark the unselected elements as "visited" */ ELEMENT_LOOP (PCB->Data); { if (! (all || TEST_FLAG (SELECTEDFLAG, element))) { visited[n] = 1; } } END_LOOP; /* initialize variables for place() */ minx = GAP; miny = GAP; maxx = GAP; maxy = GAP; /* * Pick nets with two connections. This is the start of a more * elaborate algorithm to walk serial nets, but the datastructures * are too gross so I'm going with the 80% solution. */ NET_LOOP (Nets); { ConnectionType *conna, *connb; ElementType *ea, *eb; // ElementType *epp; if (net->ConnectionN != 2) continue; conna = &net->Connection[0]; connb = &net->Connection[1]; if (!IS_ELEMENT(conna) || !IS_ELEMENT(conna)) continue; ea = (ElementType *) conna->ptr1; eb = (ElementType *) connb->ptr1; /* place this pair if possible */ if (VISITED((GList *)ea) || VISITED((GList *)eb)) continue; VISITED ((GList *)ea) = 1; VISITED ((GList *)eb) = 1; /* a weak attempt to get the linked pads side-by-side */ if (padorder(conna, connb)) { place ((ElementType *) ea); place ((ElementType *) eb); } else { place (eb); place (ea); } } END_LOOP; /* Place larger nets, still grouping by net */ NET_LOOP (Nets); { CONNECTION_LOOP (net); { ElementType *element; if (! IS_ELEMENT(connection)) continue; element = (ElementType *) connection->ptr1; /* place this one if needed */ if (VISITED ((GList *) element)) continue; VISITED ((GList *) element) = 1; place (element); } END_LOOP; } END_LOOP; /* Place up anything else */ ELEMENT_LOOP (PCB->Data); { if (! visited[n]) { place (element); } } END_LOOP; free (visited); IncrementUndoSerialNumber (); Redraw (); SetChangedFlag (1); return 0; }
static EjsString *serialize(Ejs *ejs, EjsAny *vp, Json *json) { EjsName qname; EjsFunction *fn; EjsString *result, *sv; EjsTrait *trait; EjsObj *pp, *obj, *replacerArgs[2]; wchar *cp; cchar *key; int c, isArray, i, count, slotNum, quotes; /* The main code below can handle Arrays, Objects, objects derrived from Object and also native classes with properties. All others just use toString. */ count = ejsIsPot(ejs, vp) ? ejsGetLength(ejs, vp) : 0; if (count == 0 && TYPE(vp) != ESV(Object) && TYPE(vp) != ESV(Array)) { // OPT - need some flag for this test. if (!ejsIsDefined(ejs, vp) || ejsIs(ejs, vp, Boolean) || ejsIs(ejs, vp, Number)) { return ejsToString(ejs, vp); } else if (json->regexp) { return ejsToString(ejs, vp); } else { return ejsToLiteralString(ejs, vp); } } obj = vp; json->nest++; if (json->buf == 0) { json->buf = mprCreateBuf(0, 0); mprAddRoot(json->buf); } isArray = ejsIs(ejs, vp, Array); mprPutCharToWideBuf(json->buf, isArray ? '[' : '{'); if (json->pretty) { mprPutCharToWideBuf(json->buf, '\n'); } if (++ejs->serializeDepth <= json->depth && !VISITED(obj)) { SET_VISITED(obj, 1); for (slotNum = 0; slotNum < count && !ejs->exception; slotNum++) { trait = ejsGetPropertyTraits(ejs, obj, slotNum); if (trait && (trait->attributes & (EJS_TRAIT_HIDDEN | EJS_TRAIT_DELETED | EJS_FUN_INITIALIZER | EJS_FUN_MODULE_INITIALIZER)) && !json->hidden) { continue; } pp = ejsGetProperty(ejs, obj, slotNum); if (ejs->exception) { SET_VISITED(obj, 0); json->nest--; return 0; } if (pp == 0) { continue; } if (isArray) { key = itos(slotNum); qname.name = ejsCreateStringFromAsc(ejs, key); qname.space = ESV(empty); } else { qname = ejsGetPropertyName(ejs, vp, slotNum); } quotes = json->quotes; if (!quotes) { // UNICODE for (cp = qname.name->value; cp < &qname.name->value[qname.name->length]; cp++) { if (!isalnum((uchar) *cp) && *cp != '_') { quotes = 1; break; } } } if (json->pretty) { for (i = 0; i < ejs->serializeDepth; i++) { mprPutStringToWideBuf(json->buf, json->indent); } } if (!isArray) { if (json->namespaces) { if (qname.space != ESV(empty)) { mprPutToBuf(json->buf, "\"%@\"::", qname.space); } } if (quotes) { mprPutCharToWideBuf(json->buf, '"'); } for (cp = qname.name->value; cp && *cp; cp++) { c = *cp; if (c == '"' || c == '\\') { mprPutCharToWideBuf(json->buf, '\\'); mprPutCharToWideBuf(json->buf, c); } else { mprPutCharToWideBuf(json->buf, c); } } if (quotes) { mprPutCharToWideBuf(json->buf, '"'); } mprPutCharToWideBuf(json->buf, ':'); if (json->pretty) { mprPutCharToWideBuf(json->buf, ' '); } } fn = (EjsFunction*) ejsGetPropertyByName(ejs, TYPE(pp)->prototype, N(NULL, "toJSON")); // OPT - check that this is going directly to serialize most of the time if (!ejsIsFunction(ejs, fn) || (fn->isNativeProc && fn->body.proc == (EjsProc) ejsObjToJSON)) { sv = serialize(ejs, pp, json); } else { sv = (EjsString*) ejsRunFunction(ejs, fn, pp, 1, &json->options); } if (sv == 0 || !ejsIs(ejs, sv, String)) { if (ejs->exception) { ejsThrowTypeError(ejs, "Cannot serialize property %@", qname.name); SET_VISITED(obj, 0); return 0; } } else { if (json->replacer) { replacerArgs[0] = (EjsObj*) qname.name; replacerArgs[1] = (EjsObj*) sv; /* function replacer(key: String, value: String): String */ sv = ejsRunFunction(ejs, json->replacer, obj, 2, (EjsObj**) replacerArgs); } mprPutBlockToBuf(json->buf, sv->value, sv->length * sizeof(wchar)); } if ((slotNum + 1) < count || json->commas) { mprPutCharToWideBuf(json->buf, ','); } if (json->pretty) { mprPutCharToWideBuf(json->buf, '\n'); } } SET_VISITED(obj, 0); } --ejs->serializeDepth; if (json->pretty) { for (i = ejs->serializeDepth; i > 0; i--) { mprPutStringToWideBuf(json->buf, json->indent); } } mprPutCharToWideBuf(json->buf, isArray ? ']' : '}'); mprAddNullToWideBuf(json->buf); if (--json->nest == 0) { result = ejsCreateString(ejs, mprGetBufStart(json->buf), mprGetBufLength(json->buf) / sizeof(wchar)); mprRemoveRoot(json->buf); } else { result = 0; } return result; }
/* * Prim's approximated TSP tour * See also [Cristophides'92] */ static int findEulerianPath(TSP *tsp) { int *mst, *arc; int i, j, k, l, a; int n, *iorder, *jorder; DTYPE d; DTYPE maxd; DTYPE *dist; DTYPE *dis; jorder = tsp->jorder; iorder = tsp->iorder; dist = tsp->dist; maxd = tsp->maxd; n = tsp->n; if (!(mst =(int*) palloc((size_t) n * sizeof(int))) || !(arc =(int*) palloc((size_t) n * sizeof(int))) || !(dis =(DTYPE*) palloc((size_t) n * sizeof(DTYPE))) ) { elog(ERROR, "Failed to allocate memory!"); return -1; } // PGR_DBG("findEulerianPath: 1"); k = -1; j = -1; d = maxd; dis[0] = -1; for (i = 1; i < n; i++) { dis[i] = D(i, 0); arc[i] = 0; if (d > dis[i]) { d = dis[i]; j = i; } } // PGR_DBG("findEulerianPath: j=%d", j); if (j == -1) elog(ERROR, "Error TSP fail to findEulerianPath, check your distance matrix is valid."); /* * O(n^2) Minimum Spanning Trees by Prim and Jarnick * for graphs with adjacency matrix. */ for (a = 0; a < n - 1; a++) { mst[a] = j * n + arc[j]; /* join fragment j with MST */ dis[j] = -1; d = maxd; for (i = 0; i < n; i++) { if (dis[i] >= 0) { /* not connected yet */ if (dis[i] > D(i, j)) { dis[i] = D(i, j); arc[i] = j; } if (d > dis[i]) { d = dis[i]; k = i; } } } j = k; } // PGR_DBG("findEulerianPath: 3"); /* * Preorder Tour of MST */ #define VISITED(x) jorder[x] #define NQ(x) arc[l++] = x #define DQ() arc[--l] #define EMPTY (l == 0) for (i = 0; i < n; i++) VISITED(i) = 0; k = 0; l = 0; d = 0; NQ(0); while (!EMPTY) { i = DQ(); if (!VISITED(i)) { iorder[k++] = i; VISITED(i) = 1; for (j = 0; j < n - 1; j++) /* push all kids of i */ { if (i == mst[j]%n) NQ(mst[j]/n); } } } // PGR_DBG("findEulerianPath: 4"); return 0; }
/* * Prim's approximated TSP tour * See also [Cristophides'92] */ bool TSP::findEulerianPath() { Ids iorder(n); Ids mst(n); Ids arc(n); std::vector < double > dis(n); double d; #if 0 int n, *iorder, *jorder; DTYPE d; DTYPE maxd; DTYPE *dist; DTYPE *dis; jorder = tsp->jorder; iorder = tsp->iorder; dist = tsp->dist; maxd = tsp->maxd; n = tsp->n; if (!(mst = (int*) palloc(n * sizeof(int))) || !(arc = (int*) palloc(n * sizeof(int))) || !(dis = (DTYPE*) palloc(n * sizeof(DTYPE))) ) { elog(ERROR, "Failed to allocate memory!"); return -1; } #endif // PGR_DBG("findEulerianPath: 1"); size_t j(0); double curr_maxd = maxd; dis[0] = -1; for (size_t i = 1; i < n; ++i) { dis[i] = dist[i][0]; arc[i] = 0; if (curr_maxd > dis[i]) { curr_maxd = dis[i]; j = i; } } //PGR_DBG("findEulerianPath: j=%d", j); if (curr_maxd == maxd) { // PGR_DBG("Error TSP fail to findEulerianPath, check your distance matrix is valid."); return false; } /* * O(n^2) Minimum Spanning Trees by Prim and Jarnick * for graphs with adjacency matrix. */ for (size_t a = 0; a < n - 1; a++) { size_t k(0); mst[a] = j * n + arc[j]; /* join fragment j with MST */ dis[j] = -1; d = maxd; for (size_t i = 0; i < n; i++) { if (dis[i] >= 0) /* not connected yet */ { if (dis[i] > dist[i][j]) { dis[i] = dist[i][j]; arc[i] = j; } if (d > dis[i]) { d = dis[i]; k = i; } } } j = k; } //PGR_DBG("findEulerianPath: 3"); /* * Preorder Tour of MST */ #if 0 #define VISITED(x) jorder[x] #define NQ(x) arc[l++] = x #define DQ() arc[--l] #define EMPTY (l==0) #endif for (auto &val : jorder) { val = 0; } #if 0 for (i = 0; i < n; i++) VISITED(i) = 0; #endif size_t l = 0; size_t k = 0; d = 0; arc[l++] = 0; while (!(l == 0)) { size_t i = arc[--l]; if (!jorder[i]) { iorder[k++] = i; jorder[i] = 1; /* push all kids of i */ for (size_t j = 0; j < n - 1; j++) { if (i == mst[j] % n) arc[l++] = mst[j] % n; } } } #if 0 k = 0; l = 0; d = 0; NQ(0); while (!EMPTY) { i = DQ(); if (!VISITED(i)) { iorder[k++] = i; VISITED(i) = 1; for (j = 0; j < n - 1; j++) /* push all kids of i */ { if (i == mst[j]%n) NQ(mst[j]/n); } } } #endif //PGR_DBG("findEulerianPath: 4"); update(iorder); return true; }
/* List the various property slot assignments */ static void lstSlotAssignments(EjsMod *mp, EjsModule *module, EjsObj *parent, int slotNum, EjsObj *obj) { Ejs *ejs; EjsTrait *trait; EjsType *type; EjsObj *vp; EjsPot *prototype; EjsFunction *fun; EjsBlock *block; EjsName qname; int i, numInherited, count; mprAssert(obj); mprAssert(module); ejs = mp->ejs; if (VISITED(obj)) { return; } SET_VISITED(obj, 1); if (obj == ejs->global) { mprFprintf(mp->file, "\n#\n" "# Global slot assignments (Num prop %d)\n" "#\n", ejsGetLength(ejs, obj)); /* List slots for global */ for (i = module->firstGlobal; i < module->lastGlobal; i++) { trait = ejsGetPropertyTraits(ejs, ejs->global, i); qname = ejsGetPropertyName(ejs, ejs->global, i); if (qname.name == 0) { continue; } lstVarSlot(mp, module, &qname, trait, i); } /* List slots for the initializer */ fun = (EjsFunction*) module->initializer; if (fun) { mprFprintf(mp->file, "\n#\n" "# Initializer slot assignments (Num prop %d)\n" "#\n", ejsGetLength(ejs, (EjsObj*) fun)); count = ejsGetLength(ejs, (EjsObj*) fun); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, (EjsObj*) fun, i); qname = ejsGetPropertyName(ejs, (EjsObj*) fun, i); if (qname.name == 0) { continue; } mprAssert(trait); lstVarSlot(mp, module, &qname, trait, i); } } } else if (ejsIsFunction(ejs, obj)) { fun = (EjsFunction*) obj; count = ejsGetLength(ejs, (EjsObj*) obj); if (count > 0) { mprFprintf(mp->file, "\n#\n" "# Local slot assignments for the \"%@\" function (Num slots %d)\n" "#\n", fun->name, count); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, obj, i); mprAssert(trait); qname = ejsGetPropertyName(ejs, obj, i); lstVarSlot(mp, module, &qname, trait, i); } } } else if (ejsIsType(ejs, obj)) { /* Types */ type = (EjsType*) obj; mprFprintf(mp->file, "\n#\n" "# Class slot assignments for the \"%@\" class (Num slots %d)\n" "#\n", type->qname.name, ejsGetLength(ejs, (EjsObj*) type)); count = ejsGetLength(ejs, (EjsObj*) type); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, (EjsObj*) type, i); mprAssert(trait); qname = ejsGetPropertyName(ejs, obj, i); lstVarSlot(mp, module, &qname, trait, i); } prototype = type->prototype; if (type->baseType && type->baseType->prototype) { numInherited = ejsGetLength(ejs, type->baseType->prototype); } else { numInherited = 0; } mprFprintf(mp->file, "\n#\n" "# Instance slot assignments for the \"%@\" class (Num prop %d, num inherited %d)\n" "#\n", type->qname.name, prototype ? ejsGetLength(ejs, prototype): 0, numInherited); if (prototype) { count = ejsGetLength(ejs, prototype); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, prototype, i); mprAssert(trait); qname = ejsGetPropertyName(ejs, prototype, i); if (qname.name) { lstVarSlot(mp, module, &qname, trait, i); } } } } else if (ejsIsBlock(ejs, obj)) { qname = ejsGetPropertyName(ejs, parent, slotNum); block = (EjsBlock*) obj; count = ejsGetLength(ejs, (EjsObj*) block); if (count > 0) { mprFprintf(mp->file, "\n#\n" "# Block slot assignments for the \"%@\" (Num slots %d)\n" "#\n", qname.name, ejsGetLength(ejs, obj)); count = ejsGetLength(ejs, obj); for (i = 0; i < count; i++) { trait = ejsGetPropertyTraits(ejs, obj, i); mprAssert(trait); qname = ejsGetPropertyName(ejs, obj, i); lstVarSlot(mp, module, &qname, trait, i); } } } /* Now recurse on types, functions and blocks */ if (obj == ejs->global) { i = module->firstGlobal; count = module->lastGlobal; } else { i = 0; count = ejsGetLength(ejs, obj); } for (; i < count; i++) { qname = ejsGetPropertyName(ejs, obj, i); vp = ejsGetProperty(ejs, obj, i); if (vp == 0) { continue; } if (ejsIsType(ejs, vp) || ejsIsFunction(ejs, vp) || ejsIsBlock(ejs, vp)) { lstSlotAssignments(mp, module, obj, i, vp); } } SET_VISITED(obj, 0); }