# Permutation Group # # by Shin-ichiro Hara # # Version 0.90 (2002.03.12) require "algebra/powers" require "algebra/combinatorial" require "algebra/finite-group" module Algebra class PermutationGroup < Group def self.unit_group(d) self[unity(d)] end def self.unity(n) Permutation.unity(n) end def self.perm(a) Permutation.new(a) end def self.symmetric(n) s = new(unity(n)) Combinatorial.perm(n) do |x| s << perm(x) #unity is not duplicated naturally end s end def self.alternate(n) symmetric(n).separate{|x| x.sign > 0} #slow two times end def initialize(u, *a) @degree = u.degree super(u, *a) end attr_reader :degree end class Permutation include Enumerable include Powers def self.[](*a) new(a) end def self.unity(d) new((0...d).to_a) end def initialize(x) @perm = x end attr_accessor :perm def unity self.class.unity(@perm.size) end def degree @perm.size end alias size degree def each(&b) @perm.each(&b) end def eql?(other) @perm.eql?(other.perm) end alias == eql? def hash @perm.hash end def inspect; @perm.inspect; end def to_s; @perm.inspect; end def [](i); @perm[i] || i; end alias call [] # def []=(i, x); @perm[i] = x; end def index(i); @perm.index(i); end def right_act(other)# permutation's traditional product (g*h)[x] == h[g[x]] self.class.new(collect{|i| other[i]}) end alias * right_act def left_act(other) self.class.new(other.collect{|i| self[i]}) end # alias * left_act def inverse self.class.new((0...degree).collect{|i| index(i)}) end alias inv inverse def sign a, b = perm.dup, inverse.perm s = 1 (0...(degree-1)).each do |i| if (j = a[i]) != i a[b[i]], b[j], s = j, b[i], -s end end s end def conjugate(g) g * self * g.inverse end def decompose_cyclic s = [] remain = (0...size).to_a while f = remain.shift a = [f] i = f while true j = self[i] if j == f s.push a if a.size > 1 break else remain.delete j a.push j i = j end end end s end #---------------------------- beta # def self.load(file) # s = Group[] # File.foreach(file) do |line| # g = eval(line).self # s.set_unity g unless s.unity # s.push g # end # s # end # def self.subgr_load(file) # s = Set[] # File.foreach(file) do |line| # s.push eval(line).collect{|perm| perm.self}.Group # end # s # end # def conjugate0(g) # to_Mapa.collect{|pr| [g[pr.first], g[pr.last]]}.Mapa.to_ParmGr # end # require "algebra/finite-map" def to_map m = Map.phi @perm.each_with_index do |x, i| m.append!(i, x) end m end def decompose_transposition a = [] (0...degree).each do |i| a << [i, self[i]] end r = [] while true a.delete_if{ |i, x| i == x} break if a.empty? i, x = a.shift x, j = alpha = a.assoc(x) a.delete(alpha) unless j == i a.rassoc(i)[1] = j r.unshift [i, j] end r.unshift [i, x] end r end def self.cyclic2perm(c, n = nil) unless n n = c.flatten.max + 1 end a = (0...n).collect{|i| c.each do |b| if j = b.index(i) i = b[(j+1) % b.size] end end i } new(a) end end end if $0 == __FILE__ include Algebra a = [ [Permutation[1, 0, 2], Permutation[2, 0, 1]], [Permutation[0, 2, 1]] ] PermutationGroup.generate_strong(Permutation.unity(3), *a).each do |x| p x end puts S3 = PermutationGroup.symmetric(3) S3.each do |x| p x end puts G = PermutationGroup.generate_strong(Permutation.unity(3), [Permutation[1, 2, 0]], [Permutation[2, 0, 1]]) G.each do |x| p x end puts end