85 if (
Ndim >= 3 && sscanf(p,
"%lf,%lf,%lf%c", pvec, pvec+1, pvec+2, &c) >= 3){
89 for (i = 0; i <
Ndim; i++)
98 else if (sscanf(p,
"%lf,%lf%c", pvec, pvec + 1, &c) >= 2) {
102 for (i = 0; i <
Ndim; i++)
106 if (
N_z && (p =
agxget(np,
N_z)) && sscanf(p,
"%lf",&
z) == 1) {
121 agerrorf(
"node %s, position %s, expected two doubles\n",
178 while ((c = *pos) && !
gv_isspace(c) && c !=
';')
189 lp =
agget(obj, name);
190 if (lp && sscanf(lp,
"%lf,%lf", &x, &y) == 2) {
197static cluster_data cluster_map(
graph_t *mastergraph,
graph_t *g) {
204 cluster_data
cdata = {0};
213 cdata.nclusters = nclusters;
223 c = *cs++ =
gv_calloc(*cn++,
sizeof(
int));
241 cdata.toplevel[j++] = i;
249static void freeClusterData(cluster_data c) {
250 if (c.nclusters > 0) {
253 free(c.clustersizes);
271 int sflag = 0, eflag = 0;
272 pointf sp = { 0, 0 }, ep = { 0, 0};
281 uint32_t stype, etype;
285 i = sscanf(pos,
"s,%lf,%lf%n", &x, &y, &nc);
294 i = sscanf(pos,
" e,%lf,%lf%n", &x, &y, &nc);
304 if (n < 4 || n % 3 != 1) {
315 i = sscanf(pos,
"%lf,%lf%n", &x, &y, &nc);
341 newspl->
sflag = stype;
345 newspl->
eflag = etype;
348 for (i = 0; i < npts; i++) {
392 if (!E_pos ||
Nop < 2)
433#define BS "%lf,%lf,%lf,%lf"
447 double tmp = bb.
LL.
y;
490 dfs(sg, parentg, G_lp, G_bb);
509 if (sscanf(
s,
"%lf,%lf", &x, &y) == 2) {
518 dfs(subg, g, G_lp, G_bb);
555 agerrorf(
"node %s in graph %s has no position\n",
572 if (
adjust &&
Nop == 1 && !haveBackground)
601 if (translate && !haveBackground && (
GD_bb(g).LL.x != 0||
GD_bb(g).LL.y != 0))
605 if (posEdges !=
NoEdges && (didShift || didAdjust)) {
615 return haveBackground;
632 char *p =
agget(g,
"model");
634 if (!p ||
streq(p,
""))
636 if (
streq(p,
"circuit"))
638 if (
streq(p,
"subset"))
640 if (
streq(p,
"shortpath"))
642 if (
streq(p,
"mds")) {
647 "edges in graph %s have no len attribute. Hence, the mds model\n",
agnameof(g));
648 agerr(
AGPREV,
"is inappropriate. Reverting to the shortest path model.\n");
653 "Unknown value %s for attribute \"model\" in graph %s - ignored\n",
683 "Illegal value %s for attribute \"mode\" in graph %s - ignored\n",
724 for (
size_t e = 1; e <
graph[i].nedges; e++) {
725 if (
graph[i].edists[e] == 1.0)
continue;
726 j =
graph[i].edges[e];
729 graph[i].edists[e] = x;
731 for (f = 1; f <
graph[j].nedges &&
graph[j].edges[f] != i; f++) ;
733 graph[j].edists[f] = -1.0;
750 for (i = 0; i < nv; i++) {
755 for (i = 0; i < nv; i++) {
756 if (
ND_mark(nodes[i]))
continue;
787 float *eweights =
NULL;
789 float *edists =
NULL;
795 bool haveLen =
false;
805 const size_t edges_size = (size_t)(2 * ne + nv);
806 int *edges =
gv_calloc(edges_size,
sizeof(
int));
807 if (haveLen || haveDir)
808 ewgts =
gv_calloc(edges_size,
sizeof(
float));
810 eweights =
gv_calloc(edges_size,
sizeof(
float));
813 edists =
gv_calloc(edges_size,
sizeof(
float));
821 assert(
ND_id(np) == i);
823 graph[i].edges = edges++;
824 if (haveLen || haveDir)
825 graph[i].ewgts = ewgts++;
829 graph[i].eweights = eweights++;
834 graph[i].edists = edists++;
856 *edges++ =
ND_id(vp);
865 char *
s =
agget(ep,
"dir");
869 *edists++ = np ==
aghead(ep) ? 1.0 : -1.0;
877 graph[i].nedges = i_nedges;
878 graph[i].edges[0] = i;
894 ewgts =
gv_recalloc(
graph[0].ewgts, edges_size, 2 * ne + nv,
sizeof(
float));
896 eweights =
gv_recalloc(
graph[0].eweights, edges_size, 2 * ne + nv,
sizeof(
float));
898 for (i = 0; i < nv; i++) {
899 const size_t sz =
graph[i].nedges;
900 graph[i].edges = edges;
903 graph[i].ewgts = ewgts;
907 graph[i].eweights = eweights;
939#define SLEN(s) (sizeof(s)-1)
941#define REGULAR "regular"
942#define RANDOM "random"
956 char *p =
agget(
G,
"start");
959 if (!p || *p ==
'\0')
return dflt;
984 seed = (unsigned) getpid() ^ (unsigned) time(
NULL);
1000#define exp_name "stresswt"
1005 if (exp == 0 || exp > 2) {
1030 agwarningf(
"node positions are ignored unless start=random\n");
1043 fprintf(stderr,
"#nodes %d #edges %d\n", nv, ne);
1047 for (i = 0; i < nv; i++) {
1048 const size_t n = gp[i].
nedges;
1049 fprintf(stderr,
"[%d] %" PRISIZE_T "\n", i, n);
1050 for (
size_t j = 0; j < n; j++) {
1051 fprintf(stderr,
" %3d", gp[i].edges[j]);
1053 fputs(
"\n", stderr);
1055 fputs(
" ewgts", stderr);
1056 for (
size_t j = 0; j < n; j++) {
1057 fprintf(stderr,
" %3f", gp[i].ewgts[j]);
1059 fputs(
"\n", stderr);
1061 if (gp[i].eweights) {
1062 fputs(
" eweights", stderr);
1063 for (
size_t j = 0; j < n; j++) {
1064 fprintf(stderr,
" %3f", gp[i].eweights[j]);
1066 fputs(
"\n", stderr);
1069 fputs(
" edists", stderr);
1070 for (
size_t j = 0; j < n; j++) {
1071 fprintf(stderr,
" %3f", gp[i].edists[j]);
1073 fputs(
"\n", stderr);
1075 fputs(
"\n", stderr);
1079void dumpClusterData (cluster_data* dp)
1083 fprintf (stderr,
"nvars %d nclusters %d ntoplevel %d\n", dp->nvars, dp->nclusters, dp->ntoplevel);
1084 fprintf (stderr,
"Clusters:\n");
1085 for (i = 0; i < dp->nclusters; i++) {
1086 sz = dp->clustersizes[i];
1087 fprintf (stderr,
" [%d] %d vars\n", i, sz);
1088 for (j = 0; j < sz; j++)
1089 fprintf (stderr,
" %d", dp->clusters[i][j]);
1090 fprintf (stderr,
"\n");
1094 fprintf (stderr,
"Toplevel:\n");
1095 for (i = 0; i < dp->ntoplevel; i++)
1096 fprintf (stderr,
" %d\n", dp->toplevel[i]);
1098 fprintf (stderr,
"Boxes:\n");
1099 for (i = 0; i < dp->nclusters; i++) {
1100 boxf bb = dp->bb[i];
1101 fprintf (stderr,
" (%f,%f) (%f,%f)\n", bb.
LL.
x, bb.
LL.
y, bb.
UR.
x, bb.
UR.
y);
1104void dumpOpts (ipsep_options* opp,
int nv)
1108 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);
1109 for (i = 0; i < nv; i++)
1110 fprintf (stderr,
" (%f,%f)\n", opp->nsize[i].x, opp->nsize[i].y);
1112 dumpClusterData (opp->clusters);
1143 for (
int i = 1; i <
Ndim; i++) {
1144 coords[i] = coords[0] + i * nv;
1147 fprintf(stderr,
"model %d smart_init %d stresswt %d iterations %d tol %f\n",
1149 fprintf(stderr,
"convert graph: ");
1151 fprintf(stderr,
"majorization\n");
1156 fprintf(stderr,
"%d nodes %.2f sec\n", nv,
elapsed_sec());
1163 rv = stress_majorization_with_hierarchy(gp, nv, coords, nodes,
Ndim,
1170 cluster_data cs = cluster_map(mg,g);
1172 opt.edge_gap = lgap;
1175 str =
agget(g,
"diredgeconstraints");
1179 fprintf(stderr,
"Generating Edge Constraints...\n");
1180 }
else if (
str && !strncasecmp(
str,
"hier",4)) {
1183 fprintf(stderr,
"Generating DiG-CoLa Edge Constraints...\n");
1185 else opt.diredges = 0;
1189 fprintf(stderr,
"Generating Non-overlap Constraints...\n");
1193 fprintf(stderr,
"Removing overlaps as postprocess...\n");
1195 else opt.noverlap = 0;
1204 fprintf(stderr,
"gap=%f,%f\n",opt.gap.x,opt.gap.y);
1214 fprintf (stderr,
"nv %d ne %d Ndim %d model %d MaxIter %d\n", nv, ne,
Ndim, model,
MaxIter);
1215 fprintf (stderr,
"Nodes:\n");
1216 for (
int i = 0; i < nv; i++) {
1217 fprintf (stderr,
" %s (%f,%f)\n", nodes[i]->name, coords[0][i], coords[1][i]);
1219 fprintf (stderr,
"\n");
1220 dumpData(g, gp, nv, ne);
1221 fprintf (stderr,
"\n");
1222 dumpOpts (&opt, nv);
1224 rv = stress_majorization_cola(gp, nv, coords, nodes,
Ndim, model,
MaxIter, &opt);
1225 freeClusterData(cs);
1239 for (
int i = 0; i <
Ndim; i++) {
1240 ND_pos(v)[i] = coords[i][idx];
1256 for (i = 0; i < nG; i++) {
1257 for (j = 0; j < nG; j++) {
1297 "graph %s is disconnected. Hence, the circuit model\n",
1300 "is undefined. Reverting to the shortest path model.\n");
1302 "Alternatively, consider running neato using -Gpack=true or decomposing\n");
1303 agerr(
AGPREV,
"the graph into connected components.\n");
1314 fprintf(stderr,
"Solving model %d iterations %d tol %f\n",
1346 sgd(g, layoutModel);
1429 if (
Pack < 0 && layoutMode)
1432 }
else if (
Pack < 0)
1444 for (
size_t i = 0; i < n_cc; i++) {
1474 for (
size_t i = 0; i < n_cc; i++) {
expand_t sepFactor(graph_t *g)
int adjustNodes(graph_t *G)
void graphAdjustMode(graph_t *G, adjust_data *dp, char *dflt)
int removeOverlapWith(graph_t *G, adjust_data *am)
static void agxbfree(agxbuf *xb)
free any malloced resources
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static WUR char * agxbuse(agxbuf *xb)
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
static void * gv_calloc(size_t nmemb, size_t size)
void arrow_flags(Agedge_t *e, uint32_t *sflag, uint32_t *eflag)
API for compacted arrays of booleans.
static bitarray_t bitarray_new(size_t size_bits)
create an array of the given element length
static bool bitarray_get(bitarray_t self, size_t index)
get the value of the given element
static void bitarray_set(bitarray_t *self, size_t index, bool value)
set or clear the value of the given element
static void bitarray_reset(bitarray_t *self)
free underlying resources and leave a bit array empty
abstract graph C library, Cgraph API
int circuit_model(graph_t *g, int nG)
bool mapbool(const char *p)
void setEdgeType(graph_t *g, int defaultValue)
int late_int(void *obj, attrsym_t *attr, int defaultValue, int minimum)
void common_init_node(node_t *n)
double late_double(void *obj, attrsym_t *attr, double defaultValue, double minimum)
void common_init_edge(edge_t *e)
double get_inputscale(graph_t *g)
void compute_bb(graph_t *g)
void gv_nodesize(node_t *n, bool flip)
bool is_a_cluster(Agraph_t *g)
void freeGraphData(vtx_data *graph)
static void init(int argc, char *argv[], double *angle, double *accuracy, int *check_edges_with_same_endpoint, int *seed, const char **color_scheme, int *lightness)
static const char adjust[]
#define PS2INCH(a_points)
static int cnt(Dict_t *d, Dtlink_t **set)
int agnedges(Agraph_t *g)
int agnnodes(Agraph_t *g)
size_t graphviz_node_induce(Agraph_t *g, Agraph_t *edgeset)
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
int agset(void *obj, char *name, const char *value)
int agxset(void *obj, Agsym_t *sym, const char *value)
char * agget(void *obj, char *name)
char * agxget(void *obj, Agsym_t *sym)
#define agfindedgeattr(g, a)
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
void agwarningf(const char *fmt,...)
void agerrorf(const char *fmt,...)
int agerr(agerrlevel_t level, const char *fmt,...)
#define agfindgraphattr(g, a)
#define GD_neato_nlist(g)
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
#define agfindnodeattr(g, a)
Agraph_t * agraphof(void *obj)
char * agnameof(void *)
returns a string descriptor for the object.
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
Agraph_t * agroot(void *obj)
void * agbindrec(void *obj, const char *name, unsigned int recsize, int move_to_front)
attaches a new record of the given size to the object
int agdelrec(void *obj, const char *name)
deletes a named record from one object
Agraph_t * agfstsubg(Agraph_t *g)
Agraph_t * agnxtsubg(Agraph_t *subg)
Agraph_t * graph(char *name)
replacements for ctype.h functions
static bool gv_isdigit(int c)
static bool gv_isalpha(int c)
static bool gv_isspace(int c)
textitem scanner parser str
DistType ** compute_apsp_artificial_weights(vtx_data *graph, int n)
void free_label(textlabel_t *p)
Agraph_t ** pccomps(Agraph_t *g, size_t *ncc, char *pfx, bool *pinned)
std::unordered_map< std::pair< int, int >, int, PointHash > PointMap
static void add_cluster(Agraph_t *g, Agraph_t *subg)
static void kkNeato(Agraph_t *g, int nG, int model)
static void neato_init_graph(Agraph_t *g)
bool user_pos(attrsym_t *posptr, attrsym_t *pinptr, node_t *np, int nG)
static vtx_data * makeGraphData(graph_t *g, int nv, int *nedges, int mode, int model, node_t ***nodedata)
static int checkEdge(PointMap *pm, edge_t *ep, int idx)
static int numFields(const char *pos)
int init_nop(Agraph_t *g, int adjust)
static void neato_init_edge(edge_t *e)
static void majorization(graph_t *mg, graph_t *g, int nv, int mode, int model, int dim, adjust_data *am)
static void initRegular(graph_t *G, int nG)
static void mds_model(graph_t *g)
static void neatoLayout(Agraph_t *mg, Agraph_t *g, int layoutMode, int layoutModel, adjust_data *am)
static void neato_cleanup_graph(graph_t *g)
static void dfs(Agraph_t *subg, Agraph_t *parentg, attrsym_t *G_lp, attrsym_t *G_bb)
static pos_edge nop_init_edges(Agraph_t *g)
static void nop_init_graphs(Agraph_t *, attrsym_t *, attrsym_t *)
static int neatoModel(graph_t *g)
static void freeEdgeInfo(Agraph_t *g)
void neato_cleanup(graph_t *g)
static int checkExp(graph_t *G)
int checkStart(graph_t *G, int nG, int dflt)
static void set_label(void *obj, textlabel_t *l, char *name)
void neato_layout(Agraph_t *g)
int setSeed(graph_t *G, int dflt, long *seedp)
static int user_spline(attrsym_t *E_pos, edge_t *e)
static int chkBB(Agraph_t *g, attrsym_t *G_bb, boxf *bbp)
static int neatoMode(graph_t *g)
static void addZ(Agraph_t *g)
void neato_init_node(node_t *n)
static void subset_model(Agraph_t *G, int nG)
static void neato_init_node_edge(graph_t *g)
NEATOPROCS_API void spline_edges(Agraph_t *)
NEATOPROCS_API void neato_translate(Agraph_t *g)
NEATOPROCS_API void spline_edges0(Agraph_t *, bool)
NEATOPROCS_API void free_scan_graph(graph_t *)
NEATOPROCS_API void solve_model(graph_t *, int)
NEATOPROCS_API void initial_positions(graph_t *, int)
NEATOPROCS_API void jitter_d(Agnode_t *, int, int)
NEATOPROCS_API void diffeq_model(graph_t *, int)
NEATOPROCS_API bool neato_set_aspect(graph_t *g)
NEATOPROCS_API void jitter3d(Agnode_t *, int)
NEATOPROCS_API int scan_graph(graph_t *)
NEATOPROCS_API void shortest_path(graph_t *, int)
NEATOPROCS_API int scan_graph_mode(graph_t *G, int mode)
pack_mode getPackModeInfo(Agraph_t *g, pack_mode dflt, pack_info *pinfo)
int getPack(Agraph_t *g, int not_def, int dflt)
int packGraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
support for connected components
void clearPM(PointMap *ps)
int insertPM(PointMap *pm, int x, int y, int value)
void freePM(PointMap *ps)
point containers PointSet and PointMap
void gv_postprocess(Agraph_t *g, int allowTranslation)
#define PRISIZE_T
PRIu64 alike for printing size_t
bezier * new_spline(edge_t *e, size_t sz)
void gv_cleanup_edge(Agedge_t *e)
void gv_free_splines(edge_t *e)
void gv_cleanup_node(Agnode_t *n)
static int nedges
total no. of edges used in routing
void sgd(graph_t *G, int model)
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
platform abstraction for case-insensitive string functions
static bool streq(const char *a, const char *b)
are a and b equal?
int stress_majorization_kD_mkernel(vtx_data *graph, int n, double **d_coords, node_t **nodes, int dim, int opts, int model, int maxi)
Agraph_t * root
subgraphs - ancestors
bool doSplines
use splines in constructing graph shape