mirror of
https://gitee.com/antv/g6.git
synced 2024-12-01 03:08:33 +08:00
feat: adjacency matrix in Algorithm. feat: floydShall shortest path in Algorithm.
This commit is contained in:
parent
2378d4eac9
commit
76af4f59f2
@ -126,4 +126,4 @@
|
||||
"webpack-cli": "^3.3.10",
|
||||
"worker-loader": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
40
src/algorithm/adjacent-matrix.ts
Normal file
40
src/algorithm/adjacent-matrix.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { IGraph } from '../interface/graph';
|
||||
import { Matrix } from '../types';
|
||||
|
||||
const adjMatrix = (graph: IGraph, directed?: boolean) => {
|
||||
|
||||
const nodes = graph.getNodes();
|
||||
const edges = graph.getEdges();
|
||||
const matrix: Matrix[] = [];
|
||||
// map node with index in data.nodes
|
||||
const nodeMap: {
|
||||
[key: string]: number;
|
||||
} = {};
|
||||
|
||||
if (!nodes) {
|
||||
throw new Error('invalid nodes data!');
|
||||
}
|
||||
if (nodes) {
|
||||
nodes.forEach((node, i) => {
|
||||
nodeMap[node.getID()] = i;
|
||||
const row: number[] = [];
|
||||
matrix.push(row);
|
||||
});
|
||||
}
|
||||
|
||||
if (edges) {
|
||||
edges.forEach(e => {
|
||||
const model = e.getModel();
|
||||
const { source, target } = model;
|
||||
const sIndex = nodeMap[source as string];
|
||||
const tIndex = nodeMap[target as string];
|
||||
matrix[sIndex][tIndex] = 1;
|
||||
if (!directed) {
|
||||
matrix[tIndex][sIndex] = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
return matrix
|
||||
}
|
||||
|
||||
export default adjMatrix
|
41
src/algorithm/floydWarshall.ts
Normal file
41
src/algorithm/floydWarshall.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { IGraph } from '../interface/graph';
|
||||
import adjMatrix from './adjacent-matrix';
|
||||
import { Matrix } from '../types';
|
||||
|
||||
|
||||
const floydWarshall = (graph: IGraph, directed?: boolean) => {
|
||||
|
||||
let adjacentMatrix = graph.get('adjMatrix');
|
||||
if (!adjacentMatrix) {
|
||||
adjacentMatrix = adjMatrix(graph, directed);
|
||||
}
|
||||
|
||||
|
||||
const dist: Matrix[] = [];
|
||||
const size = adjacentMatrix.length;
|
||||
for (let i = 0; i < size; i += 1) {
|
||||
dist[i] = [];
|
||||
for (let j = 0; j < size; j += 1) {
|
||||
if (i === j) {
|
||||
dist[i][j] = 0;
|
||||
} else if (adjacentMatrix[i][j] === 0 || !adjacentMatrix[i][j]) {
|
||||
dist[i][j] = Infinity;
|
||||
} else {
|
||||
dist[i][j] = adjacentMatrix[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
// floyd
|
||||
for (let k = 0; k < size; k += 1) {
|
||||
for (let i = 0; i < size; i += 1) {
|
||||
for (let j = 0; j < size; j += 1) {
|
||||
if (dist[i][j] > dist[i][k] + dist[k][j]) {
|
||||
dist[i][j] = dist[i][k] + dist[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dist;
|
||||
}
|
||||
|
||||
export default floydWarshall
|
@ -1,3 +1,7 @@
|
||||
export { default as depthFirstSearch } from './dfs'
|
||||
export { default as breadthFirstSearch } from './bfs'
|
||||
export { default as detectDirectedCycle } from './detect-cycle'
|
||||
export { default as degree } from './degree'
|
||||
export { default as adjMatrix } from './adjacent-matrix'
|
||||
export { default as floydWarshall } from './floydWarshall'
|
||||
|
||||
|
@ -46,6 +46,8 @@ import createDom from '@antv/dom-util/lib/create-dom';
|
||||
import { plainCombosToTrees, traverseTree, reconstructTree, traverseTreeUp } from '../util/graphic';
|
||||
import degree from '../algorithm/degree';
|
||||
import Stack from '../algorithm/structs/stack'
|
||||
import adjMatrix from '../algorithm/adjacent-matrix';
|
||||
import floydWarshall from '../algorithm/floydWarshall'
|
||||
|
||||
const NODE = 'node';
|
||||
const SVG = 'svg';
|
||||
@ -2370,8 +2372,13 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
console.warn('The combo to be collapsed does not exist!');
|
||||
return;
|
||||
}
|
||||
|
||||
const comboModel = combo.getModel();
|
||||
|
||||
const itemController: ItemController = this.get('itemController');
|
||||
itemController.collapseCombo(combo);
|
||||
comboModel.collapsed = true;
|
||||
|
||||
// add virtual edges
|
||||
const edges = this.getEdges().concat(this.get('vedges'));
|
||||
|
||||
@ -2414,6 +2421,7 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
const edgeWeightMap = {};
|
||||
const addedVEdges = [];
|
||||
edges.forEach(edge => {
|
||||
if (edge.isVisible() && !edge.getModel().isVEdge) return;
|
||||
let source = edge.getSource();
|
||||
let target = edge.getTarget();
|
||||
if (((cnodes.includes(source) || ccombos.includes(source))
|
||||
@ -2485,9 +2493,6 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
}, false)
|
||||
});
|
||||
|
||||
const itemController: ItemController = this.get('itemController');
|
||||
itemController.collapseCombo(combo);
|
||||
comboModel.collapsed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2548,6 +2553,7 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
const edgeWeightMap = {};
|
||||
const addedVEdges = {};
|
||||
edges.forEach(edge => {
|
||||
if (edge.isVisible() && !edge.getModel().isVEdge) return;
|
||||
let source = edge.getSource();
|
||||
let target = edge.getTarget();
|
||||
let sourceId = source.get('id');
|
||||
@ -2907,7 +2913,7 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
console.warn('请先启用 undo & redo 功能,在实例化 Graph 时候配置 enabledStack: true !')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
const stackData = data ? clone(data) : clone(this.save())
|
||||
|
||||
if (stackType === 'redo') {
|
||||
@ -2926,6 +2932,48 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
undoStack: this.undoStack,
|
||||
redoStack: this.redoStack
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* 获取邻接矩阵
|
||||
*
|
||||
* @param {boolean} cache 是否使用缓存的
|
||||
* @param {boolean} directed 是否是有向图,默认取 graph.directed
|
||||
* @returns {Matrix} 邻接矩阵
|
||||
* @memberof IGraph
|
||||
*/
|
||||
public getAdjMatrix(cache: boolean = true, directed?: boolean): Number | Object {
|
||||
if (directed === undefined) directed = this.get('directed');
|
||||
let currentAdjMatrix = this.get('adjMatrix');
|
||||
if (!currentAdjMatrix || !cache) {
|
||||
currentAdjMatrix = adjMatrix(this, directed);
|
||||
this.set('adjMatrix', currentAdjMatrix);
|
||||
}
|
||||
return currentAdjMatrix;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取最短路径矩阵
|
||||
*
|
||||
* @param {boolean} cache 是否使用缓存的
|
||||
* @param {boolean} directed 是否是有向图,默认取 graph.directed
|
||||
* @returns {Matrix} 最短路径矩阵
|
||||
* @memberof IGraph
|
||||
*/
|
||||
public getShortestPathMatrix(cache: boolean = true, directed?: boolean): Number | Object {
|
||||
if (directed === undefined) directed = this.get('directed');
|
||||
let currentAdjMatrix = this.get('adjMatrix');
|
||||
let currentShourtestPathMatrix = this.get('shortestPathMatrix');
|
||||
if (!currentAdjMatrix || !cache) {
|
||||
currentAdjMatrix = adjMatrix(this, directed);
|
||||
this.set('adjMatrix', currentAdjMatrix);
|
||||
}
|
||||
if (!currentShourtestPathMatrix || !cache) {
|
||||
currentShourtestPathMatrix = floydWarshall(this, directed);
|
||||
this.set('shortestPathMatrix', currentShourtestPathMatrix);
|
||||
}
|
||||
return currentShourtestPathMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2936,7 +2984,7 @@ export default class Graph extends EventEmitter implements IGraph {
|
||||
|
||||
// 清空栈数据
|
||||
this.clearStack();
|
||||
|
||||
|
||||
each(this.get('plugins'), plugin => {
|
||||
plugin.destroyPlugin();
|
||||
});
|
||||
|
@ -13,6 +13,7 @@ import RegisterRectCombo from './component/register-rect-combo';
|
||||
import RegisterCircleCombo from './component/register-circle-combo';
|
||||
import Edges from './component/edges';
|
||||
import DagreCombo from './component/dagre-combo';
|
||||
import Edges2 from './component/edges2';
|
||||
|
||||
export default { title: 'Combo' };
|
||||
|
||||
@ -48,4 +49,6 @@ storiesOf('Combo', module)
|
||||
<Edges />
|
||||
)).add('dagre combo', () => (
|
||||
<DagreCombo />
|
||||
)).add('edges2 ', () => (
|
||||
<Edges2 />
|
||||
));
|
||||
|
97
stories/Combo/component/edges2.tsx
Normal file
97
stories/Combo/component/edges2.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import G6 from '../../../src';
|
||||
import { IGraph } from '../../../src/interface/graph';
|
||||
import { GraphData } from '../../../src/types';
|
||||
|
||||
let graph: IGraph = null;
|
||||
|
||||
const data: GraphData = {
|
||||
nodes: [{
|
||||
id: '1',
|
||||
comboId: '分组1',
|
||||
x: 100,
|
||||
y: 100
|
||||
}, {
|
||||
id: '2',
|
||||
comboId: '分组1',
|
||||
x: 200,
|
||||
y: 100
|
||||
}, {
|
||||
id: '4',
|
||||
comboId: '分组2',
|
||||
x: 400,
|
||||
y: 100
|
||||
}
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: '分组1',
|
||||
target: '分组2',
|
||||
}
|
||||
],
|
||||
combos: [
|
||||
{
|
||||
id: '分组1',
|
||||
label: '分组1',
|
||||
//collapsed: true
|
||||
},
|
||||
{
|
||||
id: '分组2',
|
||||
label: '分组2',
|
||||
//collapsed: true,
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const Edges2 = () => {
|
||||
const container = React.useRef();
|
||||
useEffect(() => {
|
||||
if (!graph) {
|
||||
const graph = new G6.Graph({
|
||||
container: container.current as string | HTMLElement,
|
||||
width: 1000,
|
||||
height: 800,
|
||||
groupByTypes: false,
|
||||
defaultEdge: {
|
||||
style: {
|
||||
endArrow: true
|
||||
}
|
||||
},
|
||||
defaultCombo: {
|
||||
type: 'rect',
|
||||
size: [50, 60], // The minimum size of the Combo
|
||||
padding: [20, 10, 10, 20],
|
||||
style: {
|
||||
lineWidth: 3,
|
||||
},
|
||||
anchorPoints: [
|
||||
[0.5, 1],
|
||||
[0.5, 0],
|
||||
],
|
||||
labelCfg: {
|
||||
refY: 10,
|
||||
refX: 20,
|
||||
position: 'top',
|
||||
},
|
||||
},
|
||||
modes: {
|
||||
default: ['drag-canvas', 'drag-node',
|
||||
{
|
||||
type: 'drag-combo',
|
||||
enableDelegate: true //拖动时禁止合并
|
||||
}
|
||||
],
|
||||
},
|
||||
});
|
||||
graph.data(data);
|
||||
graph.render();
|
||||
graph.on('combo:click', function (e) {
|
||||
graph.collapseExpandCombo(e.item);
|
||||
graph.refreshPositions();
|
||||
});
|
||||
}
|
||||
});
|
||||
return <div ref={container}></div>;
|
||||
};
|
||||
|
||||
export default Edges2;
|
234
tests/unit/algorithm/adjacent-matrix-spec.ts
Normal file
234
tests/unit/algorithm/adjacent-matrix-spec.ts
Normal file
@ -0,0 +1,234 @@
|
||||
import G6, { Algorithm } from '../../../src';
|
||||
const { adjMatrix } = Algorithm;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.id = 'container';
|
||||
document.body.appendChild(div);
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: 'A',
|
||||
label: '0'
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
label: '1'
|
||||
},
|
||||
{
|
||||
id: 'C',
|
||||
label: '2'
|
||||
},
|
||||
{
|
||||
id: 'D',
|
||||
label: '3'
|
||||
},
|
||||
{
|
||||
id: 'E',
|
||||
label: '4'
|
||||
},
|
||||
{
|
||||
id: 'F',
|
||||
label: '5'
|
||||
},
|
||||
{
|
||||
id: 'G',
|
||||
label: '6'
|
||||
},
|
||||
{
|
||||
id: 'H',
|
||||
label: '7'
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: 'A',
|
||||
target: 'B',
|
||||
},
|
||||
{
|
||||
source: 'B',
|
||||
target: 'C',
|
||||
},
|
||||
{
|
||||
source: 'C',
|
||||
target: 'G',
|
||||
},
|
||||
{
|
||||
source: 'A',
|
||||
target: 'D',
|
||||
},
|
||||
{
|
||||
source: 'A',
|
||||
target: 'E',
|
||||
},
|
||||
{
|
||||
source: 'E',
|
||||
target: 'F',
|
||||
},
|
||||
{
|
||||
source: 'F',
|
||||
target: 'D',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
describe('Adjacency Matrix on graph', () => {
|
||||
const graph = new G6.Graph({
|
||||
container: 'container',
|
||||
width: 500,
|
||||
height: 500,
|
||||
defaultEdge: {
|
||||
style: {
|
||||
endArrow: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
graph.data(data)
|
||||
graph.render()
|
||||
|
||||
it('get graph adjacency matrix', () => {
|
||||
const matrix = graph.getAdjMatrix();
|
||||
expect(Object.keys(matrix).length).toBe(8);
|
||||
const node0Adj = matrix[0];
|
||||
expect(node0Adj.length).toBe(5);
|
||||
expect(node0Adj[0]).toBe(undefined);
|
||||
expect(node0Adj[1]).toBe(1);
|
||||
expect(node0Adj[2]).toBe(undefined);
|
||||
expect(node0Adj[3]).toBe(1);
|
||||
expect(node0Adj[4]).toBe(1);
|
||||
});
|
||||
|
||||
it('add items and cache', () => {
|
||||
graph.addItem('node', {
|
||||
id: 'I',
|
||||
label: '8'
|
||||
});
|
||||
graph.addItem('edge', {
|
||||
source: 'I',
|
||||
target: 'A'
|
||||
});
|
||||
graph.addItem('edge', {
|
||||
source: 'C',
|
||||
target: 'A'
|
||||
});
|
||||
// use the cache
|
||||
const cachedMatrix = graph.getAdjMatrix();
|
||||
expect(Object.keys(cachedMatrix).length).toBe(8);
|
||||
const cachedNode0Adj = cachedMatrix[0];
|
||||
expect(cachedNode0Adj.length).toBe(5);
|
||||
expect(cachedNode0Adj[0]).toBe(undefined);
|
||||
expect(cachedNode0Adj[1]).toBe(1);
|
||||
expect(cachedNode0Adj[2]).toBe(undefined);
|
||||
expect(cachedNode0Adj[3]).toBe(1);
|
||||
expect(cachedNode0Adj[4]).toBe(1);
|
||||
|
||||
// do not use the cache
|
||||
const matrix = graph.getAdjMatrix(false);
|
||||
expect(Object.keys(matrix).length).toBe(9);
|
||||
const node0Adj = matrix[0];
|
||||
expect(node0Adj.length).toBe(9);
|
||||
expect(node0Adj[0]).toBe(undefined);
|
||||
expect(node0Adj[1]).toBe(1);
|
||||
expect(node0Adj[2]).toBe(1);
|
||||
expect(node0Adj[3]).toBe(1);
|
||||
expect(node0Adj[4]).toBe(1);
|
||||
expect(node0Adj[5]).toBe(undefined);
|
||||
expect(node0Adj[6]).toBe(undefined);
|
||||
expect(node0Adj[7]).toBe(undefined);
|
||||
expect(node0Adj[8]).toBe(1);
|
||||
})
|
||||
|
||||
it('directed', () => {
|
||||
// do not use the cache and directed
|
||||
const matrix = graph.getAdjMatrix(false, true);
|
||||
expect(Object.keys(matrix).length).toBe(9);
|
||||
const node0Adj = matrix[0];
|
||||
expect(node0Adj.length).toBe(5);
|
||||
expect(node0Adj[0]).toBe(undefined);
|
||||
expect(node0Adj[1]).toBe(1);
|
||||
expect(node0Adj[2]).toBe(undefined);
|
||||
expect(node0Adj[3]).toBe(1);
|
||||
expect(node0Adj[4]).toBe(1);
|
||||
const node8Adj = matrix[8];
|
||||
expect(node8Adj.length).toBe(1);
|
||||
expect(node8Adj[0]).toBe(1);
|
||||
graph.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
describe('Adjacency Matrix by Algorithm', () => {
|
||||
const graph = new G6.Graph({
|
||||
container: 'container',
|
||||
width: 500,
|
||||
height: 500,
|
||||
defaultEdge: {
|
||||
style: {
|
||||
endArrow: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
graph.data(data)
|
||||
graph.render()
|
||||
|
||||
it('get graph adjacency matrix', () => {
|
||||
const matrix = adjMatrix(graph);
|
||||
expect(Object.keys(matrix).length).toBe(8);
|
||||
const node0Adj = matrix[0];
|
||||
expect(node0Adj.length).toBe(5);
|
||||
expect(node0Adj[0]).toBe(undefined);
|
||||
expect(node0Adj[1]).toBe(1);
|
||||
expect(node0Adj[2]).toBe(undefined);
|
||||
expect(node0Adj[3]).toBe(1);
|
||||
expect(node0Adj[4]).toBe(1);
|
||||
});
|
||||
|
||||
it('add items and cache', () => {
|
||||
graph.addItem('node', {
|
||||
id: 'I',
|
||||
label: '8'
|
||||
});
|
||||
graph.addItem('edge', {
|
||||
source: 'I',
|
||||
target: 'A'
|
||||
});
|
||||
graph.addItem('edge', {
|
||||
source: 'C',
|
||||
target: 'A'
|
||||
});
|
||||
|
||||
const matrix = adjMatrix(graph);
|
||||
expect(Object.keys(matrix).length).toBe(9);
|
||||
const node0Adj = matrix[0];
|
||||
expect(node0Adj.length).toBe(9);
|
||||
expect(node0Adj[0]).toBe(undefined);
|
||||
expect(node0Adj[1]).toBe(1);
|
||||
expect(node0Adj[2]).toBe(1);
|
||||
expect(node0Adj[3]).toBe(1);
|
||||
expect(node0Adj[4]).toBe(1);
|
||||
expect(node0Adj[5]).toBe(undefined);
|
||||
expect(node0Adj[6]).toBe(undefined);
|
||||
expect(node0Adj[7]).toBe(undefined);
|
||||
expect(node0Adj[8]).toBe(1);
|
||||
})
|
||||
|
||||
it('directed', () => {
|
||||
// directed
|
||||
const matrix = adjMatrix(graph, true);
|
||||
expect(Object.keys(matrix).length).toBe(9);
|
||||
const node0Adj = matrix[0];
|
||||
expect(node0Adj.length).toBe(5);
|
||||
expect(node0Adj[0]).toBe(undefined);
|
||||
expect(node0Adj[1]).toBe(1);
|
||||
expect(node0Adj[2]).toBe(undefined);
|
||||
expect(node0Adj[3]).toBe(1);
|
||||
expect(node0Adj[4]).toBe(1);
|
||||
const node8Adj = matrix[8];
|
||||
expect(node8Adj.length).toBe(1);
|
||||
expect(node8Adj[0]).toBe(1);
|
||||
graph.destroy();
|
||||
});
|
||||
});
|
264
tests/unit/algorithm/shortestpath-matrix-spec.ts
Normal file
264
tests/unit/algorithm/shortestpath-matrix-spec.ts
Normal file
@ -0,0 +1,264 @@
|
||||
import G6, { Algorithm } from '../../../src';
|
||||
const { floydWarshall } = Algorithm;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.id = 'container';
|
||||
document.body.appendChild(div);
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: 'A',
|
||||
label: '0'
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
label: '1'
|
||||
},
|
||||
{
|
||||
id: 'C',
|
||||
label: '2'
|
||||
},
|
||||
{
|
||||
id: 'D',
|
||||
label: '3'
|
||||
},
|
||||
{
|
||||
id: 'E',
|
||||
label: '4'
|
||||
},
|
||||
{
|
||||
id: 'F',
|
||||
label: '5'
|
||||
},
|
||||
{
|
||||
id: 'G',
|
||||
label: '6'
|
||||
},
|
||||
{
|
||||
id: 'H',
|
||||
label: '7'
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: 'A',
|
||||
target: 'B',
|
||||
},
|
||||
{
|
||||
source: 'B',
|
||||
target: 'C',
|
||||
},
|
||||
{
|
||||
source: 'C',
|
||||
target: 'G',
|
||||
},
|
||||
{
|
||||
source: 'A',
|
||||
target: 'D',
|
||||
},
|
||||
{
|
||||
source: 'A',
|
||||
target: 'E',
|
||||
},
|
||||
{
|
||||
source: 'E',
|
||||
target: 'F',
|
||||
},
|
||||
{
|
||||
source: 'F',
|
||||
target: 'D',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
describe('Shortest Path Matrix on graph', () => {
|
||||
const graph = new G6.Graph({
|
||||
container: 'container',
|
||||
width: 500,
|
||||
height: 500,
|
||||
defaultEdge: {
|
||||
style: {
|
||||
endArrow: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
graph.data(data)
|
||||
graph.render()
|
||||
|
||||
it('get graph shortest path matrix', () => {
|
||||
const matrix = graph.getShortestPathMatrix();
|
||||
console.log(matrix);
|
||||
expect(Object.keys(matrix).length).toBe(8);
|
||||
const node0 = matrix[0];
|
||||
expect(node0.length).toBe(8);
|
||||
expect(node0[0]).toBe(0);
|
||||
expect(node0[1]).toBe(1);
|
||||
expect(node0[2]).toBe(2);
|
||||
expect(node0[3]).toBe(1);
|
||||
expect(node0[4]).toBe(1);
|
||||
expect(node0[5]).toBe(2);
|
||||
expect(node0[6]).toBe(3);
|
||||
expect(node0[7]).toBe(Infinity);
|
||||
expect(matrix[1][7]).toBe(Infinity);
|
||||
expect(matrix[2][7]).toBe(Infinity);
|
||||
expect(matrix[3][7]).toBe(Infinity);
|
||||
});
|
||||
|
||||
it('add items and cache', () => {
|
||||
graph.addItem('node', {
|
||||
id: 'I',
|
||||
label: '8'
|
||||
});
|
||||
graph.addItem('edge', {
|
||||
source: 'I',
|
||||
target: 'A'
|
||||
});
|
||||
graph.addItem('edge', {
|
||||
source: 'C',
|
||||
target: 'A'
|
||||
});
|
||||
// use the cache
|
||||
const cachedMatrix = graph.getShortestPathMatrix();
|
||||
expect(Object.keys(cachedMatrix).length).toBe(8);
|
||||
const cachedNode0 = cachedMatrix[0];
|
||||
expect(cachedNode0.length).toBe(8);
|
||||
expect(cachedNode0[0]).toBe(0);
|
||||
expect(cachedNode0[1]).toBe(1);
|
||||
expect(cachedNode0[2]).toBe(2);
|
||||
expect(cachedNode0[3]).toBe(1);
|
||||
expect(cachedNode0[4]).toBe(1);
|
||||
expect(cachedNode0[5]).toBe(2);
|
||||
expect(cachedNode0[6]).toBe(3);
|
||||
expect(cachedNode0[7]).toBe(Infinity);
|
||||
expect(cachedMatrix[1][7]).toBe(Infinity);
|
||||
expect(cachedMatrix[2][7]).toBe(Infinity);
|
||||
expect(cachedMatrix[3][7]).toBe(Infinity);
|
||||
|
||||
// do not use the cache
|
||||
const matrix = graph.getShortestPathMatrix(false);
|
||||
expect(Object.keys(matrix).length).toBe(9);
|
||||
console.log(matrix);
|
||||
const node0 = matrix[0];
|
||||
expect(node0.length).toBe(9);
|
||||
expect(node0[0]).toBe(0);
|
||||
expect(node0[1]).toBe(1);
|
||||
expect(node0[2]).toBe(1);
|
||||
expect(node0[3]).toBe(1);
|
||||
expect(node0[4]).toBe(1);
|
||||
expect(node0[5]).toBe(2);
|
||||
expect(node0[6]).toBe(2);
|
||||
expect(node0[7]).toBe(Infinity);
|
||||
expect(node0[8]).toBe(1);
|
||||
})
|
||||
|
||||
it('directed', () => {
|
||||
// do not use the cache and directed
|
||||
const matrix = graph.getShortestPathMatrix(false, true);
|
||||
expect(Object.keys(matrix).length).toBe(9);
|
||||
console.log(matrix)
|
||||
const node0 = matrix[0];
|
||||
expect(node0.length).toBe(9);
|
||||
expect(node0[0]).toBe(0);
|
||||
expect(node0[1]).toBe(1);
|
||||
expect(node0[2]).toBe(2);
|
||||
expect(node0[3]).toBe(1);
|
||||
expect(node0[4]).toBe(1);
|
||||
expect(node0[5]).toBe(2);
|
||||
expect(node0[6]).toBe(3);
|
||||
expect(node0[7]).toBe(Infinity);
|
||||
expect(node0[8]).toBe(Infinity);
|
||||
const node8 = matrix[8];
|
||||
expect(node8.length).toBe(9);
|
||||
expect(node8[0]).toBe(1);
|
||||
graph.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
describe('Adjacency Matrix by Algorithm', () => {
|
||||
const graph = new G6.Graph({
|
||||
container: 'container',
|
||||
width: 500,
|
||||
height: 500,
|
||||
defaultEdge: {
|
||||
style: {
|
||||
endArrow: true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
graph.data(data)
|
||||
graph.render()
|
||||
|
||||
it('get graph shortestpath matrix', () => {
|
||||
const matrix = floydWarshall(graph);
|
||||
expect(Object.keys(matrix).length).toBe(8);
|
||||
const node0 = matrix[0];
|
||||
expect(node0.length).toBe(8);
|
||||
expect(node0[0]).toBe(0);
|
||||
expect(node0[1]).toBe(1);
|
||||
expect(node0[2]).toBe(2);
|
||||
expect(node0[3]).toBe(1);
|
||||
expect(node0[4]).toBe(1);
|
||||
expect(node0[5]).toBe(2);
|
||||
expect(node0[6]).toBe(3);
|
||||
expect(node0[7]).toBe(Infinity);
|
||||
expect(matrix[1][7]).toBe(Infinity);
|
||||
expect(matrix[2][7]).toBe(Infinity);
|
||||
expect(matrix[3][7]).toBe(Infinity);
|
||||
});
|
||||
|
||||
it('add items and cache', () => {
|
||||
graph.addItem('node', {
|
||||
id: 'I',
|
||||
label: '8'
|
||||
});
|
||||
graph.addItem('edge', {
|
||||
source: 'I',
|
||||
target: 'A'
|
||||
});
|
||||
graph.addItem('edge', {
|
||||
source: 'C',
|
||||
target: 'A'
|
||||
});
|
||||
|
||||
const matrix = floydWarshall(graph);
|
||||
expect(Object.keys(matrix).length).toBe(9);
|
||||
console.log(matrix);
|
||||
const node0 = matrix[0];
|
||||
expect(node0.length).toBe(9);
|
||||
expect(node0[0]).toBe(0);
|
||||
expect(node0[1]).toBe(1);
|
||||
expect(node0[2]).toBe(1);
|
||||
expect(node0[3]).toBe(1);
|
||||
expect(node0[4]).toBe(1);
|
||||
expect(node0[5]).toBe(2);
|
||||
expect(node0[6]).toBe(2);
|
||||
expect(node0[7]).toBe(Infinity);
|
||||
expect(node0[8]).toBe(1);
|
||||
})
|
||||
|
||||
it('directed', () => {
|
||||
// directed
|
||||
const matrix = floydWarshall(graph, true);
|
||||
expect(Object.keys(matrix).length).toBe(9);
|
||||
const node0 = matrix[0];
|
||||
expect(node0.length).toBe(9);
|
||||
expect(node0[0]).toBe(0);
|
||||
expect(node0[1]).toBe(1);
|
||||
expect(node0[2]).toBe(2);
|
||||
expect(node0[3]).toBe(1);
|
||||
expect(node0[4]).toBe(1);
|
||||
expect(node0[5]).toBe(2);
|
||||
expect(node0[6]).toBe(3);
|
||||
expect(node0[7]).toBe(Infinity);
|
||||
expect(node0[8]).toBe(Infinity);
|
||||
const node8 = matrix[8];
|
||||
expect(node8.length).toBe(9);
|
||||
expect(node8[0]).toBe(1);
|
||||
graph.destroy();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user