require "librarian/algorithms" module Librarian module Algorithms describe AdjacencyListDirectedGraph do describe 'cyclic?' do subject(:result) { described_class.cyclic?(graph) } context "with an empty graph" do let(:graph) { { } } it { should be false } end context "with a 1-node acyclic graph" do let(:graph) { { ?a => nil } } it { should be false } end context "with a 1-node cyclic graph" do let(:graph) { { ?a => [?a] } } it { should be true } end context "with a 2-node no-edge graph" do let(:graph) { { ?a => nil, ?b => nil } } it { should be false } end context "with a 2-node acyclic graph" do let(:graph) { { ?a => [?b], ?b => nil } } it { should be false } end context "with a 2-node cyclic graph" do let(:graph) { { ?a => [?b], ?b => [?a] } } it { should be true } end context "with a 2-scc graph" do let(:graph) { { ?a => [?b], ?b => [?a], ?c => [?d, ?b], ?d => [?c] } } it { should be true } end end describe 'feedback_arc_set' do subject(:result) { described_class.feedback_arc_set(graph) } context "with an empty graph" do let(:graph) { { } } it { should be_empty } end context "with a 1-node acyclic graph" do let(:graph) { { ?a => nil } } it { should be_empty } end context "with a 1-node cyclic graph" do let(:graph) { { ?a => [?a] } } it { should be == [[?a, ?a]] } end context "with a 2-node no-edge graph" do let(:graph) { { ?a => nil, ?b => nil } } it { should be_empty } end context "with a 2-node acyclic graph" do let(:graph) { { ?a => [?b], ?b => nil } } it { should be_empty } end context "with a 2-node cyclic graph" do let(:graph) { { ?a => [?b], ?b => [?a] } } it { should be == [[?a, ?b]] } # based on the explicit sort end context "with a 2-scc graph" do let(:graph) { { ?a => [?b], ?b => [?a], ?c => [?d, ?b], ?d => [?c] } } it { should be == [[?a, ?b], [?c, ?d]] } end end describe 'tsort_cyclic' do subject(:result) { described_class.tsort_cyclic(graph) } context "with an empty graph" do let(:graph) { { } } it { should be == [] } end context "with a 1-node acyclic graph" do let(:graph) { { ?a => nil } } it { should be == [?a] } end context "with a 1-node cyclic graph" do let(:graph) { { ?a => [?a] } } it { should be == [?a] } end context "with a 2-node no-edge graph" do let(:graph) { { ?a => nil, ?b => nil } } it { should be == [?a, ?b] } end context "with a 2-node acyclic graph" do let(:graph) { { ?a => [?b], ?b => nil } } it { should be == [?b, ?a] } # based on the explicit sort end context "with a 2-node cyclic graph" do let(:graph) { { ?a => [?b], ?b => [?a] } } it { should be == [?a, ?b] } # based on the explicit sort end context "with a 2-scc graph" do let(:graph) { { ?a => [?b], ?b => [?a], ?c => [?d, ?b], ?d => [?c] } } it { should be == [?a, ?b, ?c, ?d] } end # Dependencies are sorted alphabetically. Should they? context "should be deterministic" do let(:graph) { { ?a => [], ?b => [?c], ?c => [] } } it { should be == [?a, ?c, ?b] } end context "should be deterministic" do let(:graph) { { ?c => [], ?b => [?a], ?a => [] } } it { should be == [?a, ?b, ?c] } end end end end end