graphkit-js 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/README.md +93 -0
- package/dist/graphlib.core.js +1238 -0
- package/dist/graphlib.core.min.js +143 -0
- package/dist/graphlib.js +6905 -0
- package/dist/graphlib.min.js +2522 -0
- package/index.js +38 -0
- package/lib/alg/components.js +27 -0
- package/lib/alg/dfs.js +42 -0
- package/lib/alg/dijkstra-all.js +10 -0
- package/lib/alg/dijkstra.js +54 -0
- package/lib/alg/find-cycles.js +10 -0
- package/lib/alg/floyd-warshall.js +50 -0
- package/lib/alg/index.js +13 -0
- package/lib/alg/is-acyclic.js +15 -0
- package/lib/alg/postorder.js +7 -0
- package/lib/alg/preorder.js +7 -0
- package/lib/alg/prim.js +52 -0
- package/lib/alg/tarjan.js +47 -0
- package/lib/alg/topsort.js +35 -0
- package/lib/data/priority-queue.js +152 -0
- package/lib/graph.js +558 -0
- package/lib/index.js +5 -0
- package/lib/json.js +66 -0
- package/lib/lodash.js +34 -0
- package/lib/version.js +1 -0
- package/package.json +53 -0
package/lib/graph.js
ADDED
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _ = require("./lodash");
|
|
4
|
+
|
|
5
|
+
module.exports = Graph;
|
|
6
|
+
|
|
7
|
+
var DEFAULT_EDGE_NAME = "\x00";
|
|
8
|
+
var GRAPH_NODE = "\x00";
|
|
9
|
+
var EDGE_KEY_DELIM = "\x01";
|
|
10
|
+
|
|
11
|
+
// Implementation notes:
|
|
12
|
+
//
|
|
13
|
+
// * Node id query functions should return string ids for the nodes
|
|
14
|
+
// * Edge id query functions should return an "edgeObj", edge object, that is
|
|
15
|
+
// composed of enough information to uniquely identify an edge: {v, w, name}.
|
|
16
|
+
// * Internally we use an "edgeId", a stringified form of the edgeObj, to
|
|
17
|
+
// reference edges. This is because we need a performant way to look these
|
|
18
|
+
// edges up and, object properties, which have string keys, are the closest
|
|
19
|
+
// we're going to get to a performant hashtable in JavaScript.
|
|
20
|
+
|
|
21
|
+
function Graph(opts) {
|
|
22
|
+
this._isDirected = _.has(opts, "directed") ? opts.directed : true;
|
|
23
|
+
this._isMultigraph = _.has(opts, "multigraph") ? opts.multigraph : false;
|
|
24
|
+
this._isCompound = _.has(opts, "compound") ? opts.compound : false;
|
|
25
|
+
|
|
26
|
+
// Label for the graph itself
|
|
27
|
+
this._label = undefined;
|
|
28
|
+
|
|
29
|
+
// Defaults to be set when creating a new node
|
|
30
|
+
this._defaultNodeLabelFn = _.constant(undefined);
|
|
31
|
+
|
|
32
|
+
// Defaults to be set when creating a new edge
|
|
33
|
+
this._defaultEdgeLabelFn = _.constant(undefined);
|
|
34
|
+
|
|
35
|
+
// v -> label
|
|
36
|
+
this._nodes = {};
|
|
37
|
+
|
|
38
|
+
if (this._isCompound) {
|
|
39
|
+
// v -> parent
|
|
40
|
+
this._parent = {};
|
|
41
|
+
|
|
42
|
+
// v -> children
|
|
43
|
+
this._children = {};
|
|
44
|
+
this._children[GRAPH_NODE] = {};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// v -> edgeObj
|
|
48
|
+
this._in = {};
|
|
49
|
+
|
|
50
|
+
// u -> v -> Number
|
|
51
|
+
this._preds = {};
|
|
52
|
+
|
|
53
|
+
// v -> edgeObj
|
|
54
|
+
this._out = {};
|
|
55
|
+
|
|
56
|
+
// v -> w -> Number
|
|
57
|
+
this._sucs = {};
|
|
58
|
+
|
|
59
|
+
// e -> edgeObj
|
|
60
|
+
this._edgeObjs = {};
|
|
61
|
+
|
|
62
|
+
// e -> label
|
|
63
|
+
this._edgeLabels = {};
|
|
64
|
+
|
|
65
|
+
this._errerMsg =
|
|
66
|
+
"Could not load the graph module. Please make sure Node.js version is compatable.";
|
|
67
|
+
|
|
68
|
+
if (process.env.CODESANDBOX_HOST) {
|
|
69
|
+
throw new Error(this._errerMsg);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Number of nodes in the graph. Should only be changed by the implementation. */
|
|
74
|
+
Graph.prototype._nodeCount = 0;
|
|
75
|
+
|
|
76
|
+
/* Number of edges in the graph. Should only be changed by the implementation. */
|
|
77
|
+
Graph.prototype._edgeCount = 0;
|
|
78
|
+
|
|
79
|
+
/* === Graph functions ========= */
|
|
80
|
+
|
|
81
|
+
Graph.prototype.isDirected = function () {
|
|
82
|
+
return this._isDirected;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
Graph.prototype.isMultigraph = function () {
|
|
86
|
+
return this._isMultigraph;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
Graph.prototype.isCompound = function () {
|
|
90
|
+
return this._isCompound;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
Graph.prototype.setGraph = function (label) {
|
|
94
|
+
this._label = label;
|
|
95
|
+
return this;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
Graph.prototype.graph = function () {
|
|
99
|
+
return this._label;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/* === Node functions ========== */
|
|
103
|
+
|
|
104
|
+
Graph.prototype.setDefaultNodeLabel = function (newDefault) {
|
|
105
|
+
if (!_.isFunction(newDefault)) {
|
|
106
|
+
newDefault = _.constant(newDefault);
|
|
107
|
+
}
|
|
108
|
+
this._defaultNodeLabelFn = newDefault;
|
|
109
|
+
return this;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
Graph.prototype.nodeCount = function () {
|
|
113
|
+
return this._nodeCount;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
Graph.prototype.nodes = function () {
|
|
117
|
+
return _.keys(this._nodes);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
Graph.prototype.sources = function () {
|
|
121
|
+
var self = this;
|
|
122
|
+
return _.filter(this.nodes(), function (v) {
|
|
123
|
+
return _.isEmpty(self._in[v]);
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
Graph.prototype.sinks = function () {
|
|
128
|
+
var self = this;
|
|
129
|
+
return _.filter(this.nodes(), function (v) {
|
|
130
|
+
return _.isEmpty(self._out[v]);
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
Graph.prototype.setNodes = function (vs, value) {
|
|
135
|
+
var args = arguments;
|
|
136
|
+
var self = this;
|
|
137
|
+
_.each(vs, function (v) {
|
|
138
|
+
if (args.length > 1) {
|
|
139
|
+
self.setNode(v, value);
|
|
140
|
+
} else {
|
|
141
|
+
self.setNode(v);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
return this;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
Graph.prototype.setNode = function (v, value) {
|
|
148
|
+
if (_.has(this._nodes, v)) {
|
|
149
|
+
if (arguments.length > 1) {
|
|
150
|
+
this._nodes[v] = value;
|
|
151
|
+
}
|
|
152
|
+
return this;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
|
|
156
|
+
if (this._isCompound) {
|
|
157
|
+
this._parent[v] = GRAPH_NODE;
|
|
158
|
+
this._children[v] = {};
|
|
159
|
+
this._children[GRAPH_NODE][v] = true;
|
|
160
|
+
}
|
|
161
|
+
this._in[v] = {};
|
|
162
|
+
this._preds[v] = {};
|
|
163
|
+
this._out[v] = {};
|
|
164
|
+
this._sucs[v] = {};
|
|
165
|
+
++this._nodeCount;
|
|
166
|
+
return this;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
Graph.prototype.node = function (v) {
|
|
170
|
+
return this._nodes[v];
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
Graph.prototype.hasNode = function (v) {
|
|
174
|
+
return _.has(this._nodes, v);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
Graph.prototype.removeNode = function (v) {
|
|
178
|
+
var self = this;
|
|
179
|
+
if (_.has(this._nodes, v)) {
|
|
180
|
+
var removeEdge = function (e) {
|
|
181
|
+
self.removeEdge(self._edgeObjs[e]);
|
|
182
|
+
};
|
|
183
|
+
delete this._nodes[v];
|
|
184
|
+
if (this._isCompound) {
|
|
185
|
+
this._removeFromParentsChildList(v);
|
|
186
|
+
delete this._parent[v];
|
|
187
|
+
_.each(this.children(v), function (child) {
|
|
188
|
+
self.setParent(child);
|
|
189
|
+
});
|
|
190
|
+
delete this._children[v];
|
|
191
|
+
}
|
|
192
|
+
_.each(_.keys(this._in[v]), removeEdge);
|
|
193
|
+
delete this._in[v];
|
|
194
|
+
delete this._preds[v];
|
|
195
|
+
_.each(_.keys(this._out[v]), removeEdge);
|
|
196
|
+
delete this._out[v];
|
|
197
|
+
delete this._sucs[v];
|
|
198
|
+
--this._nodeCount;
|
|
199
|
+
}
|
|
200
|
+
return this;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
Graph.prototype.setParent = function (v, parent) {
|
|
204
|
+
if (!this._isCompound) {
|
|
205
|
+
throw new Error("Cannot set parent in a non-compound graph");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (_.isUndefined(parent)) {
|
|
209
|
+
parent = GRAPH_NODE;
|
|
210
|
+
} else {
|
|
211
|
+
// Coerce parent to string
|
|
212
|
+
parent += "";
|
|
213
|
+
for (
|
|
214
|
+
var ancestor = parent;
|
|
215
|
+
!_.isUndefined(ancestor);
|
|
216
|
+
ancestor = this.parent(ancestor)
|
|
217
|
+
) {
|
|
218
|
+
if (ancestor === v) {
|
|
219
|
+
throw new Error(
|
|
220
|
+
"Setting " + parent + " as parent of " + v + " would create a cycle",
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
this.setNode(parent);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
this.setNode(v);
|
|
229
|
+
this._removeFromParentsChildList(v);
|
|
230
|
+
this._parent[v] = parent;
|
|
231
|
+
this._children[parent][v] = true;
|
|
232
|
+
return this;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
Graph.prototype._removeFromParentsChildList = function (v) {
|
|
236
|
+
delete this._children[this._parent[v]][v];
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
Graph.prototype.parent = function (v) {
|
|
240
|
+
if (this._isCompound) {
|
|
241
|
+
var parent = this._parent[v];
|
|
242
|
+
if (parent !== GRAPH_NODE) {
|
|
243
|
+
return parent;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
Graph.prototype.children = function (v) {
|
|
249
|
+
if (_.isUndefined(v)) {
|
|
250
|
+
v = GRAPH_NODE;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (this._isCompound) {
|
|
254
|
+
var children = this._children[v];
|
|
255
|
+
if (children) {
|
|
256
|
+
return _.keys(children);
|
|
257
|
+
}
|
|
258
|
+
} else if (v === GRAPH_NODE) {
|
|
259
|
+
return this.nodes();
|
|
260
|
+
} else if (this.hasNode(v)) {
|
|
261
|
+
return [];
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
Graph.prototype.predecessors = function (v) {
|
|
266
|
+
var predsV = this._preds[v];
|
|
267
|
+
if (predsV) {
|
|
268
|
+
return _.keys(predsV);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
Graph.prototype.successors = function (v) {
|
|
273
|
+
var sucsV = this._sucs[v];
|
|
274
|
+
if (sucsV) {
|
|
275
|
+
return _.keys(sucsV);
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
Graph.prototype.neighbors = function (v) {
|
|
280
|
+
var preds = this.predecessors(v);
|
|
281
|
+
if (preds) {
|
|
282
|
+
return _.union(preds, this.successors(v));
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
Graph.prototype.isLeaf = function (v) {
|
|
287
|
+
var neighbors;
|
|
288
|
+
if (this.isDirected()) {
|
|
289
|
+
neighbors = this.successors(v);
|
|
290
|
+
} else {
|
|
291
|
+
neighbors = this.neighbors(v);
|
|
292
|
+
}
|
|
293
|
+
return neighbors.length === 0;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
Graph.prototype.filterNodes = function (filter) {
|
|
297
|
+
var copy = new this.constructor({
|
|
298
|
+
directed: this._isDirected,
|
|
299
|
+
multigraph: this._isMultigraph,
|
|
300
|
+
compound: this._isCompound,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
copy.setGraph(this.graph());
|
|
304
|
+
|
|
305
|
+
var self = this;
|
|
306
|
+
_.each(this._nodes, function (value, v) {
|
|
307
|
+
if (filter(v)) {
|
|
308
|
+
copy.setNode(v, value);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
_.each(this._edgeObjs, function (e) {
|
|
313
|
+
if (copy.hasNode(e.v) && copy.hasNode(e.w)) {
|
|
314
|
+
copy.setEdge(e, self.edge(e));
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
var parents = {};
|
|
319
|
+
function findParent(v) {
|
|
320
|
+
var parent = self.parent(v);
|
|
321
|
+
if (parent === undefined || copy.hasNode(parent)) {
|
|
322
|
+
parents[v] = parent;
|
|
323
|
+
return parent;
|
|
324
|
+
} else if (parent in parents) {
|
|
325
|
+
return parents[parent];
|
|
326
|
+
} else {
|
|
327
|
+
return findParent(parent);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (this._isCompound) {
|
|
332
|
+
_.each(copy.nodes(), function (v) {
|
|
333
|
+
copy.setParent(v, findParent(v));
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return copy;
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/* === Edge functions ========== */
|
|
341
|
+
|
|
342
|
+
Graph.prototype.setDefaultEdgeLabel = function (newDefault) {
|
|
343
|
+
if (!_.isFunction(newDefault)) {
|
|
344
|
+
newDefault = _.constant(newDefault);
|
|
345
|
+
}
|
|
346
|
+
this._defaultEdgeLabelFn = newDefault;
|
|
347
|
+
return this;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
Graph.prototype.edgeCount = function () {
|
|
351
|
+
return this._edgeCount;
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
Graph.prototype.edges = function () {
|
|
355
|
+
return _.values(this._edgeObjs);
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
Graph.prototype.setPath = function (vs, value) {
|
|
359
|
+
var self = this;
|
|
360
|
+
var args = arguments;
|
|
361
|
+
_.reduce(vs, function (v, w) {
|
|
362
|
+
if (args.length > 1) {
|
|
363
|
+
self.setEdge(v, w, value);
|
|
364
|
+
} else {
|
|
365
|
+
self.setEdge(v, w);
|
|
366
|
+
}
|
|
367
|
+
return w;
|
|
368
|
+
});
|
|
369
|
+
return this;
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
/*
|
|
373
|
+
* setEdge(v, w, [value, [name]])
|
|
374
|
+
* setEdge({ v, w, [name] }, [value])
|
|
375
|
+
*/
|
|
376
|
+
Graph.prototype.setEdge = function () {
|
|
377
|
+
var v, w, name, value;
|
|
378
|
+
var valueSpecified = false;
|
|
379
|
+
var arg0 = arguments[0];
|
|
380
|
+
|
|
381
|
+
if (typeof arg0 === "object" && arg0 !== null && "v" in arg0) {
|
|
382
|
+
v = arg0.v;
|
|
383
|
+
w = arg0.w;
|
|
384
|
+
name = arg0.name;
|
|
385
|
+
if (arguments.length === 2) {
|
|
386
|
+
value = arguments[1];
|
|
387
|
+
valueSpecified = true;
|
|
388
|
+
}
|
|
389
|
+
} else {
|
|
390
|
+
v = arg0;
|
|
391
|
+
w = arguments[1];
|
|
392
|
+
name = arguments[3];
|
|
393
|
+
if (arguments.length > 2) {
|
|
394
|
+
value = arguments[2];
|
|
395
|
+
valueSpecified = true;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
v = "" + v;
|
|
400
|
+
w = "" + w;
|
|
401
|
+
if (!_.isUndefined(name)) {
|
|
402
|
+
name = "" + name;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
var e = edgeArgsToId(this._isDirected, v, w, name);
|
|
406
|
+
if (_.has(this._edgeLabels, e)) {
|
|
407
|
+
if (valueSpecified) {
|
|
408
|
+
this._edgeLabels[e] = value;
|
|
409
|
+
}
|
|
410
|
+
return this;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (!_.isUndefined(name) && !this._isMultigraph) {
|
|
414
|
+
throw new Error("Cannot set a named edge when isMultigraph = false");
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// It didn't exist, so we need to create it.
|
|
418
|
+
// First ensure the nodes exist.
|
|
419
|
+
this.setNode(v);
|
|
420
|
+
this.setNode(w);
|
|
421
|
+
|
|
422
|
+
this._edgeLabels[e] = valueSpecified
|
|
423
|
+
? value
|
|
424
|
+
: this._defaultEdgeLabelFn(v, w, name);
|
|
425
|
+
|
|
426
|
+
var edgeObj = edgeArgsToObj(this._isDirected, v, w, name);
|
|
427
|
+
// Ensure we add undirected edges in a consistent way.
|
|
428
|
+
v = edgeObj.v;
|
|
429
|
+
w = edgeObj.w;
|
|
430
|
+
|
|
431
|
+
Object.freeze(edgeObj);
|
|
432
|
+
this._edgeObjs[e] = edgeObj;
|
|
433
|
+
incrementOrInitEntry(this._preds[w], v);
|
|
434
|
+
incrementOrInitEntry(this._sucs[v], w);
|
|
435
|
+
this._in[w][e] = edgeObj;
|
|
436
|
+
this._out[v][e] = edgeObj;
|
|
437
|
+
this._edgeCount++;
|
|
438
|
+
return this;
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
Graph.prototype.edge = function (v, w, name) {
|
|
442
|
+
var e =
|
|
443
|
+
arguments.length === 1
|
|
444
|
+
? edgeObjToId(this._isDirected, arguments[0])
|
|
445
|
+
: edgeArgsToId(this._isDirected, v, w, name);
|
|
446
|
+
return this._edgeLabels[e];
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
Graph.prototype.hasEdge = function (v, w, name) {
|
|
450
|
+
var e =
|
|
451
|
+
arguments.length === 1
|
|
452
|
+
? edgeObjToId(this._isDirected, arguments[0])
|
|
453
|
+
: edgeArgsToId(this._isDirected, v, w, name);
|
|
454
|
+
return _.has(this._edgeLabels, e);
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
Graph.prototype.removeEdge = function (v, w, name) {
|
|
458
|
+
var e =
|
|
459
|
+
arguments.length === 1
|
|
460
|
+
? edgeObjToId(this._isDirected, arguments[0])
|
|
461
|
+
: edgeArgsToId(this._isDirected, v, w, name);
|
|
462
|
+
var edge = this._edgeObjs[e];
|
|
463
|
+
if (edge) {
|
|
464
|
+
v = edge.v;
|
|
465
|
+
w = edge.w;
|
|
466
|
+
delete this._edgeLabels[e];
|
|
467
|
+
delete this._edgeObjs[e];
|
|
468
|
+
decrementOrRemoveEntry(this._preds[w], v);
|
|
469
|
+
decrementOrRemoveEntry(this._sucs[v], w);
|
|
470
|
+
delete this._in[w][e];
|
|
471
|
+
delete this._out[v][e];
|
|
472
|
+
this._edgeCount--;
|
|
473
|
+
}
|
|
474
|
+
return this;
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
Graph.prototype.inEdges = function (v, u) {
|
|
478
|
+
var inV = this._in[v];
|
|
479
|
+
if (inV) {
|
|
480
|
+
var edges = _.values(inV);
|
|
481
|
+
if (!u) {
|
|
482
|
+
return edges;
|
|
483
|
+
}
|
|
484
|
+
return _.filter(edges, function (edge) {
|
|
485
|
+
return edge.v === u;
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
Graph.prototype.outEdges = function (v, w) {
|
|
491
|
+
var outV = this._out[v];
|
|
492
|
+
if (outV) {
|
|
493
|
+
var edges = _.values(outV);
|
|
494
|
+
if (!w) {
|
|
495
|
+
return edges;
|
|
496
|
+
}
|
|
497
|
+
return _.filter(edges, function (edge) {
|
|
498
|
+
return edge.w === w;
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
Graph.prototype.nodeEdges = function (v, w) {
|
|
504
|
+
var inEdges = this.inEdges(v, w);
|
|
505
|
+
if (inEdges) {
|
|
506
|
+
return inEdges.concat(this.outEdges(v, w));
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
function incrementOrInitEntry(map, k) {
|
|
511
|
+
if (map[k]) {
|
|
512
|
+
map[k]++;
|
|
513
|
+
} else {
|
|
514
|
+
map[k] = 1;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function decrementOrRemoveEntry(map, k) {
|
|
519
|
+
if (!--map[k]) {
|
|
520
|
+
delete map[k];
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function edgeArgsToId(isDirected, v_, w_, name) {
|
|
525
|
+
var v = "" + v_;
|
|
526
|
+
var w = "" + w_;
|
|
527
|
+
if (!isDirected && v > w) {
|
|
528
|
+
var tmp = v;
|
|
529
|
+
v = w;
|
|
530
|
+
w = tmp;
|
|
531
|
+
}
|
|
532
|
+
return (
|
|
533
|
+
v +
|
|
534
|
+
EDGE_KEY_DELIM +
|
|
535
|
+
w +
|
|
536
|
+
EDGE_KEY_DELIM +
|
|
537
|
+
(_.isUndefined(name) ? DEFAULT_EDGE_NAME : name)
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function edgeArgsToObj(isDirected, v_, w_, name) {
|
|
542
|
+
var v = "" + v_;
|
|
543
|
+
var w = "" + w_;
|
|
544
|
+
if (!isDirected && v > w) {
|
|
545
|
+
var tmp = v;
|
|
546
|
+
v = w;
|
|
547
|
+
w = tmp;
|
|
548
|
+
}
|
|
549
|
+
var edgeObj = { v: v, w: w };
|
|
550
|
+
if (name) {
|
|
551
|
+
edgeObj.name = name;
|
|
552
|
+
}
|
|
553
|
+
return edgeObj;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function edgeObjToId(isDirected, edgeObj) {
|
|
557
|
+
return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name);
|
|
558
|
+
}
|
package/lib/index.js
ADDED
package/lib/json.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
var _ = require("./lodash");
|
|
2
|
+
var Graph = require("./graph");
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
write: write,
|
|
6
|
+
read: read
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function write(g) {
|
|
10
|
+
var json = {
|
|
11
|
+
options: {
|
|
12
|
+
directed: g.isDirected(),
|
|
13
|
+
multigraph: g.isMultigraph(),
|
|
14
|
+
compound: g.isCompound()
|
|
15
|
+
},
|
|
16
|
+
nodes: writeNodes(g),
|
|
17
|
+
edges: writeEdges(g)
|
|
18
|
+
};
|
|
19
|
+
if (!_.isUndefined(g.graph())) {
|
|
20
|
+
json.value = _.clone(g.graph());
|
|
21
|
+
}
|
|
22
|
+
return json;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function writeNodes(g) {
|
|
26
|
+
return _.map(g.nodes(), function(v) {
|
|
27
|
+
var nodeValue = g.node(v);
|
|
28
|
+
var parent = g.parent(v);
|
|
29
|
+
var node = { v: v };
|
|
30
|
+
if (!_.isUndefined(nodeValue)) {
|
|
31
|
+
node.value = nodeValue;
|
|
32
|
+
}
|
|
33
|
+
if (!_.isUndefined(parent)) {
|
|
34
|
+
node.parent = parent;
|
|
35
|
+
}
|
|
36
|
+
return node;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function writeEdges(g) {
|
|
41
|
+
return _.map(g.edges(), function(e) {
|
|
42
|
+
var edgeValue = g.edge(e);
|
|
43
|
+
var edge = { v: e.v, w: e.w };
|
|
44
|
+
if (!_.isUndefined(e.name)) {
|
|
45
|
+
edge.name = e.name;
|
|
46
|
+
}
|
|
47
|
+
if (!_.isUndefined(edgeValue)) {
|
|
48
|
+
edge.value = edgeValue;
|
|
49
|
+
}
|
|
50
|
+
return edge;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function read(json) {
|
|
55
|
+
var g = new Graph(json.options).setGraph(json.value);
|
|
56
|
+
_.each(json.nodes, function(entry) {
|
|
57
|
+
g.setNode(entry.v, entry.value);
|
|
58
|
+
if (entry.parent) {
|
|
59
|
+
g.setParent(entry.v, entry.parent);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
_.each(json.edges, function(entry) {
|
|
63
|
+
g.setEdge({ v: entry.v, w: entry.w, name: entry.name }, entry.value);
|
|
64
|
+
});
|
|
65
|
+
return g;
|
|
66
|
+
}
|
package/lib/lodash.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* global window */
|
|
2
|
+
|
|
3
|
+
var lodash;
|
|
4
|
+
|
|
5
|
+
if (typeof require === "function") {
|
|
6
|
+
try {
|
|
7
|
+
lodash = {
|
|
8
|
+
clone: require("lodash/clone"),
|
|
9
|
+
constant: require("lodash/constant"),
|
|
10
|
+
each: require("lodash/each"),
|
|
11
|
+
filter: require("lodash/filter"),
|
|
12
|
+
has: require("lodash/has"),
|
|
13
|
+
isArray: require("lodash/isArray"),
|
|
14
|
+
isEmpty: require("lodash/isEmpty"),
|
|
15
|
+
isFunction: require("lodash/isFunction"),
|
|
16
|
+
isUndefined: require("lodash/isUndefined"),
|
|
17
|
+
keys: require("lodash/keys"),
|
|
18
|
+
map: require("lodash/map"),
|
|
19
|
+
reduce: require("lodash/reduce"),
|
|
20
|
+
size: require("lodash/size"),
|
|
21
|
+
transform: require("lodash/transform"),
|
|
22
|
+
union: require("lodash/union"),
|
|
23
|
+
values: require("lodash/values")
|
|
24
|
+
};
|
|
25
|
+
} catch (e) {
|
|
26
|
+
// continue regardless of error
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!lodash) {
|
|
31
|
+
lodash = window._;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = lodash;
|
package/lib/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = '2.1.8';
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "graphkit-js",
|
|
3
|
+
"version": "2.1.4",
|
|
4
|
+
"description": "A directed and undirected multi-graph library",
|
|
5
|
+
"author": "Monique Meza <moniquemeza22@outlook.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "index.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"index.js",
|
|
10
|
+
"dist/",
|
|
11
|
+
"lib/",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"graph",
|
|
17
|
+
"base",
|
|
18
|
+
"graphkit",
|
|
19
|
+
"graphlib",
|
|
20
|
+
"algorithms",
|
|
21
|
+
"graphkit-js"
|
|
22
|
+
],
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"lodash": "^4.17.15"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"benchmark": "^2.1.4",
|
|
28
|
+
"browserify": "^16.2.3",
|
|
29
|
+
"chai": "^4.1.2",
|
|
30
|
+
"eslint": "^5.13.0",
|
|
31
|
+
"istanbul": "^0.4.5",
|
|
32
|
+
"jshint": "^2.9.6",
|
|
33
|
+
"jshint-stylish": "^2.2.1",
|
|
34
|
+
"karma": "^4.1.0",
|
|
35
|
+
"karma-chrome-launcher": "^2.2.0",
|
|
36
|
+
"karma-firefox-launcher": "^1.1.0",
|
|
37
|
+
"karma-mocha": "^1.3.0",
|
|
38
|
+
"karma-phantomjs-launcher": "^1.0.4",
|
|
39
|
+
"karma-requirejs": "^1.1.0",
|
|
40
|
+
"karma-safari-launcher": "^1.0.0",
|
|
41
|
+
"mocha": "^6.1.4",
|
|
42
|
+
"phantomjs-prebuilt": "^2.1.16",
|
|
43
|
+
"requirejs": "^2.3.5",
|
|
44
|
+
"seedrandom": "^2.4.3",
|
|
45
|
+
"semver": "^5.5.0",
|
|
46
|
+
"sprintf": "^0.1.5",
|
|
47
|
+
"uglify-js": "^3.3.10"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/GRAPHKITORG/graphkit-js.git"
|
|
52
|
+
}
|
|
53
|
+
}
|