Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/ferret/lib/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 11.8.2025 mit Größe 16 kB image not shown  

Quelle  yapb.gi   Sprache: unbekannt

 
#############################################################################
##
##
#W  yapb.gi                Ferret Package                Chris Jefferson
##
##  Installation file for functions of the Ferret package.
##
#Y  Copyright (C) 2013-2014 University of St. Andrews, North Haugh,
#Y                          St. Andrews, Fife KY16 9SS, Scotland
##

####
# Functions and variables beginning '_YAPB' are only called
# from C++ by YAPB.
####

_YAPB_Globals := [];

# Have a copy of this in each thread in HPCGAP
# This store references to variables we are using inside ferret,
# to make sure they don't get garbage collected.
if IsBound( MakeThreadLocal )  then
  MakeThreadLocal("_YAPB_Globals");
fi;

_YAPB_addRef := function(obj)
  Add(_YAPB_Globals, obj);
end;

_YAPB_checkRef := function(obj)
  return ForAny(_YAPB_Globals, x -> IsIdenticalObj(x, obj));
end;

_YAPB_clearRefs := function()
  _YAPB_Globals := [];
end;

_YAPB_getPermTo := function(sc, i)
  local current_perm, current_pos, base_val;
  base_val := sc.orbit[1];
  if not(IsBound(sc.transversal[i])) then
    return fail;
  fi;
  current_perm := sc.transversal[i];
  current_pos := i^current_perm;
  while (current_pos <> base_val)
  do
    current_perm := current_perm * sc.transversal[current_pos];
    current_pos := i^current_perm;
  od;
  return current_perm;
end;

_YAPB_inGroup := function(p, g)
  return (p in g);
end;

_YAPB_isGroupConj := function(p, g)
  return g^p = g;
end;

_YAPB_getOrbitPart := function(g, maxval)
  return OrbitsDomain(Group(g.generators), [1..maxval]);
end;

_YAPB_getBlockList := function(sc)
  local blocks, g, orbs, b, o;
  g := Group(sc.generators);
  orbs := Orbits(g);
  blocks := [];
  for o in orbs
  do
    b := RepresentativesMinimalBlocks(g,o);
    if b[1] <> o then
      Append(blocks, b);
    fi;
  od;

  return List(blocks, x->Orbit(g,Set(x),OnSets));
end;

_YAPB_FixedOrbits := function(group, domainsize, fixedpoints)
    return OrbitsDomain(Stabilizer(group, fixedpoints, OnTuples), [1..domainsize]);
end;

_YAPB_RepresentElement := function(group, list1, list2)
    local res;
    res := RepresentativeAction(group, list1, list2, OnTuples);
    if(res = fail) then
        return fail;
    fi;
    return ListPerm(res);
end;

_YAPB_getInfoFerret := function()
  return InfoLevel(InfoFerret);
end;

_YAPB_getInfoFerretDebug := function()
  return InfoLevel(InfoFerretDebug);
end;


_YAPB_fillRepElements := function(G, orb)
  local val, g, reps, buildorb, gens;
  reps := [];
  reps[orb[1]] := ();
  buildorb := [orb[1]];
  gens := GeneratorsOfGroup(G);
  for val in buildorb do
   for g in gens do
   if not IsBound(reps[val^g]) then
    reps[val^g] := reps[val] * g;
  Add(buildorb, val^g);
   fi;
 od;
  od;
  return reps;
end;

_YAPB_stabTime := 0;

_YAPB_getOrbitalList := function(sc, maxval)
 local G, cutoff,
        orb, orbitsG, iorb, graph, graphlist, val, p, i, orbsizes, orbpos, innerorblist, orbitsizes,
      biggestOrbit, skippedOneLargeOrbit, orbreps, stabtime;
 
  if IsGroup(sc) then
    G := sc;
  else
    G := GroupStabChain(sc);
  fi;
  
  cutoff := infinity;

 graphlist := [];
 orbitsG := Orbits(G,[1..maxval]);
 
 orbsizes := [];
 orbpos := [];
 # Efficiently store size of orbits of values
 for orb in [1..Length(orbitsG)] do
  for i in orbitsG[orb] do
   orbsizes[i] := Size(orbitsG[orb]);
   orbpos[i] := orb;
  od;
 od;

    stabtime := NanosecondsSinceEpoch();
 innerorblist := List(orbitsG, o -> Orbits(Stabilizer(G, o[1]), [1..LargestMovedPoint(G)]));
    _YAPB_stabTime := _YAPB_stabTime + (NanosecondsSinceEpoch() - stabtime);

  orbitsizes := List([1..Length(orbitsG)], 
   x -> List(innerorblist[x], y -> Size(orbitsG[x])*Size(y)));
 
 biggestOrbit := Maximum(Flat(orbitsizes));

 skippedOneLargeOrbit := false;

 for i in [1..Size(orbitsG)] do
  orb := orbitsG[i];
    orbreps := [];
  for iorb in innerorblist[i] do
   if (Size(orb) * Size(iorb) = biggestOrbit and not skippedOneLargeOrbit) then
    skippedOneLargeOrbit := true;
   else
    if (Size(orb) * Size(iorb) <= cutoff) and
    # orbit size unchanged
    not(Size(iorb) = orbsizes[iorb[1]]) and
    # orbit size only removed one point
    not(orbpos[orb[1]] = orbpos[iorb[1]] and Size(iorb) + 1 = orbsizes[iorb[1]]) and
        # don't want to take the fixed point orbit
        not(orb[1] = iorb[1] and Size(iorb) = 1)
     then
     graph := List([1..LargestMovedPoint(G)], x -> []);
          if IsEmpty(orbreps) then
            orbreps := _YAPB_fillRepElements(G, orb);
          fi;
     for val in orb do
      p := orbreps[val]; 
      graph[val] := List(iorb, x -> x^p);
     od;
     Add(graphlist, graph);
    fi;
   fi;
  od;
 od;
 return graphlist;
