From 80826a9213b49ec029bbd8d5cb07814f01bd825b Mon Sep 17 00:00:00 2001 From: alator-ux Date: Sun, 31 Oct 2021 20:05:16 +0300 Subject: [PATCH] added kruskal algorithm for matrix based graph --- lib/visual_graphs.rb | 1 + lib/visual_graphs/algorithms/Kruskal.rb | 73 +++++++++++++++++++++++++ test/algorithms/kruskal_amb_test.rb | 58 ++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 lib/visual_graphs/algorithms/Kruskal.rb create mode 100644 test/algorithms/kruskal_amb_test.rb diff --git a/lib/visual_graphs.rb b/lib/visual_graphs.rb index de0013e..ad7ad34 100644 --- a/lib/visual_graphs.rb +++ b/lib/visual_graphs.rb @@ -2,6 +2,7 @@ require_relative "visual_graphs/version" require_relative "visual_graphs/graph" +require_relative 'visual_graphs/algorithms/Kruskal' module VisualGraphs class Error < StandardError; end end diff --git a/lib/visual_graphs/algorithms/Kruskal.rb b/lib/visual_graphs/algorithms/Kruskal.rb new file mode 100644 index 0000000..144593c --- /dev/null +++ b/lib/visual_graphs/algorithms/Kruskal.rb @@ -0,0 +1,73 @@ +require 'matrix' + +class Kruskal_Helper + attr_reader :parent, :result + + def initialize(size) + @parent = Array.new(size) {|i| i} + @result = Array.new(size) { |i| Array.new(size) { |j| i == j ? 0 : -1} } # временная замена, т.к. нет нужного класса + end + + + def find(i) + while i != @parent[i] + i = @parent[i] + end + return i + end + + def union(i, j, w) + a = find(i) + b = find(j) + @parent[a] = b + addEdge(i,j,w) + end + + def addEdge(first, second, weight) + @result[first][second] = weight + @result[second][first] = weight + end + + def result + return @result + end +end + +def kruskal(matrix) + exists = lambda do |weight| + weight > 0 + end + + # следующие три строки честно взяты из интернета, я их не понимаю + n_bytes = [42].pack('i').size + n_bits = n_bytes * 16 + max_integer = 2 ** (n_bits - 2) - 1 + + sz = matrix[0].size + helper = Kruskal_Helper.new sz + + (0...matrix.size - 1).each { + min = max_integer + a = -1 + b = -1 + + (0...sz).each do |i| + (0...sz).each do |j| + way = matrix[i][j] + if exists.call(way) + if helper.find(i) != helper.find(j) and way < min + min = way + a = i + b = j + end + end + end + end + + helper.union a, b, min + } + + #p matrix + #p helper.result + helper.result +end diff --git a/test/algorithms/kruskal_amb_test.rb b/test/algorithms/kruskal_amb_test.rb new file mode 100644 index 0000000..126f145 --- /dev/null +++ b/test/algorithms/kruskal_amb_test.rb @@ -0,0 +1,58 @@ +require 'minitest/autorun' +require "visual_graphs" +#Test for Kruskal's algorithm for adjacency matrix based graph +class Kruskal_ambTest < Minitest::Test + include VisualGraphs + def setup + # Do nothing + end + + def teardown + # Do nothing + end + + def test1 + matrix = + [ + [0, 7, 8, -1, -1,-1], + [7, 0, 11, 2, -1, -1], + [8, 11, 0, 6, 9, -1], + [-1, 2, 6, 0, 11, 9], + [-1, -1, 9, 11, 0, 10], + [-1, -1, -1, 9, 10, 0] + ] + expected = + [ + [0,7,-1,-1,-1,-1], + [7,0,-1,2,-1,-1], + [-1,-1,0,6,9,-1], + [-1,2,6,0,-1,9], + [-1,-1,9,-1,0,-1], + [-1,-1,-1,9,-1,0] + ] + result = kruskal matrix + assert_equal result, expected + end + + def test2 + matrix = + [ + [0,2,-1,6,-1], + [2,0,3,8,5], + [-1,3,0,-1,7], + [6,8,-1,0,9], + [-1,5,7,9,0] + ] + expected = + [ + [0,2,-1,6,-1], + [2,0,3,-1,5], + [-1,3,0,-1,-1], + [6,-1,-1,0,-1], + [-1,5,-1,-1,0], + ] + result = kruskal matrix + assert_equal result, expected + end + +end \ No newline at end of file