occam-directed-graphs 3.0.37 → 3.0.41
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/README.md +34 -49
- package/lib/cycle.js +31 -14
- package/lib/directedGraph.js +215 -201
- package/lib/index.js +9 -1
- package/lib/utilities/index.js +40 -0
- package/lib/utilities/search.js +91 -0
- package/lib/utilities/vertex.js +11 -50
- package/lib/vertex.js +88 -251
- package/package.json +6 -7
- package/src/cycle.js +8 -28
- package/src/directedGraph.js +277 -198
- package/src/index.js +2 -0
- package/src/utilities/index.js +25 -0
- package/src/utilities/search.js +69 -0
- package/src/utilities/vertex.js +6 -61
- package/src/vertex.js +92 -261
- package/test/cirectedGraph.js +589 -0
- package/bin/main.js +0 -15
- package/lib/directedAcyclicGraph.js +0 -364
- package/lib/example.js +0 -21
- package/lib/partialCycle.js +0 -102
- package/lib/utilities/edge.js +0 -65
- package/src/directedAcyclicGraph.js +0 -422
- package/src/example.js +0 -22
- package/src/partialCycle.js +0 -69
- package/src/utilities/edge.js +0 -58
package/src/directedGraph.js
CHANGED
|
@@ -4,307 +4,386 @@ import { arrayUtilities } from "necessary";
|
|
|
4
4
|
|
|
5
5
|
import Edge from "./edge";
|
|
6
6
|
import Cycle from "./cycle";
|
|
7
|
-
import
|
|
8
|
-
import DirectedAcyclicGraph from "./directedAcyclicGraph";
|
|
7
|
+
import Vertex from "./vertex";
|
|
9
8
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { orderIndexes, indexesFromVertexes } from "./utilities/index";
|
|
10
|
+
import { orderVertexes, vertexNamesFromVertexes } from "./utilities/vertex";
|
|
12
11
|
|
|
13
|
-
const { first
|
|
12
|
+
const { first } = arrayUtilities;
|
|
14
13
|
|
|
15
14
|
export default class DirectedGraph {
|
|
16
|
-
constructor(
|
|
17
|
-
this.
|
|
18
|
-
|
|
19
|
-
this.directedAcyclicGraph = directedAcyclicGraph;
|
|
15
|
+
constructor(vertexMap) {
|
|
16
|
+
this.vertexMap = vertexMap;
|
|
20
17
|
}
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
return this.
|
|
19
|
+
getVertexNap() {
|
|
20
|
+
return this.vertexMap;
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
getVertexes() {
|
|
24
|
+
const vertexMapValues = Object.values(this.vertexMap),
|
|
25
|
+
vertexes = vertexMapValues; ///
|
|
26
|
+
|
|
27
|
+
return vertexes;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
getVertexNames() {
|
|
30
|
+
getVertexNames() {
|
|
31
|
+
const vertexMapKeys = Object.keys(this.vertexMap),
|
|
32
|
+
vertexNames = vertexMapKeys; ///
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
return vertexNames;
|
|
35
|
+
}
|
|
33
36
|
|
|
34
|
-
|
|
37
|
+
getOrderedVertexNames() {
|
|
38
|
+
const vertexes = this.getVertexes();
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
orderVertexes(vertexes);
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
const orderedVertexes = vertexes, ///
|
|
43
|
+
orderedVertexNames = vertexNamesFromVertexes(orderedVertexes);
|
|
39
44
|
|
|
40
|
-
|
|
45
|
+
return orderedVertexNames;
|
|
46
|
+
}
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
getVertexByVertexName(vertexName) {
|
|
49
|
+
const vertexPresent = this.isVertexPresentByVertexName(vertexName),
|
|
50
|
+
vertex = vertexPresent ?
|
|
51
|
+
this.vertexMap[vertexName] :
|
|
52
|
+
null;
|
|
43
53
|
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
return vertex;
|
|
55
|
+
}
|
|
46
56
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
57
|
+
getEdgesBySourceVertexName(sourceVertexName) {
|
|
58
|
+
const edges = [],
|
|
59
|
+
sourceVertex = this.getVertexByVertexName(sourceVertexName);
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
if (sourceVertex !== null) {
|
|
62
|
+
const immediateSuccessorVertexes = sourceVertex.getImmediateSuccessorVertexes(),
|
|
63
|
+
immediateSuccessorVertexNames = vertexNamesFromVertexes(immediateSuccessorVertexes),
|
|
64
|
+
targetVertexNames = immediateSuccessorVertexNames; ///
|
|
54
65
|
|
|
55
|
-
|
|
56
|
-
|
|
66
|
+
targetVertexNames.forEach((targetVertexName) => {
|
|
67
|
+
const edge = Edge.fromSourceVertexNameAndTargetVertexName(sourceVertexName, targetVertexName);
|
|
68
|
+
|
|
69
|
+
edges.push(edge);
|
|
57
70
|
});
|
|
58
71
|
}
|
|
59
72
|
|
|
60
|
-
return
|
|
73
|
+
return edges;
|
|
61
74
|
}
|
|
62
75
|
|
|
63
|
-
|
|
64
|
-
const
|
|
76
|
+
getEdgesByTargetVertexName(targetVertexName) {
|
|
77
|
+
const edges = [],
|
|
78
|
+
targetVertex = this.getVertexByVertexName(targetVertexName);
|
|
65
79
|
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
if (targetVertex !== null) {
|
|
81
|
+
const immediatePredecessorVertexes = targetVertex.getImmediatePredecessorVertexes(),
|
|
82
|
+
immediatePredecessorVertexNames = vertexNamesFromVertexes(immediatePredecessorVertexes),
|
|
83
|
+
sourceVertexNames = immediatePredecessorVertexNames; ///
|
|
69
84
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
immediateSuccessorVertexName = cyclicEdgeTargetVertexName; ///
|
|
85
|
+
sourceVertexNames.forEach((sourceVertexName) => {
|
|
86
|
+
const edge = Edge.fromSourceVertexNameAndTargetVertexName(sourceVertexName, targetVertexName);
|
|
73
87
|
|
|
74
|
-
|
|
75
|
-
}
|
|
88
|
+
edges.push(edge);
|
|
76
89
|
});
|
|
77
90
|
}
|
|
78
91
|
|
|
79
|
-
return
|
|
92
|
+
return edges;
|
|
80
93
|
}
|
|
81
94
|
|
|
82
|
-
|
|
83
|
-
let
|
|
95
|
+
getFirstCycle() {
|
|
96
|
+
let firstCycle = null;
|
|
97
|
+
|
|
98
|
+
const cyclesPresent = this.areCyclesPresent();
|
|
99
|
+
|
|
100
|
+
if (cyclesPresent) {
|
|
101
|
+
const cyclicEdges = this.getCyclicEdges(),
|
|
102
|
+
firstCyclicEdge = first(cyclicEdges),
|
|
103
|
+
sourceVertexName = firstCyclicEdge.getSourceVertexName(), ///
|
|
104
|
+
targetVertexName = firstCyclicEdge.getTargetVertexName(), ///
|
|
105
|
+
sourceVertex = this.getVertexByVertexName(sourceVertexName),
|
|
106
|
+
targetVertex = this.getVertexByVertexName(targetVertexName);
|
|
84
107
|
|
|
85
|
-
|
|
108
|
+
targetVertex.forwardsDepthFirstSearch((vertex, predecessorVertexes) => {
|
|
109
|
+
let terminate = false;
|
|
86
110
|
|
|
87
|
-
|
|
88
|
-
|
|
111
|
+
if (vertex === sourceVertex) {
|
|
112
|
+
terminate = true;
|
|
89
113
|
|
|
90
|
-
|
|
114
|
+
const cycle = Cycle.fromSourceVertexAndPredecessorVertexes(sourceVertex, predecessorVertexes); ///
|
|
115
|
+
|
|
116
|
+
firstCycle = cycle; ///
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return terminate;
|
|
120
|
+
});
|
|
91
121
|
}
|
|
92
122
|
|
|
93
|
-
return
|
|
123
|
+
return firstCycle;
|
|
94
124
|
}
|
|
95
125
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
partialCycles.push(partialCycle);
|
|
116
|
-
} else {
|
|
117
|
-
return true;
|
|
126
|
+
getCyclicEdges() {
|
|
127
|
+
const cyclicEdges = [],
|
|
128
|
+
vertexes = this.getVertexes();
|
|
129
|
+
|
|
130
|
+
vertexes.forEach((vertex) => {
|
|
131
|
+
const sourceVertex = vertex, ///
|
|
132
|
+
sourceVertexIndex = sourceVertex.getIndex();
|
|
133
|
+
|
|
134
|
+
vertex.forEachImmediateSuccessorVertex((immediateSuccessorVertex) => {
|
|
135
|
+
const targetVertex = immediateSuccessorVertex, ///
|
|
136
|
+
targetVertexIndex = targetVertex.getIndex();
|
|
137
|
+
|
|
138
|
+
if (targetVertexIndex < sourceVertexIndex) {
|
|
139
|
+
const sourceVertexName = sourceVertex.getName(),
|
|
140
|
+
targetVertexName = targetVertex.getName(),
|
|
141
|
+
edge = Edge.fromSourceVertexNameAndTargetVertexName(sourceVertexName, targetVertexName),
|
|
142
|
+
cyclicEdge = edge; ///
|
|
143
|
+
|
|
144
|
+
cyclicEdges.push(cyclicEdge);
|
|
118
145
|
}
|
|
119
146
|
});
|
|
120
147
|
|
|
121
|
-
|
|
122
|
-
terminate = (cyclicEdgesLength === 0);
|
|
123
|
-
|
|
124
|
-
return terminate;
|
|
148
|
+
sourceVertex
|
|
125
149
|
});
|
|
126
150
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
targetVertex = this.directedAcyclicGraph.getVertexByVertexName(targetVertexName);
|
|
151
|
+
return cyclicEdges;
|
|
152
|
+
}
|
|
130
153
|
|
|
131
|
-
|
|
132
|
-
|
|
154
|
+
areCyclesPresent() {
|
|
155
|
+
const vertexes = this.getVertexes(),
|
|
156
|
+
cyclesPresent = vertexes.some((vertex) => {
|
|
157
|
+
const sourceVertex = vertex, ///
|
|
158
|
+
sourceVertexIndex = sourceVertex.getIndex(),
|
|
159
|
+
cyclicEdgePresent = vertex.someImmediateSuccessorVertex((immediateSuccessorVertex) => {
|
|
160
|
+
const targetVertex = immediateSuccessorVertex, ///
|
|
161
|
+
targetVertexIndex = targetVertex.getIndex();
|
|
162
|
+
|
|
163
|
+
if (targetVertexIndex < sourceVertexIndex) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
if (cyclicEdgePresent) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
133
172
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
successorVertices = predecessorVertices, ///
|
|
137
|
-
cycle = Cycle.fromVertexNamePartialCycleAndSuccessorVertices(vertexName, partialCycle, successorVertices);
|
|
173
|
+
return cyclesPresent;
|
|
174
|
+
}
|
|
138
175
|
|
|
139
|
-
|
|
140
|
-
|
|
176
|
+
isEdgePresent(edge) {
|
|
177
|
+
let edgePresent = false;
|
|
141
178
|
|
|
142
|
-
|
|
143
|
-
|
|
179
|
+
const sourceVertexName = edge.getSourceVertexName(),
|
|
180
|
+
sourceVertex = this.getVertexByVertexName(sourceVertexName);
|
|
144
181
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
182
|
+
if (sourceVertex !== null) {
|
|
183
|
+
const targetVertexName = edge.getTargetVertexName(),
|
|
184
|
+
targetVertex = this.getVertexByVertexName(targetVertexName);
|
|
148
185
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
firstCycle = first(cycles);
|
|
186
|
+
if (targetVertex !== null) {
|
|
187
|
+
edgePresent = sourceVertex.isEdgePresentByTargetVertex(targetVertex);
|
|
188
|
+
}
|
|
153
189
|
}
|
|
154
190
|
|
|
155
|
-
return
|
|
191
|
+
return edgePresent;
|
|
156
192
|
}
|
|
157
193
|
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
vertexName = sourceVertexName, ///
|
|
163
|
-
firstCycle = this.getFirstCycleByVertexName(vertexName);
|
|
194
|
+
isVertexPresentByVertexName(vertexName) {
|
|
195
|
+
const vertexNames = this.getVertexNames(),
|
|
196
|
+
vertexNamesIncludesVertexName = vertexNames.includes(vertexName),
|
|
197
|
+
vertexPresent = vertexNamesIncludesVertexName; ///
|
|
164
198
|
|
|
165
|
-
return
|
|
199
|
+
return vertexPresent;
|
|
166
200
|
}
|
|
167
201
|
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
cyclesPresent = (cyclicEdgesLength > 0);
|
|
202
|
+
addVertexByVertexName(vertexName) {
|
|
203
|
+
const vertexPresent = this.isVertexPresentByVertexName(vertexName);
|
|
171
204
|
|
|
172
|
-
|
|
173
|
-
|
|
205
|
+
if (!vertexPresent) {
|
|
206
|
+
const vertexNames = this.getVertexNames(),
|
|
207
|
+
vertexNamesLength = vertexNames.length,
|
|
208
|
+
name = vertexName, ///
|
|
209
|
+
index = vertexNamesLength, ///
|
|
210
|
+
vertex = Vertex.fromNameAndIndex(name, index);
|
|
174
211
|
|
|
175
|
-
|
|
176
|
-
|
|
212
|
+
this.setVertexByVertexName(vertexName, vertex);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const vertex = this.getVertexByVertexName(vertexName);
|
|
216
|
+
|
|
217
|
+
return vertex;
|
|
177
218
|
}
|
|
178
219
|
|
|
179
220
|
removeVertexByVertexName(vertexName) {
|
|
180
|
-
this.
|
|
221
|
+
const vertexPresent = this.isVertexPresentByVertexName(vertexName);
|
|
181
222
|
|
|
182
|
-
|
|
183
|
-
|
|
223
|
+
if (!vertexPresent) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
184
226
|
|
|
185
|
-
|
|
186
|
-
|
|
227
|
+
const vertex = this.getVertexByVertexName(vertexName);
|
|
228
|
+
|
|
229
|
+
vertex.forEachImmediateSuccessorVertex((immediateSuccessVertex) => {
|
|
230
|
+
const immediatePredecessorVertex = vertex; ///
|
|
231
|
+
|
|
232
|
+
immediateSuccessVertex.removeImmediatePredecessorVertex(immediatePredecessorVertex);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
vertex.forEachImmediatePredecessorVertex((immediatePredecessorVertex) => {
|
|
236
|
+
const immediateSuccessVertex = vertex; ///
|
|
237
|
+
|
|
238
|
+
immediatePredecessorVertex.removeImmediateSuccessorVertex(immediateSuccessVertex);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
this.deleteVertexByVertexName(vertexName);
|
|
242
|
+
|
|
243
|
+
const vertexes = this.getVertexes(),
|
|
244
|
+
deletedVertex = vertex, ///
|
|
245
|
+
deletedVertexIndex = deletedVertex.getIndex();
|
|
246
|
+
|
|
247
|
+
vertexes.forEach((vertex) => {
|
|
248
|
+
const vertexIndex = vertex.getIndex();
|
|
249
|
+
|
|
250
|
+
if (vertexIndex > deletedVertexIndex) {
|
|
251
|
+
vertex.decrementIndex();
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
this.filterCyclicEdges();
|
|
187
256
|
}
|
|
188
257
|
|
|
189
258
|
addEdge(edge) {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
if (!success) {
|
|
193
|
-
const cyclicEdgesIncludesEdge = checkEdgesIncludesEdge(edge, this.cyclicEdges);
|
|
259
|
+
const sourceVertexName = edge.getSourceVertexName(),
|
|
260
|
+
targetVertexName = edge.getTargetVertexName();
|
|
194
261
|
|
|
195
|
-
|
|
196
|
-
|
|
262
|
+
if (sourceVertexName === targetVertexName) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
197
265
|
|
|
198
|
-
|
|
199
|
-
|
|
266
|
+
const sourceVertex = this.addVertexByVertexName(sourceVertexName),
|
|
267
|
+
targetVertex = this.addVertexByVertexName(targetVertexName),
|
|
268
|
+
edgePresent = sourceVertex.isEdgePresentByTargetVertex(targetVertex);
|
|
269
|
+
|
|
270
|
+
if (edgePresent) {
|
|
271
|
+
return;
|
|
200
272
|
}
|
|
273
|
+
|
|
274
|
+
const sourceVertexIndex = sourceVertex.getIndex(),
|
|
275
|
+
targetVertexIndex = targetVertex.getIndex();
|
|
276
|
+
|
|
277
|
+
if (sourceVertexIndex > targetVertexIndex) {
|
|
278
|
+
this.reorderVertexesBySourceVertexAndTargetVertex(sourceVertex, targetVertex);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const immediatePredecessorVertex = sourceVertex, ///
|
|
282
|
+
immediateSuccessorVertex = targetVertex; ///
|
|
283
|
+
|
|
284
|
+
immediatePredecessorVertex.addImmediateSuccessorVertex(immediateSuccessorVertex);
|
|
285
|
+
|
|
286
|
+
immediateSuccessorVertex.addImmediatePredecessorVertex(immediatePredecessorVertex);
|
|
201
287
|
}
|
|
202
|
-
|
|
288
|
+
|
|
203
289
|
addEdges(edges) {
|
|
204
|
-
edges.forEach((edge) =>
|
|
290
|
+
edges.forEach((edge) => {
|
|
291
|
+
this.addEdge(edge);
|
|
292
|
+
});
|
|
205
293
|
}
|
|
206
294
|
|
|
207
|
-
removeEdge(edge,
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
///
|
|
214
|
-
} else if (edgeCyclic) {
|
|
215
|
-
const cyclicEdge = edge; ///
|
|
216
|
-
|
|
217
|
-
removeEdgeFromEdges(cyclicEdge, this.cyclicEdges);
|
|
218
|
-
} else if (edgePresent) {
|
|
219
|
-
this.directedAcyclicGraph.removeEdge(edge);
|
|
220
|
-
|
|
221
|
-
if (removeStrandedVertices) {
|
|
222
|
-
const sourceVertexName = edge.getSourceVertexName(),
|
|
223
|
-
targetVertexName = edge.getTargetVertexName(),
|
|
224
|
-
sourceVertex = this.directedAcyclicGraph.getVertexByVertexName(sourceVertexName),
|
|
225
|
-
targetVertex = this.directedAcyclicGraph.getVertexByVertexName(targetVertexName),
|
|
226
|
-
sourceVertexStranded = sourceVertex.isStranded(),
|
|
227
|
-
targetVertexStranded = targetVertex.isStranded();
|
|
228
|
-
|
|
229
|
-
if (sourceVertexStranded) {
|
|
230
|
-
this.directedAcyclicGraph.removeVertexByVertexName(sourceVertexName);
|
|
231
|
-
}
|
|
295
|
+
removeEdge(edge, removeStrandedVertexes) {
|
|
296
|
+
const sourceVertexName = edge.getSourceVertexName(),
|
|
297
|
+
targetVertexName = edge.getTargetVertexName(),
|
|
298
|
+
sourceVertex = this.addVertexByVertexName(sourceVertexName),
|
|
299
|
+
targetVertex = this.addVertexByVertexName(targetVertexName),
|
|
300
|
+
edgePresent = sourceVertex.isEdgePresentByTargetVertex(targetVertex);
|
|
232
301
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
302
|
+
if (!edgePresent) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
sourceVertex.removeImmediateSuccessorVertex(targetVertex);
|
|
307
|
+
|
|
308
|
+
targetVertex.removeImmediatePredecessorVertex(sourceVertex);
|
|
309
|
+
|
|
310
|
+
if (removeStrandedVertexes) {
|
|
311
|
+
const sourceVertexStranded = sourceVertex.isStranded(),
|
|
312
|
+
targetVertexStranded = targetVertex.isStranded();
|
|
313
|
+
|
|
314
|
+
if (sourceVertexStranded) {
|
|
315
|
+
this.removeVertexByVertexName(sourceVertexName);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (targetVertexStranded) {
|
|
319
|
+
this.removeVertexByVertexName(targetVertexName);
|
|
236
320
|
}
|
|
237
321
|
}
|
|
238
322
|
|
|
239
323
|
this.filterCyclicEdges();
|
|
240
324
|
}
|
|
241
325
|
|
|
242
|
-
removeEdges(edges,
|
|
243
|
-
edges.forEach((edge) =>
|
|
326
|
+
removeEdges(edges, removeStrandedVertexes = false) {
|
|
327
|
+
edges.forEach((edge) => {
|
|
328
|
+
this.removeEdge(edge, removeStrandedVertexes);
|
|
329
|
+
});
|
|
244
330
|
}
|
|
245
331
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
this.addEdge(edge);
|
|
332
|
+
removeAllEdgesAndVertexes() {
|
|
333
|
+
this.vertexMap = {};
|
|
250
334
|
}
|
|
251
335
|
|
|
252
|
-
|
|
253
|
-
const
|
|
336
|
+
reorderVertexesBySourceVertexAndTargetVertex(sourceVertex, targetVertex) {
|
|
337
|
+
const sourceVertexReachable = targetVertex.isVertexReachable(sourceVertex);
|
|
254
338
|
|
|
255
|
-
|
|
256
|
-
|
|
339
|
+
if (sourceVertexReachable) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
257
342
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
edges = this.directedAcyclicGraph.getEdgesByTargetVertexName(targetVertexName);
|
|
343
|
+
const forwardsVisitedVertexes = targetVertex.retrieveForwardsVisitedVertexes(),
|
|
344
|
+
backwardsVisitedVertexes = sourceVertex.retrieveBackwardsVisitedVertexes();
|
|
261
345
|
|
|
262
|
-
|
|
346
|
+
orderVertexes(backwardsVisitedVertexes);
|
|
263
347
|
|
|
264
|
-
|
|
265
|
-
}
|
|
348
|
+
orderVertexes(forwardsVisitedVertexes);
|
|
266
349
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
350
|
+
const visitedVertexes = [
|
|
351
|
+
...backwardsVisitedVertexes,
|
|
352
|
+
...forwardsVisitedVertexes
|
|
353
|
+
],
|
|
354
|
+
visitedIndexes = indexesFromVertexes(visitedVertexes);
|
|
270
355
|
|
|
271
|
-
|
|
356
|
+
orderIndexes(visitedIndexes);
|
|
272
357
|
|
|
273
|
-
|
|
274
|
-
|
|
358
|
+
visitedVertexes.forEach((visitedVertex, index) => {
|
|
359
|
+
const visitedIndex = visitedIndexes[index];
|
|
275
360
|
|
|
276
|
-
|
|
277
|
-
this.directedAcyclicGraph = DirectedAcyclicGraph.fromNothing();
|
|
361
|
+
index = visitedIndex; ///
|
|
278
362
|
|
|
279
|
-
|
|
363
|
+
visitedVertex.setIndex(index);
|
|
364
|
+
});
|
|
280
365
|
}
|
|
281
366
|
|
|
282
367
|
filterCyclicEdges() {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
targetVertexName = cyclicEdge.getTargetVertexName(),
|
|
286
|
-
sourceVertexPresent = this.isVertexPresentByVertexName(sourceVertexName),
|
|
287
|
-
targetVertexPresent = this.isVertexPresentByVertexName(targetVertexName);
|
|
288
|
-
|
|
289
|
-
if (sourceVertexPresent && targetVertexPresent) {
|
|
290
|
-
return true;
|
|
291
|
-
}
|
|
292
|
-
});
|
|
368
|
+
const cyclicEdges = this.getCyclicEdges(),
|
|
369
|
+
edges = cyclicEdges; ///
|
|
293
370
|
|
|
294
|
-
|
|
295
|
-
const edge = cyclicEdge, ///
|
|
296
|
-
success = this.directedAcyclicGraph.addEdge(edge);
|
|
371
|
+
this.removeEdges(edges);
|
|
297
372
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
373
|
+
this.addEdges(edges);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
setVertexByVertexName(vertexName, vertex) {
|
|
377
|
+
this.vertexMap[vertexName] = vertex;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
deleteVertexByVertexName(vertexName) {
|
|
381
|
+
delete this.vertexMap[vertexName];
|
|
302
382
|
}
|
|
303
383
|
|
|
304
384
|
static fromNothing() {
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
directedGraph = new DirectedGraph(cyclicEdges, directedAcyclicGraph);
|
|
385
|
+
const vertexMap = {},
|
|
386
|
+
directedGraph = new DirectedGraph(vertexMap);
|
|
308
387
|
|
|
309
388
|
return directedGraph;
|
|
310
389
|
}
|
package/src/index.js
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export function orderIndexes(indexes) { ///
|
|
4
|
+
indexes.sort((firstIndex, secondIndex) => {
|
|
5
|
+
if (false) {
|
|
6
|
+
///
|
|
7
|
+
} else if (firstIndex < secondIndex) {
|
|
8
|
+
return -1;
|
|
9
|
+
} else if (firstIndex > secondIndex) {
|
|
10
|
+
return +1;
|
|
11
|
+
} else {
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function indexesFromVertexes(vertexes) {
|
|
18
|
+
const indexes = vertexes.map((vertex) => {
|
|
19
|
+
const index = vertex.getIndex();
|
|
20
|
+
|
|
21
|
+
return index;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return indexes;
|
|
25
|
+
}
|