CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

Views: 418346
##########################################################################
# producing tikz code for drawing numerical semigroups
# The argument is: 
#* a numerical semigroup, 
#*(optional) a list whose elements are either 
###- lists of integers or 
###- one of the strings "pseudo_frobenius", "small_elements", "min_generators", "frobenius_number", "conductor", "special_gaps", "fundamental_gaps" (the default: used when no list is present)
###- a record whose fields are:
######- func -- a function name
######-(optional) argument -- an argument (that may be a function name also)
#### Warning: When a string is mispelled, an ERROR may be signaled#######

#*(optional) a positive integer -- if it is bigger than the conductor or biggest minimal generator, it indicates the number of cells - 1 to be drawn and these are drawn in a single line; otherwise, it indicates the maximum number of cells per line.
#example
#TikzCodeForNumericalSemigroup(ns,[[3,4],"pseudo_frobenius"],20);
##
# 

InstallGlobalFunction(TikzCodeForNumericalSemigroup,
function(arg)
  local  ns, options, len, allowed_options_list, o, small, c, gen, mg, flen, 
         array, str, ev, x;
  
  ns := First(arg, IsNumericalSemigroup);
  #a gobal variable is needed to EvalString...
  AuxiliaryGlobalVariableForTikzCodeForNumericalSemigroup := ns;
  
  options := ShallowCopy(First(arg, IsList));
  if options = fail then
    options := ["small_elements"];
  fi;
  len := First(arg, IsInt);
#    Error(" ");
  
  allowed_options_list := ["pseudo_frobenius", "small_elements", "min_generators", "frobenius_number", "conductor", "special_gaps", "fundamental_gaps"];  
  for o in options do
    if IsString(o) and not (o in allowed_options_list) then
      Info(InfoWarning,1,"The option ", o, " is perhaps mispelled and will be ignored\n");
           #, unless it is the name of a function, it will cause an error to be signaled.");
    fi;
  od;

  small := SmallElementsOfNumericalSemigroup(ns);
  c := ConductorOfNumericalSemigroup(ns);
  if len = fail then
    len := c;
  fi;

  gen := MinimalGeneratingSystemOfNumericalSemigroup(ns);
  mg := Maximum(gen);
  
  flen := Maximum(len,c);
  small := Union(small, [c..flen]);
  
  array := [];
  for o in options do
    if IsHomogeneousList(o) and IsInt(o[1]) then
      Add(array,o);
    elif o = "pseudo_frobenius" then
      Add(array, PseudoFrobeniusOfNumericalSemigroup(ns));
    elif o = "small_elements" then
      Add(array,small);
    elif o = "min_generators" then
      Add(array,gen);
    elif o = "frobenius_number" then
      Add(array,[c-1]);
    elif o = "conductor" then
      Add(array,[c]);
    elif o = "special_gaps" then
      Add(array, SpecialGapsOfNumericalSemigroup(ns));
    elif o = "fundamental_gaps" then
      Add(array, FundamentalGapsOfNumericalSemigroup(ns));
    elif IsRecord(o) then
#      Error("..");
      
      if IsBound(o.func) and IsFunction(EvalString(o.func)) then
        if IsBound(o.argument) then
        if IsFunction(EvalString(o.argument)) then
          str := Concatenation(o.argument,"(AuxiliaryGlobalVariableForTikzCodeForNumericalSemigroup)");
          ev := EvalString(str);
          str := Concatenation(o.func,"(",String(ev),")");
        else
          str := Concatenation(o.func,"(",o.argument,")");
        fi;
      else
        str := Concatenation(o,"(AuxiliaryGlobalVariableForTikzCodeForNumericalSemigroup)");
      fi;
      x := EvalString(str);
      if IsTable(x) then
        Append(array, x);
      elif IsList(x) then
        Add(array, x);
      elif IsInt(x) then
        Add(array,[x]);
      else
        Error("the function ", str, " should return an integer or a list of integers\n");
      fi;
    fi;
    fi;
  od;
  flen := Maximum(len,Maximum(Flat(array)));
  return IP_TikzArrayOfIntegers([0..flen],len+1,rec(highlights:=array));
end);
  
  

##########################################################################
# This function is used to produce lists of numerical semigroups with a fixed genus or Frobenius number. They are filtered and ordered according to some criteria.
#The possible fields of the record of options:
# *  set (a record whose possible fields are genus or frobenius )
# *(optional)  filter (a record whose possible fields are genus, type and/or multiplicity and/or frobenius and/or embedding_dimension)
# *(optional)  order ("genus", "type", "multiplicity", "frobenius", "embedding_dimension")
  #
  #example
  #SetOfNumericalSemigroups(rec(set:=rec(genus:=13),filter:=rec(type:= 2),order:="multiplicity"));

