From 780e9c72720155d59edc853965a093cd36e58556 Mon Sep 17 00:00:00 2001 From: reiniscirpons Date: Sun, 5 Jul 2020 20:20:28 +0100 Subject: [PATCH 1/6] Add first 'working' version of semigroup elements by graph --- gap/fp/freeband.gd | 3 + gap/fp/freeband.gi | 146 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) diff --git a/gap/fp/freeband.gd b/gap/fp/freeband.gd index d60085d0b..e9b9418d7 100644 --- a/gap/fp/freeband.gd +++ b/gap/fp/freeband.gd @@ -18,3 +18,6 @@ DeclareGlobalFunction("FreeBand"); DeclareAttribute("ContentOfFreeBandElement", IsFreeBandElement); DeclareAttribute("ContentOfFreeBandElementCollection", IsFreeBandElementCollection); + +DeclareCategory("IsFreeBandElementByGraph", IsAssociativeElement); +DeclareCategoryCollections("IsFreeBandElementByGraph"); diff --git a/gap/fp/freeband.gi b/gap/fp/freeband.gi index d507e0a8b..1f6108ad9 100644 --- a/gap/fp/freeband.gi +++ b/gap/fp/freeband.gi @@ -550,3 +550,149 @@ function(x, hashlen) return rec(func := SEMIGROUPS.HashFunctionForFreeBandElements, data := hashlen); end); + +SEMIGROUPS.FreeBandElementByGraphInsertNode := function(x, tuple) + local u, i; + + if tuple in x!.lookup then + return x!.lookup[tuple]; + fi; + + x!.cont[tuple[1]] := true; + x!.cont[tuple[3]] := true; + + if Length(x!.graveyard) <> 0 then + u := Remove(x!.graveyard); + for i in [2, 4] do + if x!.graph[u][i] <> 0 then + x!.indeg[x!.graph[u][i]] := x!.indeg[x!.graph[u][i]] - 1; + if x!.indeg[x!.graph[u][i]] = 0 then + Add(x!.graveyard, x!.graph[u][i]); + fi; + fi; + od; + Unbind(x!.lookup[x!.graph[u]]); + x!.graph[u] := tuple; + else + u := Length(x!.graph) + 1; + Add(x!.graph, tuple); + Add(x!.indeg, 0); + fi; + + x!.lookup[tuple] := u; + + if x!.root = tuple[2] or x!.root = tuple[4] then + x!.root := u; + fi; + + for i in [2, 4] do + if tuple[i] <> 0 then + x!.indeg[tuple[i]] := x!.indeg[tuple[i]] + 1; + fi; + od; + return u; +end; + +SEMIGROUPS.FreeBandElementByGraphRightMultiplyByLetter := function(x, a) + local u, v, w, add_spine; + + add_spine := function(v) + local first, curr, prev; + if x!.graph[v][3] <> 0 then + first := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, v, x!.graph[v][3], 0]); + else + first := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, v, a, v]); + return first; + fi; + prev := first; + while v <> 0 do + v := x!.graph[v][4]; + if x!.graph[v][3] <> 0 then + curr := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, v, x!.graph[v][3], 0]); + else + curr := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, v, a, v]); + x!.graph[prev][4] := curr; + x!.indeg[curr] := x!.indeg[curr] + 1; + return first; + fi; + x!.graph[prev][4] := curr; + x!.indeg[curr] := x!.indeg[curr] + 1; + if x!.graph[v][4] = 0 then + x!.graph[curr][4] := v; + x!.indeg[v] := x!.indeg[v] + 1; + fi; + prev := curr; + od; + return first; + end; + + if not x!.cont[a] then + x!.root := add_spine(x!.root); + else + u := x!.root; + while x!.graph[u][3] <> a do + u := x!.graph[u][4]; + od; + w := x!.graph[u][4]; + v := x!.graph[w][4]; + if v <> 0 then + x!.indeg[w] := x!.indeg[w] - 1; + if x!.indeg[w] = 0 then + Add(x!.graveyard, w); + fi; + x!.graph[w][4] := 0; + x!.graph[u][3] := x!.graph[w][3]; + x!.indeg[v] := x!.indeg[v] - 1; + x!.graph[u][4] := add_spine(v); + x!.indeg[x!.graph[u][4]] := x!.indeg[x!.graph[u][4]] + 1; + fi; + fi; +end; + +SEMIGROUPS.FreeBandElementByGraphRemoveDeadVertices := function(x) + local i, j, u, v; + i := 1; + u := Length(x!.graph); + while i <= Length(x!.graveyard) and u > 0 do + v := x!.graveyard[i]; + if u <> v then + if u = x!.root then + x!.root := v; + fi; + x!.indeg[v] := x!.indeg[u]; + x!.graph[v] := x!.graph[u]; + fi; + Remove(x!.graph); + Remove(x!.indeg); + od; + for i in [1 .. Length(x!.graph)] do + for j in [2, 4] do + if x!.graph[i][j] > u then + x!.graph[i][j] := x!.graveyard[x!.graph[i][j] - u]; + fi; + od; + od; + x!.graveyard := []; +end; + +SEMIGROUPS.FreeBandElementByGraph := function(S) + local F, type, x, s; + F := NewFamily("FreeBandElementsByGraphFamily", IsFreeBandElementByGraph); + type := NewType(F, IsFreeBandElementByGraph and IsPositionalObjectRep); + x := Objectify(type, rec(root := 1, + graph := [[0, 0, 0, 0]], + cont := BlistList([1 .. Maximum(S)], []), + graveyard := [], + indeg := [0], + lookup := HashMap())); + x!.lookup[[0, 0, 0, 0]] := 1; + for s in S do + SEMIGROUPS.FreeBandElementByGraphRightMultiplyByLetter(x, s); + od; + # SEMIGROUPS.FreeBandElementByGraphRemoveDeadVertices(x); + return x; +end; From 0b9f26d9aa7e1dcc64e46cd8b71fcac6b7537a96 Mon Sep 17 00:00:00 2001 From: reiniscirpons Date: Sun, 5 Jul 2020 23:55:56 +0100 Subject: [PATCH 2/6] Fix irredundancy condition, add DotString method --- gap/fp/freeband.gi | 90 +++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/gap/fp/freeband.gi b/gap/fp/freeband.gi index 1f6108ad9..6891d6a5e 100644 --- a/gap/fp/freeband.gi +++ b/gap/fp/freeband.gi @@ -561,6 +561,12 @@ SEMIGROUPS.FreeBandElementByGraphInsertNode := function(x, tuple) x!.cont[tuple[1]] := true; x!.cont[tuple[3]] := true; + for i in [2, 4] do + if tuple[i] <> 0 then + x!.indeg[tuple[i]] := x!.indeg[tuple[i]] + 1; + fi; + od; + if Length(x!.graveyard) <> 0 then u := Remove(x!.graveyard); for i in [2, 4] do @@ -568,10 +574,10 @@ SEMIGROUPS.FreeBandElementByGraphInsertNode := function(x, tuple) x!.indeg[x!.graph[u][i]] := x!.indeg[x!.graph[u][i]] - 1; if x!.indeg[x!.graph[u][i]] = 0 then Add(x!.graveyard, x!.graph[u][i]); + Unbind(x!.lookup[x!.graph[u][i]]); fi; fi; od; - Unbind(x!.lookup[x!.graph[u]]); x!.graph[u] := tuple; else u := Length(x!.graph) + 1; @@ -585,11 +591,6 @@ SEMIGROUPS.FreeBandElementByGraphInsertNode := function(x, tuple) x!.root := u; fi; - for i in [2, 4] do - if tuple[i] <> 0 then - x!.indeg[tuple[i]] := x!.indeg[tuple[i]] + 1; - fi; - od; return u; end; @@ -597,37 +598,19 @@ SEMIGROUPS.FreeBandElementByGraphRightMultiplyByLetter := function(x, a) local u, v, w, add_spine; add_spine := function(v) - local first, curr, prev; - if x!.graph[v][3] <> 0 then - first := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, - [a, v, x!.graph[v][3], 0]); - else - first := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, - [a, v, a, v]); - return first; - fi; - prev := first; - while v <> 0 do + local u, que; + que := []; + while x!.graph[v][1] <> 0 do + Add(que, v); v := x!.graph[v][4]; - if x!.graph[v][3] <> 0 then - curr := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, - [a, v, x!.graph[v][3], 0]); - else - curr := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, - [a, v, a, v]); - x!.graph[prev][4] := curr; - x!.indeg[curr] := x!.indeg[curr] + 1; - return first; - fi; - x!.graph[prev][4] := curr; - x!.indeg[curr] := x!.indeg[curr] + 1; - if x!.graph[v][4] = 0 then - x!.graph[curr][4] := v; - x!.indeg[v] := x!.indeg[v] + 1; - fi; - prev := curr; od; - return first; + v := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, [a, v, a, v]); + while Length(que) > 0 do + u := Remove(que); + v := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, u, x!.graph[u][3], v]); + od; + return v; end; if not x!.cont[a] then @@ -643,12 +626,13 @@ SEMIGROUPS.FreeBandElementByGraphRightMultiplyByLetter := function(x, a) x!.indeg[w] := x!.indeg[w] - 1; if x!.indeg[w] = 0 then Add(x!.graveyard, w); + Unbind(x!.lookup[x!.graph[w]]); fi; - x!.graph[w][4] := 0; + Unbind(x!.lookup[x!.graph[u]]); x!.graph[u][3] := x!.graph[w][3]; - x!.indeg[v] := x!.indeg[v] - 1; x!.graph[u][4] := add_spine(v); x!.indeg[x!.graph[u][4]] := x!.indeg[x!.graph[u][4]] + 1; + x!.lookup[x!.graph[u]] := u; fi; fi; end; @@ -679,6 +663,38 @@ SEMIGROUPS.FreeBandElementByGraphRemoveDeadVertices := function(x) x!.graveyard := []; end; +SEMIGROUPS.FreeBandElementByGraphDotString := function(x) + local S, i; + S := "//dot\ndigraph {\nedge [colorscheme=set19]\n"; + S := Concatenation(S, "node [shape=circle style=filled colorscheme=set19]\n"); + x!.graveyard := Set(x!.graveyard); + for i in [1 .. Length(x!.graph)] do + if i in x!.graveyard then + S := Concatenation(S, String(i), " [fillcolor=white]\n"); + else + S := Concatenation(S, String(i), "\n"); + fi; + od; + for i in [1 .. Length(x!.graph)] do + if x!.graph[i][2] <> 0 then + S := Concatenation(S, String(i), "->", + String(x!.graph[i][2]), + " [arrowhead=empty color=", + String(x!.graph[i][1]), + "]\n"); + fi; + if x!.graph[i][4] <> 0 then + S := Concatenation(S, String(i), "->", + String(x!.graph[i][4]), + " [arrowhead=normal color=", + String(x!.graph[i][3]), + "]\n"); + fi; + od; + S := Concatenation(S, "}"); + return S; +end; + SEMIGROUPS.FreeBandElementByGraph := function(S) local F, type, x, s; F := NewFamily("FreeBandElementsByGraphFamily", IsFreeBandElementByGraph); From d0e43aad9fcd2212f58f312f08af3c3186f8e445 Mon Sep 17 00:00:00 2001 From: reiniscirpons Date: Tue, 7 Jul 2020 16:26:14 +0100 Subject: [PATCH 3/6] Add equality testing and fix up node reuse --- gap/fp/freeband.gi | 113 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 97 insertions(+), 16 deletions(-) diff --git a/gap/fp/freeband.gi b/gap/fp/freeband.gi index 6891d6a5e..7d7368003 100644 --- a/gap/fp/freeband.gi +++ b/gap/fp/freeband.gi @@ -638,29 +638,52 @@ SEMIGROUPS.FreeBandElementByGraphRightMultiplyByLetter := function(x, a) end; SEMIGROUPS.FreeBandElementByGraphRemoveDeadVertices := function(x) - local i, j, u, v; + local l, r, i, j, n, u, v, is_dead, new_pos; i := 1; - u := Length(x!.graph); - while i <= Length(x!.graveyard) and u > 0 do - v := x!.graveyard[i]; - if u <> v then - if u = x!.root then - x!.root := v; + n := Length(x!.graveyard); + while i <= n do + u := x!.graveyard[i]; + for j in [2, 4] do + v := x!.graph[u][j]; + x!.indeg[v] := x!.indeg[v] - 1; + if x!.indeg[v] = 0 then + Add(x!.graveyard, v); + Unbind(x!.lookup[x!.graph[v]]); + n := n + 1; fi; - x!.indeg[v] := x!.indeg[u]; - x!.graph[v] := x!.graph[u]; + od; + i := i + 1; + od; + is_dead := BlistList([1 .. Length(x!.graph)], x!.graveyard); + new_pos := ListWithIdenticalEntries(Length(x!.graph), 0); + i := 1; + for u in [1 .. Length(x!.graph)] do + if not is_dead[u] then + new_pos[u] := i; + i := i + 1; fi; - Remove(x!.graph); - Remove(x!.indeg); od; - for i in [1 .. Length(x!.graph)] do - for j in [2, 4] do - if x!.graph[i][j] > u then - x!.graph[i][j] := x!.graveyard[x!.graph[i][j] - u]; + x!.root := new_pos[x!.root]; + x!.lookup := HashMap(); + for u in [1 .. Length(x!.graph)] do + if not is_dead[u] then + l := 0; + if x!.graph[u][2] <> 0 then + l := new_pos[x!.graph[u][2]]; fi; - od; + r := 0; + if x!.graph[u][4] <> 0 then + r := new_pos[x!.graph[u][4]]; + fi; + x!.graph[new_pos[u]] := [x!.graph[u][1], l, x!.graph[u][3], r]; + x!.indeg[new_pos[u]] := x!.indeg[u]; + x!.lookup[x!.graph[new_pos[u]]] := new_pos[u]; + fi; od; + x!.graph := x!.graph{[1 .. i - 1]}; + x!.indeg := x!.indeg{[1 .. i - 1]}; x!.graveyard := []; + return x!.root; end; SEMIGROUPS.FreeBandElementByGraphDotString := function(x) @@ -712,3 +735,61 @@ SEMIGROUPS.FreeBandElementByGraph := function(S) # SEMIGROUPS.FreeBandElementByGraphRemoveDeadVertices(x); return x; end; + +SEMIGROUPS.FreeBandElementByGraphIsEqual := function(x, y) + local que, u, v, seen_x, seen_y, i; + if x!.cont <> y!.cont then + return false; + fi; + que := [[x!.root, y!.root]]; + seen_x := BlistList([1 .. Length(x!.graph)], []); + seen_x[x!.root] := true; + seen_y := BlistList([1 .. Length(y!.graph)], []); + seen_y[y!.root] := true; + while Length(que) <> 0 do + u := Remove(que); + v := u[2]; + u := u[1]; + if x!.graph[u][1] <> y!.graph[v][1] or x!.graph[u][3] <> y!.graph[v][3] then + return false; + fi; + for i in [2, 4] do + if (x!.graph[u][i] = 0 and y!.graph[v][i] <> 0) or + (x!.graph[u][i] <> 0 and y!.graph[v][i] = 0) then + return false; + fi; + if x!.graph[u][i] <> 0 then + if (seen_x[x!.graph[u][i]] and not seen_y[y!.graph[v][i]]) or + (not seen_x[x!.graph[u][i]] and seen_y[y!.graph[v][i]]) then + return false; + fi; + if not seen_x[x!.graph[u][i]] then + Add(que, [x!.graph[u][i], y!.graph[v][i]]); + seen_x[x!.graph[u][i]] := true; + seen_y[y!.graph[v][i]] := true; + fi; + fi; + od; + od; + return true; +end; + +SEMIGROUPS.FreeBandElementByGraphCanonicalWord := function(x) + local S, recursive_step; + + recursive_step := function(u, l, r) + local m; + if x!.graph[u][1] = 0 then + return; + fi; + m := QuoInt(r + l, 2); + S[m] := x!.graph[u][1]; + S[m + 1] := x!.graph[u][3]; + recursive_step(x!.graph[u][2], l, m - 1); + recursive_step(x!.graph[u][4], m + 2, r); + end; + + S := ListWithIdenticalEntries(2 ^ (SizeBlist(x!.cont) + 1) - 2, 0); + recursive_step(x!.root, 1, Length(S)); + return S; +end; From e167e2f3f9f83cdc8372f3204dd3cb58a58505b7 Mon Sep 17 00:00:00 2001 From: reiniscirpons Date: Wed, 15 Jul 2020 17:02:02 +0100 Subject: [PATCH 4/6] Quick save before complete letter-mult rewrite to fix bug --- gap/fp/freeband.gi | 88 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/gap/fp/freeband.gi b/gap/fp/freeband.gi index 7d7368003..a28910498 100644 --- a/gap/fp/freeband.gi +++ b/gap/fp/freeband.gi @@ -595,7 +595,7 @@ SEMIGROUPS.FreeBandElementByGraphInsertNode := function(x, tuple) end; SEMIGROUPS.FreeBandElementByGraphRightMultiplyByLetter := function(x, a) - local u, v, w, add_spine; + local que, u, v, w, add_spine; add_spine := function(v) local u, que; @@ -616,23 +616,29 @@ SEMIGROUPS.FreeBandElementByGraphRightMultiplyByLetter := function(x, a) if not x!.cont[a] then x!.root := add_spine(x!.root); else + que = [x!.root]; u := x!.root; while x!.graph[u][3] <> a do u := x!.graph[u][4]; + Add(que, u); od; w := x!.graph[u][4]; v := x!.graph[w][4]; - if v <> 0 then - x!.indeg[w] := x!.indeg[w] - 1; - if x!.indeg[w] = 0 then - Add(x!.graveyard, w); - Unbind(x!.lookup[x!.graph[w]]); - fi; - Unbind(x!.lookup[x!.graph[u]]); - x!.graph[u][3] := x!.graph[w][3]; - x!.graph[u][4] := add_spine(v); - x!.indeg[x!.graph[u][4]] := x!.indeg[x!.graph[u][4]] + 1; - x!.lookup[x!.graph[u]] := u; + + v := SEMIGROUPS.FreeBandElementByGraphInsertNode( + [x!.graph[u][1], x!.graph[u][2], + x!.graph[w][3], add_spine(v)]); + while v <> u do + od; + x!.indeg[w] := x!.indeg[w] - 1; + Unbind(x!.lookup[x!.graph[u]]); + x!.graph[u][3] := x!.graph[w][3]; + x!.graph[u][4] := add_spine(v); + x!.indeg[x!.graph[u][4]] := x!.indeg[x!.graph[u][4]] + 1; + x!.lookup[x!.graph[u]] := u; + if x!.indeg[w] = 0 then + Add(x!.graveyard, w); + Unbind(x!.lookup[x!.graph[w]]); fi; fi; end; @@ -774,22 +780,50 @@ SEMIGROUPS.FreeBandElementByGraphIsEqual := function(x, y) return true; end; -SEMIGROUPS.FreeBandElementByGraphCanonicalWord := function(x) - local S, recursive_step; +SEMIGROUPS.FreeBandElementByGraphCopy := function(x) + local lookup, key; + lookup := HashMap(); + for key in Keys(x!.lookup) do + lookup[key] := x!.lookup[key]; + od; + return Objectify(TypeObj(x), + rec(root := x!.root, + graph := ShallowCopy(x!.graph), + cont := ShallowCopy(x!.cont), + graveyard := ShallowCopy(x!.graveyard), + indeg := ShallowCopy(x!.indeg), + lookup := lookup)); +end; - recursive_step := function(u, l, r) - local m; - if x!.graph[u][1] = 0 then - return; +SEMIGROUPS.FreeBandElementByGraphCanonicalWord := function(x) + local S, que, u, v, w; + S := []; + que := []; + u := x!.root; + while x!.graph[u][1] <> 0 do + Add(que, u); + u := x!.graph[u][2]; + od; + while Length(que) <> 0 do + u := Remove(que); + Add(S, x!.graph[u][1]); + v := x!.graph[u][2]; + w := x!.graph[u][4]; + while x!.graph[w][1] <> 0 do + if x!.graph[w][1] = x!.graph[u][1] and + x!.graph[v][3] = x!.graph[u][3] then + u := w; + v := x!.graph[u][2]; + w := x!.graph[u][4]; + else + Add(que, w); + w := x!.graph[w][2]; + v := x!.graph[v][4]; + fi; + od; + if x!.graph[u][1] <> x!.graph[u][3] then + Add(S, x!.graph[u][3]); fi; - m := QuoInt(r + l, 2); - S[m] := x!.graph[u][1]; - S[m + 1] := x!.graph[u][3]; - recursive_step(x!.graph[u][2], l, m - 1); - recursive_step(x!.graph[u][4], m + 2, r); - end; - - S := ListWithIdenticalEntries(2 ^ (SizeBlist(x!.cont) + 1) - 2, 0); - recursive_step(x!.root, 1, Length(S)); + od; return S; end; From 00a48eeca58a1208138ae806eeb82af3e7108432 Mon Sep 17 00:00:00 2001 From: reiniscirpons Date: Wed, 15 Jul 2020 22:12:40 +0100 Subject: [PATCH 5/6] Fix letter mult via complete rewrite --- gap/fp/freeband.gi | 91 ++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 43 deletions(-) diff --git a/gap/fp/freeband.gi b/gap/fp/freeband.gi index a28910498..dfbe07daf 100644 --- a/gap/fp/freeband.gi +++ b/gap/fp/freeband.gi @@ -574,7 +574,7 @@ SEMIGROUPS.FreeBandElementByGraphInsertNode := function(x, tuple) x!.indeg[x!.graph[u][i]] := x!.indeg[x!.graph[u][i]] - 1; if x!.indeg[x!.graph[u][i]] = 0 then Add(x!.graveyard, x!.graph[u][i]); - Unbind(x!.lookup[x!.graph[u][i]]); + Unbind(x!.lookup[x!.graph[x!.graph[u][i]]]); fi; fi; od; @@ -595,52 +595,57 @@ SEMIGROUPS.FreeBandElementByGraphInsertNode := function(x, tuple) end; SEMIGROUPS.FreeBandElementByGraphRightMultiplyByLetter := function(x, a) - local que, u, v, w, add_spine; - - add_spine := function(v) - local u, que; - que := []; - while x!.graph[v][1] <> 0 do - Add(que, v); - v := x!.graph[v][4]; - od; - v := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, [a, v, a, v]); - while Length(que) > 0 do - u := Remove(que); - v := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, - [a, u, x!.graph[u][3], v]); - od; - return v; - end; + local que, u, v, w; - if not x!.cont[a] then - x!.root := add_spine(x!.root); - else - que = [x!.root]; - u := x!.root; - while x!.graph[u][3] <> a do - u := x!.graph[u][4]; - Add(que, u); - od; - w := x!.graph[u][4]; - v := x!.graph[w][4]; + if x!.graph[x!.root][1] = 0 then + x!.root := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, x!.root, a, x!.root]); + return; + fi; - v := SEMIGROUPS.FreeBandElementByGraphInsertNode( - [x!.graph[u][1], x!.graph[u][2], - x!.graph[w][3], add_spine(v)]); - while v <> u do - od; - x!.indeg[w] := x!.indeg[w] - 1; - Unbind(x!.lookup[x!.graph[u]]); - x!.graph[u][3] := x!.graph[w][3]; - x!.graph[u][4] := add_spine(v); - x!.indeg[x!.graph[u][4]] := x!.indeg[x!.graph[u][4]] + 1; - x!.lookup[x!.graph[u]] := u; - if x!.indeg[w] = 0 then - Add(x!.graveyard, w); - Unbind(x!.lookup[x!.graph[w]]); + u := x!.root; + que := []; + while x!.graph[u][1] <> 0 do + Add(que, u); + u := x!.graph[u][4]; + od; + u := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, u, a, u]); + v := Remove(que); + if u = v then + return; + fi; + while Length(que) > 0 do + w := v; + v := Remove(que); + if x!.graph[v][3] = a then + break; fi; + u := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, w, x!.graph[w][3], u]); + od; + + if x!.graph[v][3] <> a then + x!.root := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [a, v, x!.graph[v][3], u]); + return; fi; + + u := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [x!.graph[v][1], x!.graph[v][2], x!.graph[w][3], u]); + + while Length(que) > 0 do + v := Remove(que); + u := SEMIGROUPS.FreeBandElementByGraphInsertNode(x, + [x!.graph[v][1], x!.graph[v][2], x!.graph[v][3], u]); + od; + + if u <> v then + Add(x!.graveyard, v); + Unbind(x!.lookup[x!.graph[v]]); + fi; + + x!.root := u; end; SEMIGROUPS.FreeBandElementByGraphRemoveDeadVertices := function(x) From 9be7f626eabff8f4a68628a5874128888571b11f Mon Sep 17 00:00:00 2001 From: reiniscirpons Date: Wed, 15 Jul 2020 22:17:19 +0100 Subject: [PATCH 6/6] Add canonical form due to Tom --- gap/fp/freeband.gi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gap/fp/freeband.gi b/gap/fp/freeband.gi index dfbe07daf..468d117b9 100644 --- a/gap/fp/freeband.gi +++ b/gap/fp/freeband.gi @@ -816,7 +816,8 @@ SEMIGROUPS.FreeBandElementByGraphCanonicalWord := function(x) w := x!.graph[u][4]; while x!.graph[w][1] <> 0 do if x!.graph[w][1] = x!.graph[u][1] and - x!.graph[v][3] = x!.graph[u][3] then + x!.graph[v][3] = x!.graph[u][3] and + x!.graph[w][2] = x!.graph[v][4] then u := w; v := x!.graph[u][2]; w := x!.graph[u][4];