40 static char *cc_pfx =
"_neato_cc";
50 static void neato_init_edge(
edge_t * e)
70 (sscanf(p,
"%lf,%lf,%lf%c", pvec, pvec+1, pvec+2, &c) >= 3)){
74 for (i = 0; i <
Ndim; i++)
83 else if (sscanf(p,
"%lf,%lf%c", pvec, pvec + 1, &c) >= 2) {
87 for (i = 0; i <
Ndim; i++)
91 if (
N_z && (p =
agxget(np,
N_z)) && (sscanf(p,
"%lf",&z) == 1)) {
106 agerr(
AGERR,
"node %s, position %s, expected two doubles\n",
112 static void neato_init_node_edge(
graph_t * g)
132 static void neato_cleanup_graph(
graph_t * g)
134 if (
Nop || (Pack < 0)) {
153 neato_cleanup_graph(g);
156 static int numFields(
unsigned char *pos)
162 while (isspace(*pos))
166 while ((c = *pos) && !isspace(c) && (c !=
';'))
169 }
while (isspace(c));
173 static void set_label(
void* obj,
textlabel_t * l,
char *name)
177 lp =
agget(obj, name);
178 if (lp && (sscanf(lp,
"%lf,%lf", &x, &y) == 2)) {
179 l->
pos = pointfof(x, y);
185 static cluster_data* cluster_map(
graph_t *mastergraph,
graph_t *g)
193 cluster_data *
cdata =
GNEW(cluster_data);
197 if (!strncmp(
agnameof(subg),
"cluster", 7)) {
202 cdata->nclusters = nclusters;
203 cs = cdata->clusters =
N_GNEW(nclusters,
int*);
204 cn = cdata->clustersizes =
N_GNEW(nclusters,
int);
207 if (!strncmp(
agnameof(subg),
"cluster", 7)) {
212 c = *cs++ =
N_GNEW(*cn++,
int);
229 cdata->toplevel=
N_GNEW(cdata->ntoplevel,
int);
232 cdata->toplevel[j++]=i;
240 static void freeClusterData(cluster_data *c) {
242 free(c->clusters[0]);
244 free(c->clustersizes);
264 int sflag = 0, eflag = 0;
265 pointf sp = { 0, 0 }, ep = { 0, 0};
269 static boolean warned;
278 i = sscanf(pos,
"s,%lf,%lf%n", &x, &y, &nc);
287 i = sscanf(pos,
" e,%lf,%lf%n", &x, &y, &nc);
295 npts = numFields((
unsigned char *) pos);
297 if ((n < 4) || (n % 3 != 1)) {
308 i = sscanf(pos,
"%lf,%lf%n", &x, &y, &nc);
324 while (isspace(*pos)) pos++;
333 newspl->
sflag = stype;
337 newspl->
eflag = etype;
340 for (i = 0; i < npts; i++) {
341 newspl->
list[i] = ps[i];
384 if (!E_pos || (
Nop < 2))
389 if (user_spline(E_pos, e)) {
405 static void freeEdgeInfo (
Agraph_t * g)
425 #define BS "%lf,%lf,%lf,%lf"
439 double tmp = bb.
LL.
y;
473 if (!strncmp(
agnameof(subg),
"cluster", 7) && chkBB(subg, G_bb, &bb)) {
476 add_cluster(parentg, subg);
477 nop_init_graphs(subg, G_lp, G_bb);
481 dfs(sg, parentg, G_lp, G_bb);
500 if (sscanf(s,
"%lf,%lf", &x, &y) == 2) {
509 dfs(subg, g, G_lp, G_bb);
546 agerr(
AGERR,
"node %s in graph %s has no position\n",
553 nop_init_graphs(g, G_lp, G_bb);
554 posEdges = nop_init_edges(g);
563 if (adjust && (
Nop == 1) && !haveBackground)
592 if (translate && !haveBackground && ((
GD_bb(g).LL.x != 0)||(
GD_bb(g).LL.y != 0)))
596 if ((posEdges !=
NoEdges) && (didShift || didAdjust)) {
606 return haveBackground;
609 static void neato_init_graph (
Agraph_t * g)
618 neato_init_node_edge(g);
621 static int neatoModel(
graph_t * g)
623 char *p =
agget(g,
"model");
626 if (!p || (!(c = *p)))
628 if ((c ==
'c') &&
streq(p,
"circuit"))
631 if (
streq(p,
"subset"))
633 else if (
streq(p,
"shortpath"))
636 if ((c ==
'm') &&
streq(p,
"mds")) {
641 "edges in graph %s have no len attribute. Hence, the mds model\n",
agnameof(g));
642 agerr(
AGPREV,
"is inappropriate. Reverting to the shortest path model.\n");
647 "Unknown value %s for attribute \"model\" in graph %s - ignored\n",
654 static int neatoMode(
graph_t * g)
659 str =
agget(g,
"mode");
661 if (
streq(str,
"KK"))
663 else if (
streq(str,
"major"))
666 else if (
streq(str,
"hier"))
669 else if (
streq(str,
"ipsep"))
675 "Illegal value %s for attribute \"mode\" in graph %s - ignored\n",
716 for (e = 1; e < graph[i].
nedges; e++) {
717 if (graph[i].edists[e] == 1.0)
continue;
718 j = graph[i].
edges[e];
721 graph[i].edists[e] = x;
722 for (f = 1; (f < graph[j].
nedges) &&(graph[j].edges[f] != i); f++) ;
723 assert (f < graph[j].nedges);
724 graph[j].edists[f] = -1.0;
726 else if (
ND_mark(hp) ==
FALSE) dfsCycle(graph, j, mode, nodes);
741 for (i = 0; i < nv; i++) {
746 for (i = 0; i < nv; i++) {
747 if (
ND_mark(nodes[i]))
continue;
748 dfsCycle (graph, i, mode, nodes);
781 float *eweights =
NULL;
783 float *edists =
NULL;
789 int i, i_nedges, idx;
806 edges =
N_GNEW(2 * ne + nv,
int);
807 if (haveLen || haveDir)
808 ewgts =
N_GNEW(2 * ne + nv,
float);
810 eweights =
N_GNEW(2 * ne + nv,
float);
813 edists =
N_GNEW(2*ne+nv,
float);
823 graph[i].
edges = edges++;
824 if (haveLen || haveDir)
825 graph[i].
ewgts = ewgts++;
834 graph[i].edists = edists++;
837 graph[i].edists =
NULL;
844 idx = checkEdge(ps, ep, j);
849 int curlen = graph[i].
ewgts[idx];
857 *edges++ =
ND_id(vp);
866 char *s =
agget(ep,
"dir");
867 if(s&&!strncmp(s,
"none",4)) {
870 *edists++ = (np ==
aghead(ep) ? 1.0 : -1.0);
878 graph[i].
nedges = i_nedges;
879 graph[i].
edges[0] = i;
881 graph[i].styles =
NULL;
888 acyclic (graph, nv, mode, nodes);
896 edges =
RALLOC(2 * ne + nv, graph[0].edges,
int);
898 ewgts =
RALLOC(2 * ne + nv, graph[0].ewgts,
float);
900 eweights =
RALLOC(2 * ne + nv, graph[0].eweights,
float);
902 for (i = 0; i < nv; i++) {
904 graph[i].
edges = edges;
907 graph[i].
ewgts = ewgts;
926 static void initRegular(
graph_t * G,
int nG)
932 da = (2 *
M_PI) / nG;
943 #define SLEN(s) (sizeof(s)-1)
945 #define REGULAR "regular"
946 #define RANDOM "random"
961 char *p =
agget(G,
"start");
964 if (!p || (*p ==
'\0'))
return dflt;
965 if (isalpha(*(
unsigned char *)p)) {
978 else if (isdigit(*(
unsigned char *)p)) {
985 if (!isdigit(*(
unsigned char *)p) || sscanf(p,
"%ld", &seed) < 1) {
987 seed = (unsigned) time(
NULL);
989 seed = (unsigned) getpid() ^ (unsigned) time(
NULL);
991 sprintf(smallbuf,
"%ld", seed);
992 agset(G,
"start", smallbuf);
1003 #define exp_name "stresswt"
1005 static int checkExp (
graph_t * G)
1008 if ((exp == 0) || (exp > 2)) {
1031 init =
setSeed (G, dflt, &seed);
1033 agerr(
AGWARN,
"node positions are ignored unless start=random\n");
1046 fprintf(stderr,
"#nodes %d #edges %d\n", nv, ne);
1050 for (i = 0; i < nv; i++) {
1052 fprintf(stderr,
"[%d] %d\n", i, n);
1053 for (j = 0; j < n; j++) {
1054 fprintf(stderr,
" %3d", gp[i].edges[j]);
1056 fputs(
"\n", stderr);
1058 fputs(
" ewgts", stderr);
1059 for (j = 0; j < n; j++) {
1060 fprintf(stderr,
" %3f", gp[i].ewgts[j]);
1062 fputs(
"\n", stderr);
1064 if (gp[i].eweights) {
1065 fputs(
" eweights", stderr);
1066 for (j = 0; j < n; j++) {
1067 fprintf(stderr,
" %3f", gp[i].eweights[j]);
1069 fputs(
"\n", stderr);
1072 fputs(
" edists", stderr);
1073 for (j = 0; j < n; j++) {
1074 fprintf(stderr,
" %3f", gp[i].edists[j]);
1076 fputs(
"\n", stderr);
1078 fputs(
"\n", stderr);
1082 void dumpClusterData (cluster_data* dp)
1086 fprintf (stderr,
"nvars %d nclusters %d ntoplevel %d\n", dp->nvars, dp->nclusters, dp->ntoplevel);
1087 fprintf (stderr,
"Clusters:\n");
1088 for (i = 0; i < dp->nclusters; i++) {
1089 sz = dp->clustersizes[i];
1090 fprintf (stderr,
" [%d] %d vars\n", i, sz);
1091 for (j = 0; j < sz; j++)
1092 fprintf (stderr,
" %d", dp->clusters[i][j]);
1093 fprintf (stderr,
"\n");
1097 fprintf (stderr,
"Toplevel:\n");
1098 for (i = 0; i < dp->ntoplevel; i++)
1099 fprintf (stderr,
" %d\n", dp->toplevel[i]);
1101 fprintf (stderr,
"Boxes:\n");
1102 for (i = 0; i < dp->nclusters; i++) {
1103 boxf bb = dp->bb[i];
1104 fprintf (stderr,
" (%f,%f) (%f,%f)\n", bb.
LL.
x, bb.
LL.
y, bb.
UR.
x, bb.
UR.
y);
1107 void dumpOpts (ipsep_options* opp,
int nv)
1111 fprintf (stderr,
"diredges %d edge_gap %f noverlap %d gap (%f,%f)\n", opp->diredges, opp->edge_gap, opp->noverlap, opp->gap.x, opp->gap.y);
1112 for (i = 0; i < nv; i++)
1113 fprintf (stderr,
" (%f,%f)\n", opp->nsize[i].x, opp->nsize[i].y);
1115 dumpClusterData (opp->clusters);
1140 int opts = checkExp (g);
1145 coords =
N_GNEW(dim,
double *);
1146 coords[0] =
N_GNEW(nv * dim,
double);
1147 for (i = 1; i <
Ndim; i++) {
1148 coords[i] = coords[0] + i * nv;
1151 fprintf(stderr,
"model %d smart_init %d stresswt %d iterations %d tol %f\n",
1153 fprintf(stderr,
"convert graph: ");
1155 fprintf(stderr,
"majorization\n");
1158 gp = makeGraphData(g, nv, &ne, mode, model, &nodes);
1161 fprintf(stderr,
"%d nodes %.2f sec\n", nv,
elapsed_sec());
1168 rv = stress_majorization_with_hierarchy(gp, nv, ne, coords, nodes, Ndim,
1176 cluster_data *cs = (cluster_data*)cluster_map(mg,g);
1178 opt.edge_gap = lgap;
1184 str =
agget(g,
"diredgeconstraints");
1188 fprintf(stderr,
"Generating Edge Constraints...\n");
1192 fprintf(stderr,
"Generating DiG-CoLa Edge Constraints...\n");
1194 else opt.diredges = 0;
1198 fprintf(stderr,
"Generating Non-overlap Constraints...\n");
1202 fprintf(stderr,
"Removing overlaps as postprocess...\n");
1204 else opt.noverlap = 0;
1206 str =
agget(g,
"mosek");
1207 if(str && !strncmp(str,
"true",4)) {
1210 fprintf(stderr,
"Using Mosek for constraint optimization...\n");
1221 fprintf(stderr,
"gap=%f,%f\n",opt.gap.x,opt.gap.y);
1228 fprintf (stderr,
"nv %d ne %d Ndim %d model %d MaxIter %d\n", nv, ne, Ndim, model,
MaxIter);
1229 fprintf (stderr,
"Nodes:\n");
1230 for (i = 0; i < nv; i++) {
1231 fprintf (stderr,
" %s (%f,%f)\n", nodes[i]->name, coords[0][i], coords[1][i]);
1233 fprintf (stderr,
"\n");
1234 dumpData(g, gp, nv, ne);
1235 fprintf (stderr,
"\n");
1236 dumpOpts (&opt, nv);
1238 rv = stress_majorization_cola(gp, nv, ne, coords, nodes, Ndim, model,
MaxIter, &opt);
1239 freeClusterData(cs);
1254 for (i = 0; i <
Ndim; i++) {
1255 ND_pos(v)[i] = coords[i][idx];
1264 static void subset_model(
Agraph_t * G,
int nG)
1272 for (i = 0; i < nG; i++) {
1273 for (j = 0; j < nG; j++) {
1286 static void mds_model(
graph_t * g,
int nG)
1306 static void kkNeato(
Agraph_t * g,
int nG,
int model)
1309 subset_model(g, nG);
1313 "graph %s is disconnected. Hence, the circuit model\n",
1316 "is undefined. Reverting to the shortest path model.\n");
1318 "Alternatively, consider running neato using -Gpack=true or decomposing\n");
1319 agerr(
AGPREV,
"the graph into connected components.\n");
1330 fprintf(stderr,
"Solving model %d iterations %d tol %f\n",
1347 if ((str =
agget(g,
"maxiter")))
1355 if ((nG < 2) || (
MaxIter < 0))
1358 majorization(mg, g, nG, layoutMode, layoutModel, Ndim,
MaxIter, am);
1360 kkNeato(g, nG, layoutModel);
1372 if ((Ndim >= 3) &&
N_z) {
1386 if (!strncmp(
agnameof(subg),
"cluster", 7)) {
1388 add_cluster(g, subg);
1419 neato_init_graph(g);
1430 neato_init_graph(g);
1431 layoutMode = neatoMode(g);
1433 model = neatoModel(g);
1441 if ((Pack < 0) && layoutMode)
1444 }
else if (Pack < 0)
1453 cc =
pccomps(g, &n_cc, cc_pfx, &pin);
1457 for (i = 0; i < n_cc; i++) {
1460 neatoLayout(g, gc, layoutMode, model, &am);
1463 if (noTranslate) doEdges(gc);
1467 bp =
N_NEW(n_cc,
boolean);
1479 neatoLayout(g, g, layoutMode, model, &am);
1481 if (noTranslate) doEdges(g);
1488 for (i = 0; i < n_cc; i++) {
1499 neatoLayout(g, g, layoutMode, model, &am);
1502 if (noTranslate) doEdges(g);
int init_nop(Agraph_t *g, int adjust)
CGRAPH_API void agclean(Agraph_t *g, int kind, char *rec_name)
void free_label(textlabel_t *p)
bezier * new_spline(edge_t *e, int sz)
#define RALLOC(size, ptr, type)
DistType ** compute_apsp_artifical_weights(vtx_data *graph, int n)
void shortest_path(graph_t *, int)
Agsym_t * agattr(Agraph_t *g, int kind, char *name, char *value)
void neato_layout(Agraph_t *g)
void initial_positions(graph_t *, int)
expand_t sepFactor(graph_t *g)
int nodeInduce(Agraph_t *g)
int scan_graph(graph_t *)
int agxset(void *obj, Agsym_t *sym, char *value)
#define ALLOC(size, ptr, type)
void jitter3d(Agnode_t *, int)
void neato_cleanup(graph_t *g)
int scan_graph_mode(graph_t *G, int mode)
void gv_postprocess(Agraph_t *g, int allowTranslation)
void common_init_node(node_t *n)
CGRAPH_API Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
CGRAPH_API int agdelete(Agraph_t *g, void *obj)
Agraph_t ** pccomps(Agraph_t *g, int *ncc, char *pfx, boolean *pinned)
int agerr(agerrlevel_t level, const char *fmt,...)
void gv_cleanup_edge(Agedge_t *e)
void arrow_flags(Agedge_t *e, int *sflag, int *eflag)
CGRAPH_API Agraph_t * agfstsubg(Agraph_t *g)
int insertPM(PointMap *pm, int x, int y, int v)
int packGraphs(int ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
CGRAPH_API Agraph_t * agroot(void *obj)
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
#define ZALLOC(size, ptr, type, osize)
#define PS2INCH(a_points)
char * agget(void *obj, char *name)
CGRAPH_API Agraph_t * agraphof(void *obj)
CGRAPH_API Agraph_t * agnxtsubg(Agraph_t *subg)
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
void spline_edges0(Agraph_t *, boolean)
int user_pos(attrsym_t *posptr, attrsym_t *pinptr, node_t *np, int nG)
int agset(void *obj, char *name, char *value)
CGRAPH_API Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
adjust_data * graphAdjustMode(graph_t *G, adjust_data *dp, char *dflt)
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
pack_mode getPackModeInfo(Agraph_t *g, pack_mode dflt, pack_info *pinfo)
int strncasecmp(const char *s1, const char *s2, unsigned int n)
CGRAPH_API char * agnameof(void *)
void spline_edges(Agraph_t *)
void free_scan_graph(graph_t *)
void solve_model(graph_t *, int)
#define agfindedgeattr(g, a)
int stress_majorization_kD_mkernel(vtx_data *graph, int n, int nedges_graph, double **d_coords, node_t **nodes, int dim, int opts, int model, int maxi)
void compute_bb(graph_t *g)
int adjustNodes(graph_t *G)
int removeOverlapWith(graph_t *G, adjust_data *am)
void clearPM(PointMap *ps)
boolean mapBool(char *p, boolean dflt)
CGRAPH_API Agnode_t * agfstnode(Agraph_t *g)
int late_int(void *obj, attrsym_t *attr, int def, int low)
Agraph_t * graph(char *name)
double get_inputscale(graph_t *g)
void gv_free_splines(edge_t *e)
CGRAPH_API Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
CGRAPH_API int agdelrec(void *obj, char *name)
#define agfindgraphattr(g, a)
EXTERN Agsym_t * E_weight
void freePM(PointMap *ps)
double late_double(void *obj, attrsym_t *attr, double def, double low)
int getPack(Agraph_t *g, int not_def, int dflt)
EXTERN unsigned char Verbose
void gv_cleanup_node(Agnode_t *n)
CGRAPH_API int agnnodes(Agraph_t *g)
void freeGraphData(vtx_data *graph)
int setSeed(graph_t *G, int dflt, long *seedp)
int circuit_model(graph_t *g, int nG)
void neato_translate(Agraph_t *g)
CGRAPH_API void * agbindrec(void *obj, char *name, unsigned int size, int move_to_front)
int common_init_edge(edge_t *e)
void setEdgeType(graph_t *g, int dflt)
void neato_init_node(node_t *n)
void gv_nodesize(node_t *n, boolean flip)
CGRAPH_API int agnedges(Agraph_t *g)
int checkStart(graph_t *G, int nG, int dflt)
EXTERN double PSinputscale
char * agxget(void *obj, Agsym_t *sym)
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
void diffeq_model(graph_t *, int)
#define agfindnodeattr(g, a)
void jitter_d(Agnode_t *, int, int)
#define GD_neato_nlist(g)
boolean neato_set_aspect(graph_t *g)