InstallGlobalFunction(SetOfNumericalSemigroups,
        function(opt)
  local  options, universe, aux_list, ordered_list;

  if IsRecord(opt) then
    options := opt;
  else
    Error("The argument must be a record (of options)");
  fi;

  # note that the field "set" must be present
  if IsBound(options.set.frobenius) then 
    universe := NumericalSemigroupsWithFrobeniusNumber(options.set.frobenius);
  else
    universe := NumericalSemigroupsWithGenus(options.set.genus);
  fi;

  ## filtering
  if IsBound(options.filter) then
    if IsBound(options.filter.genus) then
      universe := Filtered(universe, s -> GenusOfNumericalSemigroup(s) = options.filter.genus);
    fi;      
    if IsBound(options.filter.type) then
      universe := Filtered(universe, s -> TypeOfNumericalSemigroup(s) = options.filter.type);
    fi;      
    if IsBound(options.filter.frobenius) then
      universe := Filtered(universe, s -> FrobeniusNumberOfNumericalSemigroup(s) = options.filter.frobenius);
    fi;      
    if IsBound(options.filter.multiplicity) then
      universe := Filtered(universe, s -> MultiplicityOfNumericalSemigroup(s) = options.filter.multiplicity);
    fi;
    if IsBound(options.filter.embedding_dimension) then
      universe := Filtered(universe, s -> EmbeddingDimensionOfNumericalSemigroup(s) = options.filter.embedding_dimension);
    fi;
  fi;

  #ordering
  if IsBound(options.order) then
    if options.order = "embedding_dimension" then
      aux_list := List(universe, s-> [EmbeddingDimensionOfNumericalSemigroup(s),s]);
      ordered_list := List(Set(aux_list), l -> l[2]);
    elif options.order = "frobenius" then
      aux_list := List(universe, s-> [FrobeniusNumberOfNumericalSemigroup(s),s]);
      ordered_list := List(Set(aux_list), l -> l[2]);
    elif options.order = "pseudo_frobenius" then
      aux_list := List(universe, s-> [PseudoFrobeniusOfNumericalSemigroup(s),s]);
      ordered_list := List(Set(aux_list), l -> l[2]);
    elif options.order = "type" then
      aux_list := List(universe, s-> [TypeOfNumericalSemigroup(s),s]);
      ordered_list := List(Set(aux_list), l -> l[2]);
    elif options.order = "genus" then
      aux_list := List(universe, s-> [GenusOfNumericalSemigroup(s),s]);
      ordered_list := List(Set(aux_list), l -> l[2]);
    elif options.order = "multiplicity" then
      aux_list := List(universe, s-> [MultiplicityOfNumericalSemigroup(s),s]);
      ordered_list := List(Set(aux_list), l -> l[2]);
    else
      ordered_list := universe;
    fi;
  else
    ordered_list := universe;
  fi;
  return ordered_list;
end);

  ############################################################################
  # Produces a single image from the images of a set of numerical semigroups
  #
  # arguments
  #* a list of numerical semigroups
  #*(optional) an integer that (when present) determines the length of each line
  #*(optional) a record with fields:
  ### -(optional) splash: which (when present) consists of a record of options for the Viz Splash function 
  ### -(optional) highlights: a list to be passed to the function that produces the tikz code for each individual semigroup (whose aim is to say which elements are to be highlighted) 
  #example
# ns1 := NumericalSemigroup(3,5);;
# ns2 := NumericalSemigroup(5,7,11);;
# DrawSetOfNumericalSemigroups(ns1,rec(splash:= rec(viewer := "evince"),highlights := ["pseudo_frobenius","small_elements","min_generators"]));
#DrawSetOfNumericalSemigroups(ns1,ns2,rec(splash:= rec(viewer := "evince"),highlights := ["pseudo_frobenius","small_elements","min_generators"]));
#DrawSetOfNumericalSemigroups([ns1,ns2],rec(splash:= rec(viewer := "evince"),highlights := ["pseudo_frobenius","small_elements","min_generators"]));

InstallGlobalFunction(DrawSetOfNumericalSemigroups,
        function(arg)  
  local  set, options, mm, ns, m, line_length, tk, i;
  
  set := Filtered(arg,IsNumericalSemigroup);
  if set = [] then
    set := First(arg,s -> IsHomogeneousList(s) and IsNumericalSemigroup(s[1]));
  fi;
  
  # if  First(arg,IsNumericalSemigroup) <> fail then
  #   set := [First(arg,IsNumericalSemigroup)];
  # else 
  #   set := First(arg,s -> IsHomogeneousList(s) and IsNumericalSemigroup(s[1]));
  # fi;
  
  line_length := First(arg,IsInt);
  options := First(arg,IsRecord);
  if options = fail then
    options := rec();
  fi;
  #determining the maximum of the minimal generators and the conductors
  mm := 0;
  for ns in set do
    m := Maximum(Union(MinimalGeneratingSystemOfNumericalSemigroup(ns),[ConductorOfNumericalSemigroup(ns)]));
    mm := Maximum(m,mm);
  od;
  if line_length = fail then
    line_length := mm;
  fi;

  tk := "";
  if IsBound(options.highlights) then
    tk := Concatenation(tk,TikzCodeForNumericalSemigroup(set[1],options.highlights, line_length));
    if Length(set) > 1 then 
      for i in [2..Length(set)] do
        tk := Concatenation(tk,"\\\\\n",TikzCodeForNumericalSemigroup(set[i],options.highlights, line_length));
      od;
    fi;
  else
    tk := Concatenation(tk,TikzCodeForNumericalSemigroup(set[1], line_length));
    if Length(set) > 1 then 
      for i in [2..Length(set)] do
        tk := Concatenation(tk,"\\\\\n",TikzCodeForNumericalSemigroup(set[i], line_length));
      od;
    fi;
  fi;

  if IsBound(options.splash) then
    IP_Splash(tk,options.splash);
  else
    IP_Splash(tk);
  fi;
end);
######