end;

#####
# END OF FUNCTIONS CALLED FROM C++ CODE
#####

#############################################################################
##
##
##  <#GAPDoc Label="ConStabilize">
##  <ManSection>
##  <Func Name="ConStabilize" Arg="object, action" Label="for an object and an action"/>
##  <Func Name="ConStabilize" Arg="object, n" Label="for a transformation or partial perm"/>
##
##  <Description>
##  This function creates a Constraint which can be given to <Ref Func="Solve" />.
##  It does not perform any useful actions by itself
##  <P/>
##  In the first form this represents the group which stabilises <A>object</A>
##  under <A>action</A>.
##  The currently allowed actions are <C>OnSets</C>, <C>OnSetsSets</C>, <C>OnSetsDisjointSets</C>,
##  <C>OnSetsTuples</C>, <C>OnTuples</C>, <C>OnPairs</C> and <C>OnDirectedGraph</C>.
##  <P/>
##  In the second form it represents the stabilizer of a partial perm
##  or transformation in the symmetric group on <A>n</A> points.
##
##
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
InstallMethod(ConStabilize, [IsList, IsFunction],
function(list, op)
  if op = OnSets then
    return rec(constraint := "SetStab",
               arg := list,
               max := MaximumList(list, 0));
  fi;

  if op = OnSetsDisjointSets then
    return rec(constraint := "SetSetStab",
               arg := list,
               max := MaximumList(List(list, x -> MaximumList(x, 0)),0));
  fi;

  if op = OnSetsSets then
    return rec(constraint := "OverlappingSetSetStab",
               arg := list,
               max := MaximumList(List(list, x -> MaximumList(x, 0)),0));
  fi;

  if op = OnSetsTuples then
    return rec(constraint := "SetTupleStab",
               arg := list,
               max := MaximumList(List(list, x -> MaximumList(x, 0)),0));
  fi;

  if op = OnTuples or op = OnPairs then
    return rec(constraint := "ListStab",
               arg := list,
               max := MaximumList(list, 0));
  fi;

  if op = OnTuplesTuples then
      return rec(constraint := "ListStab",
                 arg := Concatenation(list),
                 max := MaximumList(Concatenation(list), 0));
  fi;

  if op = OnTuplesSets then
     return List(list, x -> ConStabilize(x, OnSets));
  fi;

  if op = OnDirectedGraph then
    return rec(constraint := "DirectedGraph",
               arg := list,
               max := Length(list));
  fi;
  
  if op = OnEdgeColouredDirectedGraph then
      return rec(constraint := "EdgeColouredDirectedGraph",
                 arg := list,
                 max := Length(list));
  fi;

  Error("Do not understand:", op);
end);

InstallMethod(ConStabilize, [IsList, IsFunction, IsRecord],
  function(list, op, useroptions)
    local con, options;
    
    if Size(RecNames(useroptions)) = 0 then
      return ConStabilize(list, op);
    fi;
  
    if op = OnEdgeColouredDirectedGraph then
      con := rec(constraint := "EdgeColouredDirectedGraph",
                 arg := list,
                 max := Length(list));
    elif op = OnDirectedGraph then
      con := rec(constraint := "DirectedGraph",
               arg := list,
               max := Length(list));
    else
      ErrorNoReturn("No record argument allowed for " + op);
    fi;
    
     useroptions := _FerretHelperFuncs.fillUserValues(
          rec(start_path_length := 1,
              normal_path_length := 1), useroptions);
     
     con.start_path_length := useroptions.start_path_length;
     con.normal_path_length := useroptions.normal_path_length;
     
     return con;
  end);
  
  

