Skip to content

Commit

Permalink
prims
Browse files Browse the repository at this point in the history
  • Loading branch information
mglsj committed Jun 13, 2024
1 parent 5ff5bb9 commit ac55415
Show file tree
Hide file tree
Showing 22 changed files with 649 additions and 250 deletions.
25 changes: 25 additions & 0 deletions lib/algorithms/algorithm.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:visual_graphs/graph_editor/globals.dart';
import 'package:visual_graphs/graph_editor/models/graph.dart';

abstract class Algorithm {
bool isRunning = false;

final Graph graph = Globals.game.graph;

void start() async {}

void initialize() {
Globals.game.gameMode = GameMode.lockedMode;
clear();
Globals.game.greyOutGraphComponents();
isRunning = true;
}

void finalize() {
isRunning = false;
}

void clear() {
isRunning = false;
}
}
142 changes: 0 additions & 142 deletions lib/algorithms/mst/kruskal.dart

This file was deleted.

80 changes: 80 additions & 0 deletions lib/algorithms/mst/kruskals_algorithm.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import 'package:flutter/material.dart';
import 'package:visual_graphs/algorithms/mst/mst.dart';
import 'package:visual_graphs/graph_editor/globals.dart';
import 'package:visual_graphs/graph_editor/models/graph.dart';
import 'package:visual_graphs/helpers/data_structures/union_find.dart';

class KruskalsAlgorithm extends MinimumSpanningTree {
ColoredUnionFind<Vertex> unionFind = ColoredUnionFind();
List<Edge> edges = [];

@override
void start() async {
initialize();
edges = graph.edges..sort((a, b) => a.weight.compareTo(b.weight));

for (var edge in edges) {
await checkEdge(currentEdge.value = edge);
}

finalize();
}

bool makesCycle(Edge edge) {
return unionFind.find(edge.from).first == unionFind.find(edge.to).first;
}

Future checkEdge(Edge edge) async {
await Future.delayed(const Duration(milliseconds: 500));
edge.component
..edgeWidth += 2
..setColors(Colors.white, Colors.white);
edge.from.component
..radius = Globals.defaultVertexRadius + 5
..drawBorder = true;

edge.to.component
..radius = Globals.defaultVertexRadius + 5
..drawBorder = true;

await Future.delayed(const Duration(milliseconds: 500));

edge.component.edgeWidth = Globals.defaultEdgeWidth;
edge.from.component
..radius = Globals.defaultVertexRadius
..drawBorder = false;
edge.to.component
..radius = Globals.defaultVertexRadius
..drawBorder = false;

if (!edge.isSelfEdge && !makesCycle(edge)) {
includeEdge(edge);
} else {
edge.component.setColors(Colors.black, Colors.black);
}

updateColors();
}

void includeEdge(Edge edge) {
unionFind.union(edge.from, edge.to);
includedEdges.add(edge);
weightNotifier.value += edge.weight;
}

void updateColors() {
for (var edge in includedEdges.set) {
var color = unionFind.find(edge.from).second ?? Colors.white;
edge.component.setColors(color, color);
edge.from.component.setColors(color, color);
edge.to.component.setColors(color, color);
}
}

@override
void clear() {
super.clear();
edges.clear();
unionFind.clear();
}
}
96 changes: 96 additions & 0 deletions lib/algorithms/mst/lazy_prims_algorithm.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import 'package:flutter/material.dart';
import 'package:visual_graphs/algorithms/mst/mst.dart';
import 'package:visual_graphs/graph_editor/models/graph.dart';
import 'package:visual_graphs/helpers/notifiers/priority_queue_notifier.dart';

class LazyPrimsAlgorithm extends MinimumSpanningTree {
final PriorityQueueNotifier<Edge> pq =
PriorityQueueNotifier((a, b) => a.weight.compareTo(b.weight));

final Set<Vertex> seen = {};
final Set<Vertex> visited = {};

@override
void start([Vertex? startingVertex]) async {
initialize();

see(startingVertex!);
await Future.delayed(const Duration(milliseconds: 500));
await visit(startingVertex);

while (pq.isNotEmpty && edgeCount < graph.vertices.length - 1) {
await checkEdge(currentEdge.value = pq.removeFirst());
}
await Future.delayed(const Duration(seconds: 1));
finalize();
}

Future visit(Vertex vertex) async {
vertex.component.setColors(Colors.green, Colors.greenAccent);
visited.add(vertex);
await Future.delayed(const Duration(milliseconds: 100));
addEdges(vertex);
}

void addEdges(Vertex vertex) {
vertex.neighbours.forEach(
(vertex, edges) {
if (!visited.contains(vertex)) {
for (var edge in edges) {
edge.component.setColors(Colors.orange, Colors.orange);
pq.add(edge);
}
}
Future.delayed(const Duration(milliseconds: 100));
see(vertex);
},
);
}

void see(Vertex vertex) {
if (seen.contains(vertex)) return;
seen.add(vertex);
vertex.component.setColors(Colors.orange, Colors.orange);
}

Future checkEdge(Edge edge) async {
await Future.delayed(const Duration(seconds: 1));

if (!visited.contains(currentEdge.value!.to)) {
includeEdge(currentEdge.value!);
await visit(currentEdge.value!.to);
} else if (!edge.isDirected && !visited.contains(edge.from)) {
// this is just becuase i don't represent undirected egde as two directed
includeEdge(currentEdge.value!);
await visit(currentEdge.value!.from);
} else {
excludeEdge(currentEdge.value!);
}
}

void includeEdge(Edge edge) {
edge.component.setColors(
Colors.lightGreen,
Colors.lightGreen,
);

weightNotifier.value += edge.weight;
edgeCount++;
includedEdges.add(edge);
}

void excludeEdge(Edge edge) {
edge.component.setColors(
Colors.black,
Colors.black,
);
}

@override
void clear() {
super.clear();
pq.clear();
seen.clear();
visited.clear();
}
}
26 changes: 26 additions & 0 deletions lib/algorithms/mst/mst.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
import 'package:visual_graphs/algorithms/algorithm.dart';
import 'package:visual_graphs/graph_editor/models/graph.dart';
import 'package:visual_graphs/helpers/notifiers/set_notifier.dart';

class MinimumSpanningTree extends Algorithm {
final ValueNotifier<int> weightNotifier = ValueNotifier<int>(0);
final SetNotifier<Edge> includedEdges = SetNotifier<Edge>();
ValueNotifier<Edge?> currentEdge = ValueNotifier<Edge?>(null);
int edgeCount = 0;

@override
void clear() {
super.clear();
includedEdges.clear();
currentEdge.value = null;
weightNotifier.value = 0;
edgeCount = 0;
}

@override
void finalize() {
super.finalize();
currentEdge.value = null;
}
}
Loading

0 comments on commit ac55415

Please sign in to comment.