Skip to content

Commit 2be1f65

Browse files
committed
Warshalls for Euclidean graphs (random needs work)
1 parent 4ee9aba commit 2be1f65

File tree

5 files changed

+74
-35
lines changed

5 files changed

+74
-35
lines changed

src/algorithms/controllers/transitiveClosure.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export default {
1919
initVisualisers() {
2020
return {
2121
graph: {
22-
instance: new GraphTracer('key', null, 'Transitive Closure'),
22+
// instance: new GraphTracer('key', null, 'Transitive Closure'),
23+
instance: new GraphTracer('key', null, 'Graph view'),
2324
order: 0
2425
},
2526
// create a separate component for displaying the matrix as a 2D array
@@ -42,22 +43,25 @@ export default {
4243
return out;
4344
},
4445

45-
run(chunker, { matrix, size }) {
46+
run(chunker, { edgeValueMatrix, coordsMatrix, startNode, endNodes, moveNode}) {
4647
// eslint-disable-next-line no-unused-expressions
48+
const matrix = edgeValueMatrix;
49+
const size = matrix.length;
4750
const numOfNodes = size;
4851
const nodes = new Array(numOfNodes);
4952
let prevI = 0;
5053
let prevJ = 0;
5154
let prevK = 0;
52-
chunker.add(1, (g) => {
55+
chunker.add(1, (g, edgeArray, coordsArray) => {
5356
// show kth tag when step back
5457
setKthVisible(true);
5558
g.array.set([...matrix], 'tc');
56-
g.graph.set([...matrix], Array.from({ length: matrix.length }, (v, k) => (k + 1)));
57-
g.graph.layoutCircle();
59+
g.graph.set(edgeArray, Array.from({ length: matrix.length }, (v, k) => (k + 1)),coordsArray);
60+
// g.graph.layoutCircle();
5861
// initialise the matrix in the 'Matrix' component
5962
g.graph.setIstc();
60-
}, [this.graph], [this.array]);
63+
g.graph.moveNodeFn(moveNode);
64+
}, [[...edgeValueMatrix], [...coordsMatrix]]);
6165

6266
for (let i = 0; i < numOfNodes; i++) {
6367
nodes[i] = this.copyArr([...matrix]);

src/algorithms/parameters/TCParam.js

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,55 @@
11
/* eslint-disable no-unused-vars */
22
import React, { useState } from 'react';
3-
import MatrixParam from './helpers/MatrixParam';
3+
// import MatrixParam from './helpers/MatrixParam';
4+
import EuclideanMatrixParams from './helpers/EuclideanMatrixParams';
45
import '../../styles/Param.scss';
56

6-
const DEFAULT_SIZE = 4;
7+
const DEFAULT_SIZE = 4; // gets overwritten by GRAPH_EGS[0] now
8+
const DEFAULT_START = null; // disable
9+
const DEFAULT_END = null; // disable
10+
const DEFAULT_HEUR = null; // disable
11+
const DEFAULT_WEIGHT = 2; // weights "as input"
712
const TRANSITIVE_CLOSURE = 'Transitive Closure';
813
const TRANSITIVE_CLOSURE_EXAMPLE = 'Please follow the example provided: 0,1';
14+
const GRAPH_EGS = [ // XXX think up better examples?
15+
{ name: 'Graph 1',
16+
size: 4,
17+
coords: '10-13,20-13,20-3,10-3',
18+
edges: '1-1,2-2,3-3,4-4,1-2,2-3,3-4'
19+
},
20+
{ name: 'Graph 2',
21+
size: 4,
22+
coords: '10-13,20-13,20-3,10-3',
23+
edges: '1-1,2-2,3-3,4-4,1-3,2-1,3-2,4-3'
24+
},
25+
{ name: 'Graph 3',
26+
size: 5,
27+
coords: '6-9,15-16,20-10,17-2,8-2',
28+
edges: '1-2,2-1,2-3,3-4,4-5,5-3'
29+
}];
930

1031
function TransitiveClosureParam() {
1132
const [message, setMessage] = useState(null);
1233

1334
return (
1435
<>
1536
{/* Matrix input */}
16-
<MatrixParam
37+
<EuclideanMatrixParams
1738
name="transitiveClosure"
1839
mode="tc"
1940
defaultSize={DEFAULT_SIZE}
20-
min={0}
21-
max={1}
41+
defaultStart={DEFAULT_START}
42+
defaultEnd={DEFAULT_END}
43+
defaultWeight = {DEFAULT_WEIGHT}
44+
defaultHeur = {DEFAULT_HEUR}
45+
min={1}
46+
max={49}
47+
graphEgs={GRAPH_EGS}
2248
ALGORITHM_NAME={TRANSITIVE_CLOSURE}
2349
EXAMPLE={TRANSITIVE_CLOSURE_EXAMPLE}
2450
setMessage={setMessage}
51+
symmetric={false}
52+
unweighted
2553
/>
2654

2755
{/* render success/error message */}

src/algorithms/parameters/helpers/EuclideanMatrixParams.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ function EuclideanMatrixParams({
184184
defaultSize,
185185
defaultStart,
186186
defaultEnd,
187+
// XXX should have defaultWeight = 0 (=Euclidean) defined in the
188+
// graph traversal parameters; included explicitly in Warshall's
189+
defaultWeight = 0, // in case defaultWeight not defined
187190
defaultHeur,
188191
graphEgs,
189192
min,
@@ -220,7 +223,7 @@ function EuclideanMatrixParams({
220223
const W_MANHATTAN = 1;
221224
const W_INPUT = 2; // as defined by input
222225
const weightCalcName = ['Euclidean', 'Manhattan', 'As input'];
223-
const [weightCalc, setCalcMethod] = useState(W_EUCLIDEAN);
226+
const [weightCalc, setCalcMethod] = useState(defaultWeight);
224227

225228
// Button toggles Euclidean/Manhattan for heuristic
226229
const HEURCALCMAX = 2; // number of heuristic calculation options
@@ -730,6 +733,20 @@ function EuclideanMatrixParams({
730733
+
731734
</button>
732735
</div>);
736+
737+
let startButton = '';
738+
if (defaultStart !== null)
739+
startButton =
740+
(<div className="sLineButtonContainer">
741+
<button className="startBtn" onClick={() => updateStartNode(startNode - 1)}>
742+
743+
</button>
744+
<span className='size'>Start: {startNode}</span>
745+
<button className="sizeBtn" onClick={() => updateStartNode(startNode + 1)}>
746+
+
747+
</button>
748+
749+
</div>);
733750

734751
let weightButton = '';
735752
if (!unweighted)
@@ -764,16 +781,7 @@ function EuclideanMatrixParams({
764781
</div>
765782
{weightButton}
766783
{heurButton}
767-
<div className="sLineButtonContainer">
768-
<button className="startBtn" onClick={() => updateStartNode(startNode - 1)}>
769-
770-
</button>
771-
<span className='size'>Start: {startNode}</span>
772-
<button className="sizeBtn" onClick={() => updateStartNode(startNode + 1)}>
773-
+
774-
</button>
775-
776-
</div>
784+
{startButton}
777785
{endButton}
778786
</div>
779787
{endNodeDiv}

src/components/DataStructures/Graph/GraphRenderer/index.js

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ class GraphRenderer extends Renderer {
5555
constructor(props) {
5656
super(props);
5757

58+
// XXX shouldn't rely on this.props.title
59+
// XXX This plus the code for axes and graph layout (eg layoutCircle()
60+
// and code where X-Y coordinates are explicitly given by the user) is
61+
// linked. Some magic numbers were added to shift things around and make
62+
// things look ok. It should be rethought or at least the numbers for
63+
// this.centerX and this.centerY should be put in one place.
5864
if (this.props.title === 'Graph view') {
5965
// Center to new axis origin
6066
// this.centerX = 180;
@@ -83,17 +89,7 @@ class GraphRenderer extends Renderer {
8389
handleMouseMove(e) {
8490
// XXX would be nice to avoid selecting text with reverse video
8591
// as we move the mouse around!
86-
// XXX really shouldn't depend on this.props.title - moving away
87-
// from this but still have a hack for Warshalls
88-
if (this.selectedNode && this.props.title === 'Transitive Closure') {
89-
// XXX Old stuff so Warshall's remains as it was
90-
// Allow mouse movement
91-
const { x, y } = this.computeCoords(e);
92-
const node = this.props.data.findNode(this.selectedNode.id);
93-
node.x = x;
94-
node.y = y;
95-
this.refresh();
96-
} else if (this.selectedNode && this.props.data.moveNode) {
92+
if (this.selectedNode && this.props.data.moveNode) {
9793
// Allow mouse to move nodes (for Euclidean graphs) if
9894
// this.props.data.moveNode function is defined
9995
const { x, y } = this.computeCoords(e);

src/components/DataStructures/Graph/GraphTracer.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class GraphTracer extends Tracer {
115115
this.scaledCoords = coordinates;
116116
this.setNodeRadius(coordinates);
117117

118+
console.log(['coordinates', coordinates]);
118119
// Set layout to null if nodes are to be displayed by coordinates.
119120
if(coordinates.length > 0)
120121
{
@@ -404,8 +405,10 @@ class GraphTracer extends Tracer {
404405
const unitAngle = (2 * Math.PI) / this.nodes.length;
405406
let angle = -Math.PI / 2;
406407
for (const node of this.nodes) {
407-
const x = (Math.cos(angle) * rect.width) / 2;
408-
const y = (Math.sin(angle) * rect.height) / 2;
408+
// XXX see comment about magic numbers in constructor() in
409+
// Graph/GraphRenderer/index.js
410+
const x = 650 - 200 + (Math.cos(angle) * rect.width) / 2;
411+
const y = -200 - 70 + (Math.sin(angle) * rect.height) / 2;
409412
node.x = x;
410413
node.y = y;
411414
angle += unitAngle;

0 commit comments

Comments
 (0)