InstallMethod(ConStabilize, [IsPosInt, IsFunction],
function(i, op)
  if op = OnPoints then
    return rec(constraint := "SetStab",
               arg := [i],
               max := i);
  fi;

  Error("Do not understand:", op);
end);

InstallMethod(ConStabilize, [IsTransformation, IsPosInt],
function(t, i)
  return ConStabilize(List([1..i], x -> [x^t]), OnDirectedGraph);
end);

InstallMethod(ConStabilize, [IsPartialPerm, IsPosInt],
function(pp, m)
  local l, i;
  l := List([1..m], x -> []);
  for i in [1..m] do
    if i^pp <> 0 then
      Add(l[i], i^pp);
    fi;
  od;
  return ConStabilize(l, OnDirectedGraph);
end);

#############################################################################
##
##
##  <#GAPDoc Label="ConInGroup">
##  <ManSection>
##  <Func Name="ConInGroup" Arg="G"/>
##
##  <Description>
##  This function creates a Constraint which can be given to <Ref Func="Solve" />.
##  It does not perform any useful actions by itself
##  <P/>
##  Represents the set of permutations in a permutation group <A>G</A>, as an
##  argument for
##  <Ref Func="Solve" />.
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
InstallMethod(ConInGroup, [IsPermGroup],
function(G)
  return ConInGroup(G, rec() );
end);

# Inefficient, StabChain, BlockStabChain, OrbStabChain, BlockOrbStabChain, UnorderedStabChain

InstallMethod(ConInGroup, [IsPermGroup, IsRecord],
function(G, useroptions)

  useroptions := _FerretHelperFuncs.fillUserValues(
          rec(orbits := "always", blocks := "never", orbitals := "never"), useroptions);

  # We special case the identity group, because it is a pain
  if IsTrivial(G) then
    return rec(constraint:="FixAllPoints", max := 1);
  else
    return rec(constraint:= "Generators_StabChain",
               arg := G,
               orbits := useroptions.orbits,
               blocks := useroptions.blocks,
               orbitals := useroptions.orbitals,
               max := LargestMovedPoint(G));
  fi;
end);


InstallGlobalFunction( OnDirectedGraph, function(graph, perm)
  local newgraph, list, i, j;
  newgraph := [];
  for i in [1..Length(graph)] do
    list := [];
    for j in [1..Length(graph[i])] do
      Add(list, (graph[i][j])^perm);
    od;
    if i^perm > Length(graph) then
      ErrorNoReturn("perm invalid on graph");
    fi;
    newgraph[i^perm] := Set(list);
  od;
  return newgraph;
end );

InstallGlobalFunction( OnEdgeColouredDirectedGraph, function(graph, perm)
  local newgraph, list, i, j;
  newgraph := [];
  for i in [1..Length(graph)] do
    list := [];
    for j in [1..Length(graph[i])] do
      Add(list, [(graph[i][j][1])^perm, graph[i][j][2]]);
    od;
    if i^perm > Length(graph) then
      ErrorNoReturn("perm invalid on graph");
    fi;
    newgraph[i^perm] := Set(list);
  od;
  return newgraph;
end );

_FERRET_DEFAULT_OPTIONS := MakeImmutable(rec(searchValueHeuristic := "RBase",
                               searchFirstBranchValueHeuristic := "RBase",
                               rbaseCellHeuristic := "smallest",
                               rbaseValueHeuristic := "smallest",
                               stats := false,
                               nodeLimit := false,
                               recreturn := false,
                               only_find_generators := true,
                               just_rbase := false
                               ));

#############################################################################
##
##
##  <#GAPDoc Label="Solve">
##  <ManSection>
##  <Func Name="Solve" Arg="constraints [,rec]"/>
##
##  <Description>
##  Finds the intersection of the list <A>Constraints</A>.
##
##  Each member of <A>constraints</A> should be a group or coset
##  generated by one of <Ref Func="ConInGroup" /> or
##  <Ref Func="ConStabilize" Label="for an object and an action"/>.
##
##  The optional second argument allows configuration options to be
##  passed in. These follow options are supported:
##
##  <List>
##  <Mark><C>rbaseCellHeuristic</C> (default "smallest")</Mark>
##  <Item>
##      The cell to be branched on. This is the option which will most
##      effect the time taken to search. the default is usually best.
##
##      Other options are: "First" (first cell), "Largest" (largest cell),
##      "smallest2" (the 2nd smallest cell), "random" (a random cell)
##      and "randomsmallest" (one of the smallest cells, chosen randomly)
##  </Item>
##  <Mark><C>rbaseValueHeuristic</C> (default "smallest")</Mark>
##  <Item>
##      Choose which cell to branch on within a cell. While this will
##      generally make a big difference to search, it is hard to predict
##      the best value, and small changes to the problem will change the
##      best heuristic. Options are the same as <C>rbaseCellHeuristic</C>.
##  </Item>
##  <Mark><C>searchValueHeuristic</C> (default <K>RBase</K>)</Mark>
##  <Item>
##      The order to branch during search. In general the best order
##      is very hard to predict. Options are "RBase", "InvRBase",
##      "Random", "Sorted" or "Nosort" (which uses the order the values
##      naturally end up in by the algorithm).
##  </Item>
##  <Mark><C>searchFirstBranchValueHeuristic</C> (default <K>RBase</K>)</Mark>
##  <Item>
##      Choose the search order used just on the left-most branches of
##      search. Allows the same options as <C>searchValueHeuristic</C>
##  </Item>
##  <Mark><C>stats</C> (default <C>false</C>)</Mark>
##  <Item>
##      Change the return value to provide a range of information about how
##      search performed (implies <C>recreturn</C>). This information will
##      change between releases.
##  </Item>
##  <Mark><C>nodeLimit</C> (default <C>false</C>) </Mark>
##  <Item>
##      Either <B>false</B>, or an integer which places a limit on the amount
##      of search which should be performed. WARNING: When this option is set
##      to an integer, Ferret will return the current best answer when the limit
##      is reached, which may be a subgroup of the actual result. To know if this
##      limit was reached, set <C>stats</C> to <B>true</B>, and check the nodes.
##  </Item>
##  <Mark><C>recreturn</C> (default <C>false</C>) </Mark>
##  <Item>
##      Return a record containing private information, rather than the group.
##  </Item>
##  <Mark><C>only_find_generators</C> (default <C>true</C>)</Mark>
##  <Item>
##      By default only find the generators of the group. If false, then
##      find all members of the group. This option is only useful for testing.
##      If 'true', then sets 'recreturn' to true.
##  </Item>
##  </List>
##
##
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
InstallGlobalFunction( Solve, function( arg )
  local maxpoint, record, l, options, useroptions,
        constraints, name, buildStabChain, retgrp;
  l := Length(arg);
  if l = 0 or l > 2 then
    Error( "usage: Solve(<C>[, <options>])");
  fi;

  constraints := Filtered(Flat(arg[1]), x -> x.max > 0);

  if Length(constraints) = 0 then
    Error("Cannot create infinite group in Solve");
  fi;

  maxpoint := Maximum(List(constraints, x -> x.max));

  # YAPB++ requires at least 2 points. We solve this in this way
  # because it makes sure we return all the various things
  # users might want (an rbase, etc).
  if maxpoint < 2 then
    Add(constraints, rec(constraint:="FixAllPoints", max := 2));
    maxpoint := 2;
  fi;

  if l = 2 then
    useroptions := arg[2];
  else
    useroptions := rec();
  fi;

  options := _FerretHelperFuncs.fillUserValues(_FERRET_DEFAULT_OPTIONS,
                                               useroptions);

  options.size := maxpoint;

  if options.stats or options.just_rbase then
    options.recreturn := true;
  fi;

_YAPB_stabTime := 0;
  record := YAPB_SOLVE(constraints, options);
  if IsBound(record.timing) then
    record.timing[1].stabInOrbFinding := _YAPB_stabTime;
fi;
  _YAPB_clearRefs();

  # We now stitch together a stabilizer chain from the return values of YAPB++
  buildStabChain := function(gens, gen_map)
    local sc, current_val, start_of_range, i;
    current_val := gen_map[1][1];
    start_of_range := 1;
    sc := EmptyStabChain(gens, ());
    for i in [2..Length(gen_map)] do
      if gen_map[i][1] <> current_val then
        InsertTrivialStabilizer(sc, current_val);
        AddGeneratorsExtendSchreierTree(sc, gens{[start_of_range..i-1]});
        current_val := gen_map[i][1];
        start_of_range := i;
      fi;
    od;
    InsertTrivialStabilizer(sc, current_val);
    AddGeneratorsExtendSchreierTree(sc, gens{[start_of_range..Length(gens)]});
    return sc;
  end;

  if options.recreturn then
    return record;
  else
    if record.generators = [()] then # just to avoid having to make code work in this case
      retgrp := Group(());
      StabChainMutable(retgrp);
    else
      retgrp := Group(record.generators);
      SetStabChainMutable(retgrp, buildStabChain(record.generators, record.generators_map));
    fi;

    Size(retgrp);
    return retgrp;
  fi;

end );
#E  files.gi  . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here

[ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ]