1############################################################################
2##
3#W pargap/consist.gi		LPRES				René Hartung
4##
5
6############################################################################
7##
8#F  LPRESPar_ListOfConsistencyChecks( <coll>, <weights> )
9##
10## parallel version for consistency-checks.
11##
12InstallGlobalFunction( LPRESPar_ListOfConsistencyChecks,
13  function( coll, weights )
14  local Checks, # list of consistency checks
15	n,	# number of generators
16	I, 	# list of generators with finite relative order
17	c, 	# the nilpotency class
18  	i,j,k;	# loop variables
19
20  # the number of generators
21  n := coll![ PC_NUMBER_OF_GENERATORS ];
22
23  # generators with finite relative order
24  I := Filtered( [1..n], x -> IsBound( coll![ PC_EXPONENTS ][x] ) );
25
26  # the nilpotency class
27  c := Maximum( weights );
28
29  # initialize list of consistency checks which we send to the slaves
30  Checks := [];
31
32  # k ( j i ) = ( k j ) i
33  for k in [ n, n-1 .. 1 ] do
34    for j in [ k-1, k-2 .. 1 ] do
35      for i in [ 1 .. j-1 ] do
36        if weights[i] + weights[j] + weights[k] <= c then
37          Add( Checks, [ k, j, i ] );
38        else
39          break;
40        fi;
41      od;
42    od;
43  od;
44
45  # j ^ m i = j ^ (m-1) ( j i )
46  for j in Reversed( I ) do
47    for i in [ 1 .. j-1 ] do
48      if weights[j] + weights[i] <= c then
49        Add( Checks, [ -j, i ] );
50      else
51        break;
52      fi;
53    od;
54  od;
55
56  # j i ^ m  = ( j i ) i ^ (m-1)
57  for i in I do
58    for j in [ i+1 .. n ] do
59      if weights[i] + weights[j] <= c then
60        Add( Checks, [ j, -i ] );
61      else
62        break;
63      fi;
64    od;
65  od;
66
67  # i ^ m i = i i ^ m
68  for i in [ 1 .. n ] do
69    if IsBound(  coll![ PC_EXPONENTS ][i] ) then
70      if 2 * weights[i] <= c then
71        Add( Checks, [ i ] );
72      else
73        break;
74      fi;
75    fi;
76  od;
77
78  # j = ( j i ^ -1 ) i
79  for i in [ 1 .. n ] do
80    if not IsBound( coll![ PC_EXPONENTS ][i] ) then
81      for j in [ i+1 .. n ] do
82        if weights[i] + weights[j] <= c then
83          Add( Checks, [ -j, -i ] );
84        else
85          break;
86        fi;
87      od;
88    fi;
89  od;
90
91  # i = j ^ -1 ( j i )
92  for j in [ 1 .. n ] do
93    if not IsBound( coll![ PC_EXPONENTS ][j] ) then
94      for i in [ 1 .. j-1 ] do
95        if weights[i] + weights[j] <= c then
96          Add( Checks, [ -i, -j ] );
97
98          if not IsBound( coll![ PC_EXPONENTS ][i] ) then
99            # i ^ -1 = j ^ -1 ( j i ^ -1 )
100            Add( Checks, [ j, i ] );
101          fi;
102        else
103          break;
104        fi;
105      od;
106    fi;
107  od;
108
109  return( Checks );
110  end);
111
112############################################################################
113##
114#F  LPRESPar_CheckConsRel( <coll>, <job> )
115##
116## function for checking overlaps on the slaves.
117##
118InstallGlobalFunction( LPRESPar_CheckConsRel,
119  function( coll, job )
120  local ev1,ev2,# exponent vectors
121	w,	# ExtRepOfObj of a PcpElement
122	n,	# number of generators
123	m,	# relative order of a generator
124	i,j,k;	# loop variables
125
126  # number of generators
127  n := coll![ PC_NUMBER_OF_GENERATORS ];
128
129  if Length( job ) = 3 then
130    # k ( j i ) = ( k j ) i
131    k := job[1]; j := job[2]; i := job[3];
132    repeat
133      ev1 := ListWithIdenticalEntries( n, 0 );;
134    until CollectWordOrFail( coll, ev1, [ j, 1, i, 1 ] ) <> fail;
135
136    w := ObjByExponents( coll, ev1 );
137    repeat
138      ev1 := ExponentsByObj( coll, [ k, 1 ] );
139    until CollectWordOrFail( coll, ev1, w ) <> fail;
140
141    repeat
142      ev2 := ListWithIdenticalEntries( n, 0 );
143    until CollectWordOrFail( coll, ev2, [ k, 1, j, 1, i, 1 ] ) <> fail;;
144
145    return( ev1 - ev2 );
146  fi;
147
148  if Length( job ) = 2 then
149    if ( IsPosInt( - job[1] ) and IsPosInt( job[2] ) ) and
150                   - job[1] > job[2]  then
151
152      # j ^ m i = j ^ (m-1) ( j i )
153      j := -job[1]; i := job[2];
154      m := coll![ PC_EXPONENTS ][j];
155
156      repeat
157        ev1 := ListWithIdenticalEntries( n, 0 );
158      until CollectWordOrFail( coll, ev1, [ j, m-1, j, 1, i, 1 ] ) <> fail;
159
160      repeat
161        ev2 := ListWithIdenticalEntries( n, 0 );
162      until CollectWordOrFail( coll, ev2, [ j, 1, i, 1 ] ) <> fail;
163
164      w := ObjByExponents( coll, ev2 );
165      repeat
166        ev2 := ExponentsByObj( coll, [ j, m-1 ] );
167      until CollectWordOrFail( coll, ev2, w ) <> fail;
168
169      return( ev1 - ev2 );
170    elif ( IsPosInt( job[1] ) and IsPosInt( - job[2] ) ) and
171                     job[1] > - job[2] then
172      # j i ^ m  = ( j i ) i ^ (m-1)
173      j := job[1]; i := - job[2];
174      m := coll![ PC_EXPONENTS ][i];
175
176      if IsBound( coll![ PC_POWERS ][i] ) then
177        repeat
178          ev1 := ExponentsByObj( coll, [ j, 1 ]);
179        until CollectWordOrFail( coll, ev1, coll![ PC_POWERS ][i] ) <> fail;
180      else
181        ev1 := ExponentsByObj( coll, [ j, 1 ] );
182      fi;
183
184      repeat
185        ev2 := ListWithIdenticalEntries( n, 0 );
186      until CollectWordOrFail( coll, ev2, [ j, 1, i, m ] ) <> fail;
187
188      return( ev1 - ev2 );
189    elif ( IsPosInt( - job[1] ) and IsPosInt( - job[2] ) ) then
190      if - job[1] > - job[2] then
191        # j = ( j i ^ -1 ) i
192        j := - job[1]; i := - job[2];
193        repeat
194          ev1 := ListWithIdenticalEntries( n, 0 );
195        until CollectWordOrFail( coll, ev1, [ j, 1, i, -1, i, 1 ] ) <> fail;
196        ev1[j] := ev1[j] - 1;
197
198        return( ev1 );
199      elif - job[1] < - job[2] then
200        # i = j ^ -1 ( j i )
201        j := - job[2]; i := - job[1];
202        repeat
203          ev1 := ListWithIdenticalEntries( n, 0 );
204        until CollectWordOrFail( coll, ev1, [ j, 1, i, 1 ] ) <> fail;
205
206        w := ObjByExponents( coll, ev1 );
207        repeat
208          ev1 := ExponentsByObj( coll, [ j, -1 ] );
209        until CollectWordOrFail( coll, ev1, w ) <> fail;
210
211        return( ev1 - ExponentsByObj( coll, [ i, 1 ] ) );
212      else
213        Error("in LPRESPar_CheckConsistencyRelations");
214      fi;
215    elif IsPosInt( job[1] ) and IsPosInt( job[2] ) then
216      #  i ^ -1 = j ^ -1 ( j i ^-1 )
217      j := job[1]; i := job[2];
218
219      repeat
220        ev1 := ListWithIdenticalEntries( n, 0 );
221      until CollectWordOrFail( coll, ev1, [ j, 1, i, -1 ] ) <> fail;
222
223      w := ObjByExponents( coll, ev1 );
224      repeat
225        ev1 := ExponentsByObj( coll, [ j, -1 ] );
226      until CollectWordOrFail( coll, ev1, w ) <> fail;
227
228      return( ExponentsByObj( coll, [ i, -1 ] ) - ev1 );
229    fi;
230  fi;
231
232  if Length( job ) = 1 then
233    # i ^ m i = i i ^ m
234    i := job[1];
235    m := coll![ PC_EXPONENTS ][i];
236
237    repeat
238      ev1 := ListWithIdenticalEntries( n, 0 );
239    until CollectWordOrFail( coll, ev1, [ i, m+1 ] ) <> fail;
240
241    if IsBound( coll![ PC_POWERS ][i] ) then
242      repeat
243        ev2 := ExponentsByObj( coll, [ i, 1 ] );
244      until CollectWordOrFail( coll, ev2, coll![ PC_POWERS ][i] ) <> fail;
245    else
246      ev2 := ExponentsByObj( coll, [ i, 1 ] );
247    fi;
248    return( ev1 - ev2 );
249  fi;
250
251  Error("still missing consistency check");
252  end);
253
254############################################################################,
255##
256#F  LPRESPar_MSCheckConsistencyRelations( <weights> )
257##
258ParInstallTOPCGlobalFunction( "LPRESPar_MSCheckConsistencyRelations",
259  function( weights )
260  local	HNF,	# the Hermite normal form
261  	Checks,	# a list of consistency checks
262	b,	# position of the first tail
263  	n,	# number of generators of the collector
264	SubmitTaskInput, DoTask, CheckTaskResult; # MasterSlave-functions
265
266  # initialization
267  HNF := rec( mat := [], Heads := [] );
268  n := ReadEvalFromString( "ftl" )![ PC_NUMBER_OF_GENERATORS ];
269  b := Position( weights, Maximum( weights ));
270
271  Checks := LPRESPar_ListOfConsistencyChecks( ReadEvalFromString("ftl"),
272                                            weights );
273
274  SubmitTaskInput := TaskInputIterator( Checks );
275
276  DoTask := x -> LPRESPar_CheckConsRel( ReadEvalFromString("ftl"), x ){[b..n]};
277
278  CheckTaskResult := function( input, output )
279    local ev;
280    for ev in output do LPRES_AddRow( HNF, ev ); od;
281    return NO_ACTION;
282    end;
283
284  MasterSlave( SubmitTaskInput, DoTask, CheckTaskResult, Error, 5 );
285
286  return( HNF );
287  end);
288
289
290############################################################################
291##
292#F LPRESPar_CheckConsistencyRelations( <coll>, <weights> )
293##
294InstallGlobalFunction( LPRESPar_CheckConsistencyRelations,
295  function( ftl, weights )
296  local HNF;
297
298  # define the collector on the slaves
299  ParEval( PrintToString( "fnc:=", LPRESPar_CollectorToFunction( ftl ) ) );
300  ParEval( "ftl := fnc();");
301  ParEval( "Unbind( fnc );" );
302
303  # parallel consistency checks
304  HNF := LPRESPar_MSCheckConsistencyRelations( weights );
305
306  return( HNF );
307  end);
308