4

In abstract algebra, the notion of a group is fairly fundamental. To get a group, we need a set of objects, and an binary operation with 3 properties (4 if you count closure). If we want to randomly generate a group given a finite set, (that is, randomly generate a table giving the result of every possible combination of elements in the set), then it's pretty easy to hack in an identity element, and hack in inverses, but it seems very hard to randomly generate an operation that is associative.

My question is whether there is some (efficient) way to randomly generate an associative operation. I've tried randomly generating an operation, then perturbing non-associative relationships so that they are associative one at a time, but this doesn't really seem to converge. Any ideas?

deontologician
  • 2,764
  • 1
  • 21
  • 33
  • I would try this question in http://math.stackexchange.com/ – Kiril Kirov Nov 10 '11 at 19:29
  • How can I move it there? – deontologician Nov 10 '11 at 19:41
  • I think you can't, but you can repost it there, if you decide to do so. – Kiril Kirov Nov 10 '11 at 19:43
  • Are you sure this question isn't better suited for [math.se]? This seems more like high-level theoretical mathematics than it is about programming. – Lasse V. Karlsen Nov 11 '11 at 08:43
  • It's about an algorithm for something that is useful in mathematics, but is not particularly high level itself. It's debatable where it should go, but on the whole, the efficiency of the algorithm is important. I can easily write a brute force implementation that follows the mathematical definition exactly. I'm asking here because I want a good implementation. – deontologician Nov 11 '11 at 19:42

4 Answers4

3

This depends only on what is considered "random". One option is to, instead of generating the actual group operation matrix randomly, to pick randomly an associative group from a family of groups that are known to be associative by construction.

For example:

  • Group of integers {0...n-1} with addition modulo n is an associative group
  • Group of integers {1..p-1} with multiplication modulo n is an associative group when p is prime
  • If G and H and two associative groups, then the group (G,H) with group operation (g,h) * (g',h') = (g*g',h*h') is associative
  • if G is a group with group operation * and c is a constant in G, then also the operation @ defined as g @ g' = (g * c) * g' is associative as (g @ g') @ g'' = g * c * g' * c * g'' = g @ (g' @ g'')

So, for example, in order to generate a random group of size N, get a factorization of N into primes N = (p1, ..., pk) (same prime can appear multiple times in that list), then build random products q1, ..., qn from them so that N = q1 * ... * qn, and then for every qi, pick an additive or multiplicative integer group, add random constants, and then use the resulting product group as a random associative group. It won't generate all the associative groups with the same probabilities, but it is still a random process to get a random additive group, and might be much better than filling a matrix randomly especially if you need bigger groups.

Antti Huima
  • 25,136
  • 3
  • 52
  • 71
  • You might find this useful too : http://en.wikipedia.org/wiki/Classification_of_finite_simple_groups You can then potentially break the group up as a combination of finite simple groups. – Michael Anderson Nov 11 '11 at 01:04
  • In particular you need this result too: "A group that is not simple can be broken into two smaller groups, a normal subgroup and the quotient group, and the process can be repeated." (from here http://en.wikipedia.org/wiki/Simple_group ) – Michael Anderson Nov 11 '11 at 01:15
3

You could try Knuth-Bendix completion.

In essence this means that you force your group to be associative by repeatedly identifying the two sides of the associativity equation.

So your group will become smaller than your initial size, but you can again add some elements and continue.

starblue
  • 55,348
  • 14
  • 97
  • 151
  • Would you mind expanding your post a bit, perhaps with a simple example? – deontologician Nov 11 '11 at 20:23
  • If you find that the two sides of associativity give two different elements `x` and `y` then you identify them, that is you replace `y` by `x` everywhere and get rid of `y`. You also need to consider ripple effects by also identifying their sums and inverses. – starblue Nov 11 '11 at 21:02
1

Associativity of binary operations is defined for triples (a, b, c) to be (a * (b * c)) = ((a * b) * c). Therefore, when you go to define a * b randomly, you could simply select at random one of assignments to a * b that doesn't cause associativity to be violated; if there aren't any such assignments, back up and choose a different assignment at the last step. So...

  MakeRandomAssociative(table[1..N, 1..N], elements[1..N], n)
  0. if n = N + 1 return true
  1. a := elements[n mod N]
  2. b := elements[n // N]
  3. candidates = []
  4. for each c in elements do
  5.    table[n mod N,n // N] = c
  6.    if not violates_associativity(table) then candidates.add(c)
  7. if empty(candidates) return false
  8. else then
  9.    c := remove_random(candidates)
  A.    table[n mod N,n // N] = c
  B.    if MakeRandomAssociative(table, elements, n+1) then
  C.       return true
  D.    else goto 7

That's ugly and brute-force, but (the implementation given here might be buggy) it should conceptually find an associative operator which should be "random" in some sense.

Patrick87
  • 27,682
  • 3
  • 38
  • 73
1

Here are some Prolog predicates that generates all binary functions on a give set:

gen_binop(A,BinOp):-
    cartesian(A,Cart),
    gen_func(Cart,A,BinOp).gen_func(Dom,Rng,Func) :-
    is_set(Dom),
    is_set(Rng),
    gen_func(Dom,Rng,[],Tmp),
    reverse(Tmp,Func).

cartesian(A,B,Cart):-
    findall([X,Y],(member(X,A),member(Y,B)),L),
    list_to_set(L,Cart),!.

gen_func([],_,Func,Func).
gen_func([H|T],Rng,Func1,Func) :-
    member(Y,Rng),
    Func2=[[H,Y]|Func1],
    gen_func(T,Rng,Func2,Func).

Finally, we test to see if any given binary operation is non-associative (and then negate that to find the associative ones):

non_assoc_binop(BinOp):-
    domain(BinOp,D),
    flatten(D,A),
    cartesian3(A,A,A,Cart),
    member([X,Y,Z],Cart),
    eval(BinOp,[X,Y],X1),
    eval(BinOp,[Y,Z],Y2),
    eval(BinOp,[X1,Z],U),
    eval(BinOp,[X,Y2],V),
    U\=V.

eval(F,X,Y) :-
    function(F),
    member([X,Y],F).

function(PL) :-
    pair_list(PL),
    forall(image(PL,_,ImgX),func_image(PL,ImgX)).

image(PL,X,ImgX) :-
    pair_list(PL),
    domain(PL,Dom),
    member(X,Dom),
    findall(Y,member([X,Y],PL),L),
    list_to_set(L,ImgX).

func_image(PL,ImgX) :-
    image(PL,_,ImgX),
    length(ImgX,1).

pair_list([]).
pair_list([[_,_]|T]) :-
    pair_list(T).
Taryn
  • 242,637
  • 56
  • 362
  • 405