@sinm/kai 1.8.5
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 +21 -0
- package/README.md +219 -0
- package/bin/kai-cli.js +21 -0
- package/dist-cli/kai-cli.js +218494 -0
- package/dist-electron/renderer/assets/_baseUniq-C3qTPmDE.js +660 -0
- package/dist-electron/renderer/assets/arc-BNCDL4e8.js +131 -0
- package/dist-electron/renderer/assets/architectureDiagram-Q4EWVU46-BdbGbDeJ.js +8718 -0
- package/dist-electron/renderer/assets/blockDiagram-DXYQGD6D-QiXI7ilT.js +3637 -0
- package/dist-electron/renderer/assets/c4Diagram-AHTNJAMY-BddxtMgY.js +2482 -0
- package/dist-electron/renderer/assets/channel-C_JLiB8I.js +7 -0
- package/dist-electron/renderer/assets/chunk-4BX2VUAB-s-dHrXuO.js +16 -0
- package/dist-electron/renderer/assets/chunk-4TB4RGXK-vzGbJGfp.js +1920 -0
- package/dist-electron/renderer/assets/chunk-55IACEB6-DS6S48ws.js +13 -0
- package/dist-electron/renderer/assets/chunk-EDXVE4YY-CkjF90gW.js +24 -0
- package/dist-electron/renderer/assets/chunk-FMBD7UC4-BXvIgVUY.js +19 -0
- package/dist-electron/renderer/assets/chunk-OYMX7WX6-YZbrtKSv.js +1939 -0
- package/dist-electron/renderer/assets/chunk-QZHKN3VN-BbLYRfB3.js +19 -0
- package/dist-electron/renderer/assets/chunk-YZCP3GAM-JVGt9SK_.js +116 -0
- package/dist-electron/renderer/assets/classDiagram-6PBFFD2Q-BwZMRjub.js +23 -0
- package/dist-electron/renderer/assets/classDiagram-v2-HSJHXN6E-BwZMRjub.js +23 -0
- package/dist-electron/renderer/assets/clone-BC-6Iyrf.js +8 -0
- package/dist-electron/renderer/assets/cose-bilkent-S5V4N54A-C3CGX8BH.js +4942 -0
- package/dist-electron/renderer/assets/cytoscape.esm-D6E6cAed.js +30246 -0
- package/dist-electron/renderer/assets/dagre-KV5264BT-DXOCL1ZZ.js +694 -0
- package/dist-electron/renderer/assets/defaultLocale-B2RvLBDe.js +206 -0
- package/dist-electron/renderer/assets/diagram-5BDNPKRD-B9dghm7-.js +171 -0
- package/dist-electron/renderer/assets/diagram-G4DWMVQ6-DDupyCeT.js +853 -0
- package/dist-electron/renderer/assets/diagram-MMDJMWI5-Bagr5R3p.js +303 -0
- package/dist-electron/renderer/assets/diagram-TYMM5635-YL5sCgeo.js +214 -0
- package/dist-electron/renderer/assets/erDiagram-SMLLAGMA-CHytCe4p.js +1227 -0
- package/dist-electron/renderer/assets/flowDiagram-DWJPFMVM-BJgPbbzi.js +2332 -0
- package/dist-electron/renderer/assets/ganttDiagram-T4ZO3ILL-BN-Vq0iy.js +3714 -0
- package/dist-electron/renderer/assets/gitGraphDiagram-UUTBAWPF-CbUpEcLb.js +1375 -0
- package/dist-electron/renderer/assets/graph-Di49T8Ee.js +953 -0
- package/dist-electron/renderer/assets/index-C55TZN9T.css +14105 -0
- package/dist-electron/renderer/assets/index-D-H_6heO.js +91405 -0
- package/dist-electron/renderer/assets/infoDiagram-42DDH7IO-BPl-rsFx.js +33 -0
- package/dist-electron/renderer/assets/init-ZxktEp_H.js +16 -0
- package/dist-electron/renderer/assets/ishikawaDiagram-UXIWVN3A-C8ly-VN_.js +967 -0
- package/dist-electron/renderer/assets/journeyDiagram-VCZTEJTY-nUjo5Mzy.js +1255 -0
- package/dist-electron/renderer/assets/kanban-definition-6JOO6SKY-DWVGGGQB.js +1052 -0
- package/dist-electron/renderer/assets/katex-CYis69t2.js +14301 -0
- package/dist-electron/renderer/assets/layout-BO15dWax.js +2217 -0
- package/dist-electron/renderer/assets/linear-bwcJeNAk.js +340 -0
- package/dist-electron/renderer/assets/min-CSnTolL5.js +41 -0
- package/dist-electron/renderer/assets/mindmap-definition-QFDTVHPH-WJVpu9VT.js +1186 -0
- package/dist-electron/renderer/assets/ordinal-CxptdPJm.js +76 -0
- package/dist-electron/renderer/assets/pieDiagram-DEJITSTG-DF_DZ5Q4.js +248 -0
- package/dist-electron/renderer/assets/quadrantDiagram-34T5L4WZ-UhXGuJcr.js +1342 -0
- package/dist-electron/renderer/assets/requirementDiagram-MS252O5E-BtD6ux77.js +1204 -0
- package/dist-electron/renderer/assets/sankeyDiagram-XADWPNL6-CC4IbM1T.js +1205 -0
- package/dist-electron/renderer/assets/sequenceDiagram-FGHM5R23-Da4bQBSu.js +4502 -0
- package/dist-electron/renderer/assets/stateDiagram-FHFEXIEX-zEkMqOXM.js +452 -0
- package/dist-electron/renderer/assets/stateDiagram-v2-QKLJ7IA2-DpXHvwUL.js +21 -0
- package/dist-electron/renderer/assets/timeline-definition-GMOUNBTQ-DJnjzEUR.js +1596 -0
- package/dist-electron/renderer/assets/vennDiagram-DHZGUBPP-f6WAsZFS.js +2486 -0
- package/dist-electron/renderer/assets/wardley-RL74JXVD-pTLEMWKj.js +24199 -0
- package/dist-electron/renderer/assets/wardleyDiagram-NUSXRM2D-GRV6kOg2.js +901 -0
- package/dist-electron/renderer/assets/xychartDiagram-5P7HB3ND-BAcUBgxf.js +1932 -0
- package/dist-electron/renderer/index.html +13 -0
- package/package.json +52 -0
|
@@ -0,0 +1,953 @@
|
|
|
1
|
+
import { aS as copyObject, aT as keysIn, aU as getPrototype, aV as cloneArrayBuffer, aW as Symbol$1, aX as cloneTypedArray, aY as isObjectLike, aZ as getTag, a_ as baseUnary, a$ as nodeUtil, b0 as isObject, b1 as copyArray, b2 as isBuffer, b3 as cloneBuffer, b4 as initCloneObject, b5 as Stack, aH as isArray, b6 as assignValue, b7 as baseRest, b8 as isArrayLikeObject, b9 as constant, ba as isFunction, bb as isEmpty } from "./index-D-H_6heO.js";
|
|
2
|
+
import { k as keys, g as getSymbols, s as stubArray, e as arrayPush, f as baseGetAllKeys, h as arrayEach, j as getAllKeys, d as arrayMap, l as baseUniq, b as baseFlatten, m as filter, n as forEach, r as reduce } from "./_baseUniq-C3qTPmDE.js";
|
|
3
|
+
function baseAssign(object, source) {
|
|
4
|
+
return object && copyObject(source, keys(source), object);
|
|
5
|
+
}
|
|
6
|
+
function baseAssignIn(object, source) {
|
|
7
|
+
return object && copyObject(source, keysIn(source), object);
|
|
8
|
+
}
|
|
9
|
+
function copySymbols(source, object) {
|
|
10
|
+
return copyObject(source, getSymbols(source), object);
|
|
11
|
+
}
|
|
12
|
+
var nativeGetSymbols = Object.getOwnPropertySymbols;
|
|
13
|
+
var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
|
|
14
|
+
var result = [];
|
|
15
|
+
while (object) {
|
|
16
|
+
arrayPush(result, getSymbols(object));
|
|
17
|
+
object = getPrototype(object);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
function copySymbolsIn(source, object) {
|
|
22
|
+
return copyObject(source, getSymbolsIn(source), object);
|
|
23
|
+
}
|
|
24
|
+
function getAllKeysIn(object) {
|
|
25
|
+
return baseGetAllKeys(object, keysIn, getSymbolsIn);
|
|
26
|
+
}
|
|
27
|
+
var objectProto = Object.prototype;
|
|
28
|
+
var hasOwnProperty = objectProto.hasOwnProperty;
|
|
29
|
+
function initCloneArray(array) {
|
|
30
|
+
var length = array.length, result = new array.constructor(length);
|
|
31
|
+
if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) {
|
|
32
|
+
result.index = array.index;
|
|
33
|
+
result.input = array.input;
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
function cloneDataView(dataView, isDeep) {
|
|
38
|
+
var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
|
|
39
|
+
return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
|
|
40
|
+
}
|
|
41
|
+
var reFlags = /\w*$/;
|
|
42
|
+
function cloneRegExp(regexp) {
|
|
43
|
+
var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
|
|
44
|
+
result.lastIndex = regexp.lastIndex;
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
var symbolProto = Symbol$1 ? Symbol$1.prototype : void 0, symbolValueOf = symbolProto ? symbolProto.valueOf : void 0;
|
|
48
|
+
function cloneSymbol(symbol) {
|
|
49
|
+
return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
|
|
50
|
+
}
|
|
51
|
+
var boolTag$1 = "[object Boolean]", dateTag$1 = "[object Date]", mapTag$2 = "[object Map]", numberTag$1 = "[object Number]", regexpTag$1 = "[object RegExp]", setTag$2 = "[object Set]", stringTag$1 = "[object String]", symbolTag$1 = "[object Symbol]";
|
|
52
|
+
var arrayBufferTag$1 = "[object ArrayBuffer]", dataViewTag$1 = "[object DataView]", float32Tag$1 = "[object Float32Array]", float64Tag$1 = "[object Float64Array]", int8Tag$1 = "[object Int8Array]", int16Tag$1 = "[object Int16Array]", int32Tag$1 = "[object Int32Array]", uint8Tag$1 = "[object Uint8Array]", uint8ClampedTag$1 = "[object Uint8ClampedArray]", uint16Tag$1 = "[object Uint16Array]", uint32Tag$1 = "[object Uint32Array]";
|
|
53
|
+
function initCloneByTag(object, tag, isDeep) {
|
|
54
|
+
var Ctor = object.constructor;
|
|
55
|
+
switch (tag) {
|
|
56
|
+
case arrayBufferTag$1:
|
|
57
|
+
return cloneArrayBuffer(object);
|
|
58
|
+
case boolTag$1:
|
|
59
|
+
case dateTag$1:
|
|
60
|
+
return new Ctor(+object);
|
|
61
|
+
case dataViewTag$1:
|
|
62
|
+
return cloneDataView(object, isDeep);
|
|
63
|
+
case float32Tag$1:
|
|
64
|
+
case float64Tag$1:
|
|
65
|
+
case int8Tag$1:
|
|
66
|
+
case int16Tag$1:
|
|
67
|
+
case int32Tag$1:
|
|
68
|
+
case uint8Tag$1:
|
|
69
|
+
case uint8ClampedTag$1:
|
|
70
|
+
case uint16Tag$1:
|
|
71
|
+
case uint32Tag$1:
|
|
72
|
+
return cloneTypedArray(object, isDeep);
|
|
73
|
+
case mapTag$2:
|
|
74
|
+
return new Ctor();
|
|
75
|
+
case numberTag$1:
|
|
76
|
+
case stringTag$1:
|
|
77
|
+
return new Ctor(object);
|
|
78
|
+
case regexpTag$1:
|
|
79
|
+
return cloneRegExp(object);
|
|
80
|
+
case setTag$2:
|
|
81
|
+
return new Ctor();
|
|
82
|
+
case symbolTag$1:
|
|
83
|
+
return cloneSymbol(object);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
var mapTag$1 = "[object Map]";
|
|
87
|
+
function baseIsMap(value) {
|
|
88
|
+
return isObjectLike(value) && getTag(value) == mapTag$1;
|
|
89
|
+
}
|
|
90
|
+
var nodeIsMap = nodeUtil && nodeUtil.isMap;
|
|
91
|
+
var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
|
|
92
|
+
var setTag$1 = "[object Set]";
|
|
93
|
+
function baseIsSet(value) {
|
|
94
|
+
return isObjectLike(value) && getTag(value) == setTag$1;
|
|
95
|
+
}
|
|
96
|
+
var nodeIsSet = nodeUtil && nodeUtil.isSet;
|
|
97
|
+
var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
|
|
98
|
+
var CLONE_DEEP_FLAG = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG = 4;
|
|
99
|
+
var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", weakMapTag = "[object WeakMap]";
|
|
100
|
+
var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]";
|
|
101
|
+
var cloneableTags = {};
|
|
102
|
+
cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
|
|
103
|
+
cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
|
|
104
|
+
function baseClone(value, bitmask, customizer, key, object, stack) {
|
|
105
|
+
var result, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG;
|
|
106
|
+
if (result !== void 0) {
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
if (!isObject(value)) {
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
var isArr = isArray(value);
|
|
113
|
+
if (isArr) {
|
|
114
|
+
result = initCloneArray(value);
|
|
115
|
+
if (!isDeep) {
|
|
116
|
+
return copyArray(value, result);
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
var tag = getTag(value), isFunc = tag == funcTag || tag == genTag;
|
|
120
|
+
if (isBuffer(value)) {
|
|
121
|
+
return cloneBuffer(value, isDeep);
|
|
122
|
+
}
|
|
123
|
+
if (tag == objectTag || tag == argsTag || isFunc && !object) {
|
|
124
|
+
result = isFlat || isFunc ? {} : initCloneObject(value);
|
|
125
|
+
if (!isDeep) {
|
|
126
|
+
return isFlat ? copySymbolsIn(value, baseAssignIn(result, value)) : copySymbols(value, baseAssign(result, value));
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
if (!cloneableTags[tag]) {
|
|
130
|
+
return object ? value : {};
|
|
131
|
+
}
|
|
132
|
+
result = initCloneByTag(value, tag, isDeep);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
stack || (stack = new Stack());
|
|
136
|
+
var stacked = stack.get(value);
|
|
137
|
+
if (stacked) {
|
|
138
|
+
return stacked;
|
|
139
|
+
}
|
|
140
|
+
stack.set(value, result);
|
|
141
|
+
if (isSet(value)) {
|
|
142
|
+
value.forEach(function(subValue) {
|
|
143
|
+
result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
|
|
144
|
+
});
|
|
145
|
+
} else if (isMap(value)) {
|
|
146
|
+
value.forEach(function(subValue, key2) {
|
|
147
|
+
result.set(key2, baseClone(subValue, bitmask, customizer, key2, value, stack));
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
|
|
151
|
+
var props = isArr ? void 0 : keysFunc(value);
|
|
152
|
+
arrayEach(props || value, function(subValue, key2) {
|
|
153
|
+
if (props) {
|
|
154
|
+
key2 = subValue;
|
|
155
|
+
subValue = value[key2];
|
|
156
|
+
}
|
|
157
|
+
assignValue(result, key2, baseClone(subValue, bitmask, customizer, key2, value, stack));
|
|
158
|
+
});
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
function baseValues(object, props) {
|
|
162
|
+
return arrayMap(props, function(key) {
|
|
163
|
+
return object[key];
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function values(object) {
|
|
167
|
+
return object == null ? [] : baseValues(object, keys(object));
|
|
168
|
+
}
|
|
169
|
+
function isUndefined(value) {
|
|
170
|
+
return value === void 0;
|
|
171
|
+
}
|
|
172
|
+
var union = baseRest(function(arrays) {
|
|
173
|
+
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
|
|
174
|
+
});
|
|
175
|
+
var DEFAULT_EDGE_NAME = "\0";
|
|
176
|
+
var GRAPH_NODE = "\0";
|
|
177
|
+
var EDGE_KEY_DELIM = "";
|
|
178
|
+
class Graph {
|
|
179
|
+
/**
|
|
180
|
+
* @param {GraphOptions} [opts] - Graph options.
|
|
181
|
+
*/
|
|
182
|
+
constructor(opts = {}) {
|
|
183
|
+
this._isDirected = Object.prototype.hasOwnProperty.call(opts, "directed") ? opts.directed : true;
|
|
184
|
+
this._isMultigraph = Object.prototype.hasOwnProperty.call(opts, "multigraph") ? opts.multigraph : false;
|
|
185
|
+
this._isCompound = Object.prototype.hasOwnProperty.call(opts, "compound") ? opts.compound : false;
|
|
186
|
+
this._label = void 0;
|
|
187
|
+
this._defaultNodeLabelFn = constant(void 0);
|
|
188
|
+
this._defaultEdgeLabelFn = constant(void 0);
|
|
189
|
+
this._nodes = {};
|
|
190
|
+
if (this._isCompound) {
|
|
191
|
+
this._parent = {};
|
|
192
|
+
this._children = {};
|
|
193
|
+
this._children[GRAPH_NODE] = {};
|
|
194
|
+
}
|
|
195
|
+
this._in = {};
|
|
196
|
+
this._preds = {};
|
|
197
|
+
this._out = {};
|
|
198
|
+
this._sucs = {};
|
|
199
|
+
this._edgeObjs = {};
|
|
200
|
+
this._edgeLabels = {};
|
|
201
|
+
}
|
|
202
|
+
/* === Graph functions ========= */
|
|
203
|
+
/**
|
|
204
|
+
*
|
|
205
|
+
* @returns {boolean} `true` if the graph is [directed](https://en.wikipedia.org/wiki/Directed_graph).
|
|
206
|
+
* A directed graph treats the order of nodes in an edge as significant whereas an
|
|
207
|
+
* [undirected](https://en.wikipedia.org/wiki/Graph_(mathematics)#Undirected_graph)
|
|
208
|
+
* graph does not.
|
|
209
|
+
* This example demonstrates the difference:
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
*
|
|
213
|
+
* ```js
|
|
214
|
+
* var directed = new Graph({ directed: true });
|
|
215
|
+
* directed.setEdge("a", "b", "my-label");
|
|
216
|
+
* directed.edge("a", "b"); // returns "my-label"
|
|
217
|
+
* directed.edge("b", "a"); // returns undefined
|
|
218
|
+
*
|
|
219
|
+
* var undirected = new Graph({ directed: false });
|
|
220
|
+
* undirected.setEdge("a", "b", "my-label");
|
|
221
|
+
* undirected.edge("a", "b"); // returns "my-label"
|
|
222
|
+
* undirected.edge("b", "a"); // returns "my-label"
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
isDirected() {
|
|
226
|
+
return this._isDirected;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* @returns {boolean} `true` if the graph is a multigraph.
|
|
230
|
+
*/
|
|
231
|
+
isMultigraph() {
|
|
232
|
+
return this._isMultigraph;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* @returns {boolean} `true` if the graph is compound.
|
|
236
|
+
*/
|
|
237
|
+
isCompound() {
|
|
238
|
+
return this._isCompound;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Sets the label for the graph to `label`.
|
|
242
|
+
*
|
|
243
|
+
* @param {GraphLabel} label - Label for the graph.
|
|
244
|
+
* @returns {this}
|
|
245
|
+
*/
|
|
246
|
+
setGraph(label) {
|
|
247
|
+
this._label = label;
|
|
248
|
+
return this;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* @returns {GraphLabel | undefined} the currently assigned label for the graph.
|
|
252
|
+
* If no label has been assigned, returns `undefined`.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
*
|
|
256
|
+
* ```js
|
|
257
|
+
* var g = new Graph();
|
|
258
|
+
* g.graph(); // returns undefined
|
|
259
|
+
* g.setGraph("graph-label");
|
|
260
|
+
* g.graph(); // returns "graph-label"
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
graph() {
|
|
264
|
+
return this._label;
|
|
265
|
+
}
|
|
266
|
+
/* === Node functions ========== */
|
|
267
|
+
/**
|
|
268
|
+
* Sets a new default value that is assigned to nodes that are created without
|
|
269
|
+
* a label.
|
|
270
|
+
*
|
|
271
|
+
* @param {typeof this._defaultNodeLabelFn | NodeLabel} newDefault - If a function,
|
|
272
|
+
* it is called with the id of the node being created.
|
|
273
|
+
* Otherwise, it is assigned as the label directly.
|
|
274
|
+
* @returns {this}
|
|
275
|
+
*/
|
|
276
|
+
setDefaultNodeLabel(newDefault) {
|
|
277
|
+
if (!isFunction(newDefault)) {
|
|
278
|
+
newDefault = constant(newDefault);
|
|
279
|
+
}
|
|
280
|
+
this._defaultNodeLabelFn = newDefault;
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* @returns {number} the number of nodes in the graph.
|
|
285
|
+
*/
|
|
286
|
+
nodeCount() {
|
|
287
|
+
return this._nodeCount;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* @returns {NodeID[]} the ids of the nodes in the graph.
|
|
291
|
+
*
|
|
292
|
+
* @remarks
|
|
293
|
+
* Use {@link node()} to get the label for each node.
|
|
294
|
+
* Takes `O(|V|)` time.
|
|
295
|
+
*/
|
|
296
|
+
nodes() {
|
|
297
|
+
return keys(this._nodes);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* @returns {NodeID[]} those nodes in the graph that have no in-edges.
|
|
301
|
+
* @remarks Takes `O(|V|)` time.
|
|
302
|
+
*/
|
|
303
|
+
sources() {
|
|
304
|
+
var self = this;
|
|
305
|
+
return filter(this.nodes(), function(v) {
|
|
306
|
+
return isEmpty(self._in[v]);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* @returns {NodeID[]} those nodes in the graph that have no out-edges.
|
|
311
|
+
* @remarks Takes `O(|V|)` time.
|
|
312
|
+
*/
|
|
313
|
+
sinks() {
|
|
314
|
+
var self = this;
|
|
315
|
+
return filter(this.nodes(), function(v) {
|
|
316
|
+
return isEmpty(self._out[v]);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Invokes setNode method for each node in `vs` list.
|
|
321
|
+
*
|
|
322
|
+
* @param {Collection<NodeID | number>} vs - List of node IDs to create/set.
|
|
323
|
+
* @param {NodeLabel} [value] - If set, update all nodes with this value.
|
|
324
|
+
* @returns {this}
|
|
325
|
+
* @remarks Complexity: O(|names|).
|
|
326
|
+
*/
|
|
327
|
+
setNodes(vs, value) {
|
|
328
|
+
var args = arguments;
|
|
329
|
+
var self = this;
|
|
330
|
+
forEach(vs, function(v) {
|
|
331
|
+
if (args.length > 1) {
|
|
332
|
+
self.setNode(v, value);
|
|
333
|
+
} else {
|
|
334
|
+
self.setNode(v);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
return this;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Creates or updates the value for the node `v` in the graph.
|
|
341
|
+
*
|
|
342
|
+
* @param {NodeID | number} v - ID of the node to create/set.
|
|
343
|
+
* @param {NodeLabel} [value] - If supplied, it is set as the value for the node.
|
|
344
|
+
* If not supplied and the node was created by this call then
|
|
345
|
+
* {@link setDefaultNodeLabel} will be used to set the node's value.
|
|
346
|
+
* @returns {this} the graph, allowing this to be chained with other functions.
|
|
347
|
+
* @remarks Takes `O(1)` time.
|
|
348
|
+
*/
|
|
349
|
+
setNode(v, value) {
|
|
350
|
+
if (Object.prototype.hasOwnProperty.call(this._nodes, v)) {
|
|
351
|
+
if (arguments.length > 1) {
|
|
352
|
+
this._nodes[v] = value;
|
|
353
|
+
}
|
|
354
|
+
return this;
|
|
355
|
+
}
|
|
356
|
+
this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
|
|
357
|
+
if (this._isCompound) {
|
|
358
|
+
this._parent[v] = GRAPH_NODE;
|
|
359
|
+
this._children[v] = {};
|
|
360
|
+
this._children[GRAPH_NODE][v] = true;
|
|
361
|
+
}
|
|
362
|
+
this._in[v] = {};
|
|
363
|
+
this._preds[v] = {};
|
|
364
|
+
this._out[v] = {};
|
|
365
|
+
this._sucs[v] = {};
|
|
366
|
+
++this._nodeCount;
|
|
367
|
+
return this;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Gets the label of node with specified name.
|
|
371
|
+
*
|
|
372
|
+
* @param {NodeID | number} v - Node ID.
|
|
373
|
+
* @returns {NodeLabel | undefined} the label assigned to the node with the id `v`
|
|
374
|
+
* if it is in the graph.
|
|
375
|
+
* Otherwise returns `undefined`.
|
|
376
|
+
* @remarks Takes `O(1)` time.
|
|
377
|
+
*/
|
|
378
|
+
node(v) {
|
|
379
|
+
return this._nodes[v];
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Detects whether graph has a node with specified name or not.
|
|
383
|
+
*
|
|
384
|
+
* @param {NodeID | number} v - Node ID.
|
|
385
|
+
* @returns {boolean} Returns `true` the graph has a node with the id.
|
|
386
|
+
* @remarks Takes `O(1)` time.
|
|
387
|
+
*/
|
|
388
|
+
hasNode(v) {
|
|
389
|
+
return Object.prototype.hasOwnProperty.call(this._nodes, v);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Remove the node with the id `v` in the graph or do nothing if the node is
|
|
393
|
+
* not in the graph.
|
|
394
|
+
*
|
|
395
|
+
* If the node was removed this function also removes any incident edges.
|
|
396
|
+
*
|
|
397
|
+
* @param {NodeID | number} v - Node ID to remove.
|
|
398
|
+
* @returns {this} the graph, allowing this to be chained with other functions.
|
|
399
|
+
* @remarks Takes `O(|E|)` time.
|
|
400
|
+
*/
|
|
401
|
+
removeNode(v) {
|
|
402
|
+
if (Object.prototype.hasOwnProperty.call(this._nodes, v)) {
|
|
403
|
+
var removeEdge = (e) => this.removeEdge(this._edgeObjs[e]);
|
|
404
|
+
delete this._nodes[v];
|
|
405
|
+
if (this._isCompound) {
|
|
406
|
+
this._removeFromParentsChildList(v);
|
|
407
|
+
delete this._parent[v];
|
|
408
|
+
forEach(this.children(v), (child) => {
|
|
409
|
+
this.setParent(child);
|
|
410
|
+
});
|
|
411
|
+
delete this._children[v];
|
|
412
|
+
}
|
|
413
|
+
forEach(keys(this._in[v]), removeEdge);
|
|
414
|
+
delete this._in[v];
|
|
415
|
+
delete this._preds[v];
|
|
416
|
+
forEach(keys(this._out[v]), removeEdge);
|
|
417
|
+
delete this._out[v];
|
|
418
|
+
delete this._sucs[v];
|
|
419
|
+
--this._nodeCount;
|
|
420
|
+
}
|
|
421
|
+
return this;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Sets the parent for `v` to `parent` if it is defined or removes the parent
|
|
425
|
+
* for `v` if `parent` is undefined.
|
|
426
|
+
*
|
|
427
|
+
* @param {NodeID | number} v - Node ID to set the parent for.
|
|
428
|
+
* @param {NodeID | number} [parent] - Parent node ID. If not defined, removes the parent.
|
|
429
|
+
* @returns {this} the graph, allowing this to be chained with other functions.
|
|
430
|
+
* @throws if the graph is not compound.
|
|
431
|
+
* @throws if setting the parent would create a cycle.
|
|
432
|
+
* @remarks Takes `O(1)` time.
|
|
433
|
+
*/
|
|
434
|
+
setParent(v, parent) {
|
|
435
|
+
if (!this._isCompound) {
|
|
436
|
+
throw new Error("Cannot set parent in a non-compound graph");
|
|
437
|
+
}
|
|
438
|
+
if (isUndefined(parent)) {
|
|
439
|
+
parent = GRAPH_NODE;
|
|
440
|
+
} else {
|
|
441
|
+
parent += "";
|
|
442
|
+
for (var ancestor = parent; !isUndefined(ancestor); ancestor = this.parent(ancestor)) {
|
|
443
|
+
if (ancestor === v) {
|
|
444
|
+
throw new Error("Setting " + parent + " as parent of " + v + " would create a cycle");
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
this.setNode(parent);
|
|
448
|
+
}
|
|
449
|
+
this.setNode(v);
|
|
450
|
+
this._removeFromParentsChildList(v);
|
|
451
|
+
this._parent[v] = parent;
|
|
452
|
+
this._children[parent][v] = true;
|
|
453
|
+
return this;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* @private
|
|
457
|
+
* @param {NodeID | number} v - Node ID.
|
|
458
|
+
*/
|
|
459
|
+
_removeFromParentsChildList(v) {
|
|
460
|
+
delete this._children[this._parent[v]][v];
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Get parent node for node `v`.
|
|
464
|
+
*
|
|
465
|
+
* @param {NodeID | number} v - Node ID.
|
|
466
|
+
* @returns {NodeID | undefined} the node that is a parent of node `v`
|
|
467
|
+
* or `undefined` if node `v` does not have a parent or is not a member of
|
|
468
|
+
* the graph.
|
|
469
|
+
* Always returns `undefined` for graphs that are not compound.
|
|
470
|
+
* @remarks Takes `O(1)` time.
|
|
471
|
+
*/
|
|
472
|
+
parent(v) {
|
|
473
|
+
if (this._isCompound) {
|
|
474
|
+
var parent = this._parent[v];
|
|
475
|
+
if (parent !== GRAPH_NODE) {
|
|
476
|
+
return parent;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Gets list of direct children of node v.
|
|
482
|
+
*
|
|
483
|
+
* @param {NodeID | number} [v] - Node ID. If not specified, gets nodes
|
|
484
|
+
* with no parent (top-level nodes).
|
|
485
|
+
* @returns {NodeID[] | undefined} all nodes that are children of node `v` or
|
|
486
|
+
* `undefined` if node `v` is not in the graph.
|
|
487
|
+
* Always returns `[]` for graphs that are not compound.
|
|
488
|
+
* @remarks Takes `O(|V|)` time.
|
|
489
|
+
*/
|
|
490
|
+
children(v) {
|
|
491
|
+
if (isUndefined(v)) {
|
|
492
|
+
v = GRAPH_NODE;
|
|
493
|
+
}
|
|
494
|
+
if (this._isCompound) {
|
|
495
|
+
var children = this._children[v];
|
|
496
|
+
if (children) {
|
|
497
|
+
return keys(children);
|
|
498
|
+
}
|
|
499
|
+
} else if (v === GRAPH_NODE) {
|
|
500
|
+
return this.nodes();
|
|
501
|
+
} else if (this.hasNode(v)) {
|
|
502
|
+
return [];
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* @param {NodeID | number} v - Node ID.
|
|
507
|
+
* @returns {NodeID[] | undefined} all nodes that are predecessors of the
|
|
508
|
+
* specified node or `undefined` if node `v` is not in the graph.
|
|
509
|
+
* @remarks
|
|
510
|
+
* Behavior is undefined for undirected graphs - use {@link neighbors} instead.
|
|
511
|
+
* Takes `O(|V|)` time.
|
|
512
|
+
*/
|
|
513
|
+
predecessors(v) {
|
|
514
|
+
var predsV = this._preds[v];
|
|
515
|
+
if (predsV) {
|
|
516
|
+
return keys(predsV);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* @param {NodeID | number} v - Node ID.
|
|
521
|
+
* @returns {NodeID[] | undefined} all nodes that are successors of the
|
|
522
|
+
* specified node or `undefined` if node `v` is not in the graph.
|
|
523
|
+
* @remarks
|
|
524
|
+
* Behavior is undefined for undirected graphs - use {@link neighbors} instead.
|
|
525
|
+
* Takes `O(|V|)` time.
|
|
526
|
+
*/
|
|
527
|
+
successors(v) {
|
|
528
|
+
var sucsV = this._sucs[v];
|
|
529
|
+
if (sucsV) {
|
|
530
|
+
return keys(sucsV);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* @param {NodeID | number} v - Node ID.
|
|
535
|
+
* @returns {NodeID[] | undefined} all nodes that are predecessors or
|
|
536
|
+
* successors of the specified node
|
|
537
|
+
* or `undefined` if node `v` is not in the graph.
|
|
538
|
+
* @remarks Takes `O(|V|)` time.
|
|
539
|
+
*/
|
|
540
|
+
neighbors(v) {
|
|
541
|
+
var preds = this.predecessors(v);
|
|
542
|
+
if (preds) {
|
|
543
|
+
return union(preds, this.successors(v));
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* @param {NodeID | number} v - Node ID.
|
|
548
|
+
* @returns {boolean} True if the node is a leaf (has no successors), false otherwise.
|
|
549
|
+
*/
|
|
550
|
+
isLeaf(v) {
|
|
551
|
+
var neighbors;
|
|
552
|
+
if (this.isDirected()) {
|
|
553
|
+
neighbors = this.successors(v);
|
|
554
|
+
} else {
|
|
555
|
+
neighbors = this.neighbors(v);
|
|
556
|
+
}
|
|
557
|
+
return neighbors.length === 0;
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Creates new graph with nodes filtered via `filter`.
|
|
561
|
+
* Edges incident to rejected node
|
|
562
|
+
* are also removed.
|
|
563
|
+
*
|
|
564
|
+
* In case of compound graph, if parent is rejected by `filter`,
|
|
565
|
+
* than all its children are rejected too.
|
|
566
|
+
|
|
567
|
+
* @param {(v: NodeID) => boolean} filter - Function that returns `true` for nodes to keep.
|
|
568
|
+
* @returns {Graph<GraphLabel, NodeLabel, EdgeLabel>} A new graph containing only the nodes for which `filter` returns `true`.
|
|
569
|
+
* @remarks Average-case complexity: O(|E|+|V|).
|
|
570
|
+
*/
|
|
571
|
+
filterNodes(filter2) {
|
|
572
|
+
var copy = new this.constructor({
|
|
573
|
+
directed: this._isDirected,
|
|
574
|
+
multigraph: this._isMultigraph,
|
|
575
|
+
compound: this._isCompound
|
|
576
|
+
});
|
|
577
|
+
copy.setGraph(this.graph());
|
|
578
|
+
var self = this;
|
|
579
|
+
forEach(this._nodes, function(value, v) {
|
|
580
|
+
if (filter2(v)) {
|
|
581
|
+
copy.setNode(v, value);
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
forEach(this._edgeObjs, function(e) {
|
|
585
|
+
if (copy.hasNode(e.v) && copy.hasNode(e.w)) {
|
|
586
|
+
copy.setEdge(e, self.edge(e));
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
var parents = {};
|
|
590
|
+
function findParent(v) {
|
|
591
|
+
var parent = self.parent(v);
|
|
592
|
+
if (parent === void 0 || copy.hasNode(parent)) {
|
|
593
|
+
parents[v] = parent;
|
|
594
|
+
return parent;
|
|
595
|
+
} else if (parent in parents) {
|
|
596
|
+
return parents[parent];
|
|
597
|
+
} else {
|
|
598
|
+
return findParent(parent);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (this._isCompound) {
|
|
602
|
+
forEach(copy.nodes(), function(v) {
|
|
603
|
+
copy.setParent(v, findParent(v));
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
return copy;
|
|
607
|
+
}
|
|
608
|
+
/* === Edge functions ========== */
|
|
609
|
+
/**
|
|
610
|
+
* Sets a new default value that is assigned to edges that are created without
|
|
611
|
+
* a label.
|
|
612
|
+
*
|
|
613
|
+
* @param {typeof this._defaultEdgeLabelFn | EdgeLabel} newDefault - If a function,
|
|
614
|
+
* it is called with the parameters `(v, w, name)`.
|
|
615
|
+
* Otherwise, it is assigned as the label directly.
|
|
616
|
+
* @returns {this}
|
|
617
|
+
*/
|
|
618
|
+
setDefaultEdgeLabel(newDefault) {
|
|
619
|
+
if (!isFunction(newDefault)) {
|
|
620
|
+
newDefault = constant(newDefault);
|
|
621
|
+
}
|
|
622
|
+
this._defaultEdgeLabelFn = newDefault;
|
|
623
|
+
return this;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* @returns {number} the number of edges in the graph.
|
|
627
|
+
* @remarks Complexity: O(1).
|
|
628
|
+
*/
|
|
629
|
+
edgeCount() {
|
|
630
|
+
return this._edgeCount;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Gets edges of the graph.
|
|
634
|
+
*
|
|
635
|
+
* @returns {EdgeObj[]} the {@link EdgeObj} for each edge in the graph.
|
|
636
|
+
*
|
|
637
|
+
* @remarks
|
|
638
|
+
* In case of compound graph subgraphs are not considered.
|
|
639
|
+
* Use {@link edge()} to get the label for each edge.
|
|
640
|
+
* Takes `O(|E|)` time.
|
|
641
|
+
*/
|
|
642
|
+
edges() {
|
|
643
|
+
return values(this._edgeObjs);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Establish an edges path over the nodes in nodes list.
|
|
647
|
+
*
|
|
648
|
+
* If some edge is already exists, it will update its label, otherwise it will
|
|
649
|
+
* create an edge between pair of nodes with label provided or default label
|
|
650
|
+
* if no label provided.
|
|
651
|
+
*
|
|
652
|
+
* @param {Collection<NodeID>} vs - List of node IDs to create edges between.
|
|
653
|
+
* @param {EdgeLabel} [value] - If set, update all edges with this value.
|
|
654
|
+
* @returns {this}
|
|
655
|
+
* @remarks Complexity: O(|nodes|).
|
|
656
|
+
*/
|
|
657
|
+
setPath(vs, value) {
|
|
658
|
+
var self = this;
|
|
659
|
+
var args = arguments;
|
|
660
|
+
reduce(vs, function(v, w) {
|
|
661
|
+
if (args.length > 1) {
|
|
662
|
+
self.setEdge(v, w, value);
|
|
663
|
+
} else {
|
|
664
|
+
self.setEdge(v, w);
|
|
665
|
+
}
|
|
666
|
+
return w;
|
|
667
|
+
});
|
|
668
|
+
return this;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Creates or updates the label for the edge (`v`, `w`) with the optionally
|
|
672
|
+
* supplied `name`.
|
|
673
|
+
*
|
|
674
|
+
* @overload
|
|
675
|
+
* @param {EdgeObj} arg0 - Edge object.
|
|
676
|
+
* @param {EdgeLabel} [value] - If supplied, it is set as the label for the edge.
|
|
677
|
+
* If not supplied and the edge was created by this call then
|
|
678
|
+
* {@link setDefaultEdgeLabel} will be used to assign the edge's label.
|
|
679
|
+
* @returns {this} the graph, allowing this to be chained with other functions.
|
|
680
|
+
* @remarks Takes `O(1)` time.
|
|
681
|
+
*/
|
|
682
|
+
/**
|
|
683
|
+
* Creates or updates the label for the edge (`v`, `w`) with the optionally
|
|
684
|
+
* supplied `name`.
|
|
685
|
+
*
|
|
686
|
+
* @overload
|
|
687
|
+
* @param {NodeID | number} v - Source node ID. Number values will be coerced to strings.
|
|
688
|
+
* @param {NodeID | number} w - Target node ID. Number values will be coerced to strings.
|
|
689
|
+
* @param {EdgeLabel} [value] - If supplied, it is set as the label for the edge.
|
|
690
|
+
* If not supplied and the edge was created by this call then
|
|
691
|
+
* {@link setDefaultEdgeLabel} will be used to assign the edge's label.
|
|
692
|
+
* @param {string | number} [name] - Edge name. Only useful with multigraphs.
|
|
693
|
+
* @returns {this} the graph, allowing this to be chained with other functions.
|
|
694
|
+
* @remarks Takes `O(1)` time.
|
|
695
|
+
*/
|
|
696
|
+
setEdge() {
|
|
697
|
+
var v, w, name, value;
|
|
698
|
+
var valueSpecified = false;
|
|
699
|
+
var arg0 = arguments[0];
|
|
700
|
+
if (typeof arg0 === "object" && arg0 !== null && "v" in arg0) {
|
|
701
|
+
v = arg0.v;
|
|
702
|
+
w = arg0.w;
|
|
703
|
+
name = arg0.name;
|
|
704
|
+
if (arguments.length === 2) {
|
|
705
|
+
value = arguments[1];
|
|
706
|
+
valueSpecified = true;
|
|
707
|
+
}
|
|
708
|
+
} else {
|
|
709
|
+
v = arg0;
|
|
710
|
+
w = arguments[1];
|
|
711
|
+
name = arguments[3];
|
|
712
|
+
if (arguments.length > 2) {
|
|
713
|
+
value = arguments[2];
|
|
714
|
+
valueSpecified = true;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
v = "" + v;
|
|
718
|
+
w = "" + w;
|
|
719
|
+
if (!isUndefined(name)) {
|
|
720
|
+
name = "" + name;
|
|
721
|
+
}
|
|
722
|
+
var e = edgeArgsToId(this._isDirected, v, w, name);
|
|
723
|
+
if (Object.prototype.hasOwnProperty.call(this._edgeLabels, e)) {
|
|
724
|
+
if (valueSpecified) {
|
|
725
|
+
this._edgeLabels[e] = value;
|
|
726
|
+
}
|
|
727
|
+
return this;
|
|
728
|
+
}
|
|
729
|
+
if (!isUndefined(name) && !this._isMultigraph) {
|
|
730
|
+
throw new Error("Cannot set a named edge when isMultigraph = false");
|
|
731
|
+
}
|
|
732
|
+
this.setNode(v);
|
|
733
|
+
this.setNode(w);
|
|
734
|
+
this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name);
|
|
735
|
+
var edgeObj = edgeArgsToObj(this._isDirected, v, w, name);
|
|
736
|
+
v = edgeObj.v;
|
|
737
|
+
w = edgeObj.w;
|
|
738
|
+
Object.freeze(edgeObj);
|
|
739
|
+
this._edgeObjs[e] = edgeObj;
|
|
740
|
+
incrementOrInitEntry(this._preds[w], v);
|
|
741
|
+
incrementOrInitEntry(this._sucs[v], w);
|
|
742
|
+
this._in[w][e] = edgeObj;
|
|
743
|
+
this._out[v][e] = edgeObj;
|
|
744
|
+
this._edgeCount++;
|
|
745
|
+
return this;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Gets the label for the specified edge.
|
|
749
|
+
*
|
|
750
|
+
* @overload
|
|
751
|
+
* @param {EdgeObj} v - Edge object.
|
|
752
|
+
* @returns {EdgeLabel | undefined} the label for the edge (`v`, `w`) if the
|
|
753
|
+
* graph has an edge between `v` and `w` with the optional `name`.
|
|
754
|
+
* Returned `undefined` if there is no such edge in the graph.
|
|
755
|
+
* @remarks
|
|
756
|
+
* `v` and `w` can be interchanged for undirected graphs.
|
|
757
|
+
* Takes `O(1)` time.
|
|
758
|
+
*/
|
|
759
|
+
/**
|
|
760
|
+
* Gets the label for the specified edge.
|
|
761
|
+
*
|
|
762
|
+
* @overload
|
|
763
|
+
* @param {NodeID | number} v - Source node ID.
|
|
764
|
+
* @param {NodeID | number} w - Target node ID.
|
|
765
|
+
* @param {string | number} [name] - Edge name. Only useful with multigraphs.
|
|
766
|
+
* @returns {EdgeLabel | undefined} the label for the edge (`v`, `w`) if the
|
|
767
|
+
* graph has an edge between `v` and `w` with the optional `name`.
|
|
768
|
+
* Returned `undefined` if there is no such edge in the graph.
|
|
769
|
+
* @remarks
|
|
770
|
+
* `v` and `w` can be interchanged for undirected graphs.
|
|
771
|
+
* Takes `O(1)` time.
|
|
772
|
+
*/
|
|
773
|
+
edge(v, w, name) {
|
|
774
|
+
var e = arguments.length === 1 ? edgeObjToId(this._isDirected, arguments[0]) : edgeArgsToId(this._isDirected, v, w, name);
|
|
775
|
+
return this._edgeLabels[e];
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Detects whether the graph contains specified edge or not.
|
|
779
|
+
*
|
|
780
|
+
* @overload
|
|
781
|
+
* @param {EdgeObj} v - Edge object.
|
|
782
|
+
* @returns {boolean} `true` if the graph has an edge between `v` and `w`
|
|
783
|
+
* with the optional `name`.
|
|
784
|
+
* @remarks
|
|
785
|
+
* `v` and `w` can be interchanged for undirected graphs.
|
|
786
|
+
* No subgraphs are considered.
|
|
787
|
+
* Takes `O(1)` time.
|
|
788
|
+
*/
|
|
789
|
+
/**
|
|
790
|
+
* Detects whether the graph contains specified edge or not.
|
|
791
|
+
*
|
|
792
|
+
* @overload
|
|
793
|
+
* @param {NodeID | number} v - Source node ID.
|
|
794
|
+
* @param {NodeID | number} w - Target node ID.
|
|
795
|
+
* @param {string | number} [name] - Edge name. Only useful with multigraphs.
|
|
796
|
+
* @returns {boolean} `true` if the graph has an edge between `v` and `w`
|
|
797
|
+
* with the optional `name`.
|
|
798
|
+
* @remarks
|
|
799
|
+
* `v` and `w` can be interchanged for undirected graphs.
|
|
800
|
+
* No subgraphs are considered.
|
|
801
|
+
* Takes `O(1)` time.
|
|
802
|
+
*/
|
|
803
|
+
hasEdge(v, w, name) {
|
|
804
|
+
var e = arguments.length === 1 ? edgeObjToId(this._isDirected, arguments[0]) : edgeArgsToId(this._isDirected, v, w, name);
|
|
805
|
+
return Object.prototype.hasOwnProperty.call(this._edgeLabels, e);
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Removes the edge (`v`, `w`) if the graph has an edge between `v` and `w`
|
|
809
|
+
* with the optional `name`. If not this function does nothing.
|
|
810
|
+
*
|
|
811
|
+
* @overload
|
|
812
|
+
* @param {EdgeObj} v - Edge object.
|
|
813
|
+
* @returns {this}
|
|
814
|
+
* @remarks
|
|
815
|
+
* `v` and `w` can be interchanged for undirected graphs.
|
|
816
|
+
* No subgraphs are considered.
|
|
817
|
+
* Takes `O(1)` time.
|
|
818
|
+
*/
|
|
819
|
+
/**
|
|
820
|
+
* Removes the edge (`v`, `w`) if the graph has an edge between `v` and `w`
|
|
821
|
+
* with the optional `name`. If not this function does nothing.
|
|
822
|
+
*
|
|
823
|
+
* @overload
|
|
824
|
+
* @param {NodeID | number} v - Source node ID.
|
|
825
|
+
* @param {NodeID | number} w - Target node ID.
|
|
826
|
+
* @param {string | number} [name] - Edge name. Only useful with multigraphs.
|
|
827
|
+
* @returns {this}
|
|
828
|
+
* @remarks
|
|
829
|
+
* `v` and `w` can be interchanged for undirected graphs.
|
|
830
|
+
* Takes `O(1)` time.
|
|
831
|
+
*/
|
|
832
|
+
removeEdge(v, w, name) {
|
|
833
|
+
var e = arguments.length === 1 ? edgeObjToId(this._isDirected, arguments[0]) : edgeArgsToId(this._isDirected, v, w, name);
|
|
834
|
+
var edge = this._edgeObjs[e];
|
|
835
|
+
if (edge) {
|
|
836
|
+
v = edge.v;
|
|
837
|
+
w = edge.w;
|
|
838
|
+
delete this._edgeLabels[e];
|
|
839
|
+
delete this._edgeObjs[e];
|
|
840
|
+
decrementOrRemoveEntry(this._preds[w], v);
|
|
841
|
+
decrementOrRemoveEntry(this._sucs[v], w);
|
|
842
|
+
delete this._in[w][e];
|
|
843
|
+
delete this._out[v][e];
|
|
844
|
+
this._edgeCount--;
|
|
845
|
+
}
|
|
846
|
+
return this;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* @param {NodeID | number} v - Target node ID.
|
|
850
|
+
* @param {NodeID | number} [u] - Optionally filters edges down to just those
|
|
851
|
+
* coming from node `u`.
|
|
852
|
+
* @returns {EdgeObj[] | undefined} all edges that point to the node `v`.
|
|
853
|
+
* Returns `undefined` if node `v` is not in the graph.
|
|
854
|
+
* @remarks
|
|
855
|
+
* Behavior is undefined for undirected graphs - use {@link nodeEdges} instead.
|
|
856
|
+
* Takes `O(|E|)` time.
|
|
857
|
+
*/
|
|
858
|
+
inEdges(v, u) {
|
|
859
|
+
var inV = this._in[v];
|
|
860
|
+
if (inV) {
|
|
861
|
+
var edges = values(inV);
|
|
862
|
+
if (!u) {
|
|
863
|
+
return edges;
|
|
864
|
+
}
|
|
865
|
+
return filter(edges, function(edge) {
|
|
866
|
+
return edge.v === u;
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* @param {NodeID | number} v - Target node ID.
|
|
872
|
+
* @param {NodeID | number} [w] - Optionally filters edges down to just those
|
|
873
|
+
* that point to `w`.
|
|
874
|
+
* @returns {EdgeObj[] | undefined} all edges that point to the node `v`.
|
|
875
|
+
* Returns `undefined` if node `v` is not in the graph.
|
|
876
|
+
* @remarks
|
|
877
|
+
* Behavior is undefined for undirected graphs - use {@link nodeEdges} instead.
|
|
878
|
+
* Takes `O(|E|)` time.
|
|
879
|
+
*/
|
|
880
|
+
outEdges(v, w) {
|
|
881
|
+
var outV = this._out[v];
|
|
882
|
+
if (outV) {
|
|
883
|
+
var edges = values(outV);
|
|
884
|
+
if (!w) {
|
|
885
|
+
return edges;
|
|
886
|
+
}
|
|
887
|
+
return filter(edges, function(edge) {
|
|
888
|
+
return edge.w === w;
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* @param {NodeID | number} v - Target Node ID.
|
|
894
|
+
* @param {NodeID | number} [w] - If set, filters those edges down to just
|
|
895
|
+
* those between nodes `v` and `w` regardless of direction
|
|
896
|
+
* @returns {EdgeObj[] | undefined} all edges to or from node `v` regardless
|
|
897
|
+
* of direction. Returns `undefined` if node `v` is not in the graph.
|
|
898
|
+
* @remarks Takes `O(|E|)` time.
|
|
899
|
+
*/
|
|
900
|
+
nodeEdges(v, w) {
|
|
901
|
+
var inEdges = this.inEdges(v, w);
|
|
902
|
+
if (inEdges) {
|
|
903
|
+
return inEdges.concat(this.outEdges(v, w));
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
Graph.prototype._nodeCount = 0;
|
|
908
|
+
Graph.prototype._edgeCount = 0;
|
|
909
|
+
function incrementOrInitEntry(map, k) {
|
|
910
|
+
if (map[k]) {
|
|
911
|
+
map[k]++;
|
|
912
|
+
} else {
|
|
913
|
+
map[k] = 1;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
function decrementOrRemoveEntry(map, k) {
|
|
917
|
+
if (!--map[k]) {
|
|
918
|
+
delete map[k];
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
function edgeArgsToId(isDirected, v_, w_, name) {
|
|
922
|
+
var v = "" + v_;
|
|
923
|
+
var w = "" + w_;
|
|
924
|
+
if (!isDirected && v > w) {
|
|
925
|
+
var tmp = v;
|
|
926
|
+
v = w;
|
|
927
|
+
w = tmp;
|
|
928
|
+
}
|
|
929
|
+
return v + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM + (isUndefined(name) ? DEFAULT_EDGE_NAME : name);
|
|
930
|
+
}
|
|
931
|
+
function edgeArgsToObj(isDirected, v_, w_, name) {
|
|
932
|
+
var v = "" + v_;
|
|
933
|
+
var w = "" + w_;
|
|
934
|
+
if (!isDirected && v > w) {
|
|
935
|
+
var tmp = v;
|
|
936
|
+
v = w;
|
|
937
|
+
w = tmp;
|
|
938
|
+
}
|
|
939
|
+
var edgeObj = { v, w };
|
|
940
|
+
if (name) {
|
|
941
|
+
edgeObj.name = name;
|
|
942
|
+
}
|
|
943
|
+
return edgeObj;
|
|
944
|
+
}
|
|
945
|
+
function edgeObjToId(isDirected, edgeObj) {
|
|
946
|
+
return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name);
|
|
947
|
+
}
|
|
948
|
+
export {
|
|
949
|
+
Graph as G,
|
|
950
|
+
baseClone as b,
|
|
951
|
+
isUndefined as i,
|
|
952
|
+
values as v
|
|
953
|
+
};
|