Skip to content

Instantly share code, notes, and snippets.

@remigijusj
Created July 21, 2020 17:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save remigijusj/8ca0758f2601bf216a77418ab985797b to your computer and use it in GitHub Desktop.
Save remigijusj/8ca0758f2601bf216a77418ab985797b to your computer and use it in GitHub Desktop.
Counting all monoids with three elements
class Table
# 1 is an identity, so we know it's composition with other elements.
ELTS = [1, :a, :b].freeze
BASIC = {'11' => 1, '1a' => :a, '1b' => :b, 'a1' => :a, 'b1' => :b}.freeze
# Iterate through all possible composition tables.
def self.each
return to_enum unless block_given?
ELTS.product(ELTS, ELTS, ELTS) { |list| yield new(*list) }
end
# Composition table:
# * | 1 a b
# --+ -----
# 1 | a a b
# a | a ? ?
# b | b ? ?
# Define 4 compositions: aa, ab, ba, bb
def initialize(aa, ab, ba, bb)
@table = BASIC.merge('aa' => aa, 'ab' => ab, 'ba' => ba, 'bb' => bb)
end
# What is the composition of x and y?
def [](x, y)
@table.fetch("#{x}#{y}")
end
# Does composition table stay the same when :a and :b are swapped?
def symmetric?
[[[:a, :a], [:b, :b]], [[:a, :b], [:b, :a]]].all? do |one, two|
one, two = self[*one], self[*two]
(one == 1 && two == 1) || (one != 1 && two != 1 && one != two)
end
end
# It is a monoid when composition is associative.
def associative?
ELTS.product(ELTS, ELTS).all? { |a, b, c| self[self[a, b], c] == self[a, self[b, c]] }
end
end
count = Table.each.with_object(Hash.new(0)) do |t, cnt|
next unless t.associative?
symmetric = t.symmetric? ? :s : :ns
cnt[symmetric] += 1
end
p count
# => {:ns=>8, :s=>3}
#
# It means there are 4 different non-symmetric monoids and 3 symmetric, total: 7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment