Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2022
688
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 21.58 KB | None | 0 0
  1. /**
  2.  * Author: Kacper Blachut
  3.  * Purpose: Applies Burnside's Lemma, Polya's Enumaration or Color Enumeration on chosen group actions
  4.  *
  5.  * Program used in "O pewnym problemie przeliczania unikalnych przeksztalcen na zbiorach skonczonych" for Malopolski Konkurs Prac Matematycznych 2022.
  6.  * Doesn't have a UI
  7.  */
  8.  
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Text;
  12.  
  13. namespace RotatingHypercubes
  14. {
  15.     class GeneralCase
  16.     {
  17.         public class Cycle
  18.         {
  19.             public IntPL Elements;
  20.  
  21.             public Cycle(IntPL newElements)
  22.             {
  23.                 Elements = newElements;
  24.             }
  25.  
  26.             public int Length()
  27.             {
  28.                 return Elements.Count;
  29.             }
  30.             public override string ToString()
  31.             {
  32.                 return Elements.ToString();
  33.             }
  34.         }
  35.         public class Permutation
  36.         {
  37.             ///An object representing a permutation
  38.            
  39.             //The permutation
  40.             public int[] Pi;
  41.  
  42.             public Permutation(int[] NewPi)
  43.             {
  44.                 if (IsPiCorrect(NewPi))
  45.                 {
  46.                     Pi = NewPi;
  47.                 }
  48.                 else
  49.                 {
  50.                     Pi = NewPi;
  51.                     Console.Write("\nPermutation is incorrect: \n" + this);
  52.  
  53.                     //Throw exception:
  54.                     Pi[0] = Pi[NewPi.Length];
  55.                 }
  56.             }
  57.  
  58.             //Checks if all the numbers in the permutation are within the range <0, length>
  59.             public bool IsPiCorrect(int[] NewPi)
  60.             {
  61.                 bool[] Temp = new bool[NewPi.Length];
  62.  
  63.                 for (int i = 0; i < NewPi.Length; i++)
  64.                 {
  65.                     if (NewPi[i] <= NewPi.Length && NewPi[i] >= 1)
  66.                     {
  67.                         if (!Temp[NewPi[i] - 1])
  68.                         {
  69.                             Temp[NewPi[i] - 1] = true;
  70.                         }
  71.                         else
  72.                         {
  73.                             return false;
  74.                         }
  75.                     }
  76.                     else
  77.                     {
  78.                         return false;
  79.                     }
  80.                 }
  81.  
  82.                 return true;
  83.             }
  84.             //Gets the lengths of all cycles inside the permutation
  85.             public int[] GetCycleLengths()
  86.             {
  87.                 IntPL CycleLengths = new IntPL();
  88.                 bool[] IndexesChecked = new bool[Pi.Length];
  89.  
  90.                 for (int CurrentIndex = 1; CurrentIndex <= Pi.Length; CurrentIndex++)
  91.                 {
  92.                     //Checks if the current index has already been in a previous cycle
  93.                     if (!IndexesChecked[CurrentIndex - 1])
  94.                     {
  95.                         int RunningIndex = CurrentIndex;
  96.                         int RunningLength = 1;
  97.  
  98.                         //Console.Write(RunningIndex);
  99.  
  100.                         //Follows the cycle
  101.                         while (Pi[RunningIndex - 1] != CurrentIndex)
  102.                         {
  103.                             IndexesChecked[RunningIndex - 1] = true;
  104.                             RunningIndex = Pi[RunningIndex - 1];
  105.                             RunningLength++;
  106.  
  107.                             //Console.Write(", " + RunningIndex);
  108.                         }
  109.                         IndexesChecked[RunningIndex - 1] = true;
  110.  
  111.                         //Console.Write(" - " + RunningLength);
  112.                         //Console.WriteLine();
  113.  
  114.                         CycleLengths.Add(RunningLength);
  115.                     }
  116.  
  117.                     IndexesChecked[CurrentIndex - 1] = true;
  118.                 }
  119.  
  120.                 return CycleLengths.ToArray();
  121.             }
  122.             //Converts the permutation into an array of cycles
  123.             public Cycle[] ConvertToCycles()
  124.             {
  125.                 List<Cycle> Cycles = new List<Cycle>();
  126.                 bool[] IndexesChecked = new bool[Pi.Length];
  127.  
  128.                 for (int CurrentIndex = 1; CurrentIndex <= Pi.Length; CurrentIndex++)
  129.                 {
  130.                     //Checks if the current index has already been in a previous cycle
  131.                     if (!IndexesChecked[CurrentIndex - 1])
  132.                     {
  133.                         int RunningIndex = CurrentIndex;
  134.                         IntPL RunningCycle = new IntPL();
  135.                         RunningCycle.Add(RunningIndex);
  136.  
  137.                         //Console.Write(RunningIndex);
  138.  
  139.                         //Follows the cycle
  140.                         while (Pi[RunningIndex - 1] != CurrentIndex)
  141.                         {
  142.                             IndexesChecked[RunningIndex - 1] = true;
  143.                             RunningIndex = Pi[RunningIndex - 1];
  144.                             RunningCycle.Add(RunningIndex);
  145.  
  146.                             //Console.Write(", " + RunningIndex);
  147.                         }
  148.                         IndexesChecked[RunningIndex - 1] = true;
  149.  
  150.                         //Console.Write(" - " + RunningLength);
  151.                         //Console.WriteLine();
  152.  
  153.                         Cycles.Add(new Cycle(RunningCycle));
  154.                     }
  155.  
  156.                     IndexesChecked[CurrentIndex - 1] = true;
  157.                 }
  158.  
  159.                 return Cycles.ToArray();
  160.             }
  161.  
  162.             public override string ToString()
  163.             {
  164.                 return ArrayToString(Pi);
  165.             }
  166.         }
  167.         public class IntPL : List<int>
  168.         {
  169.             public override string ToString()
  170.             {
  171.                 return "(" + String.Join(", ", this) + ")";
  172.             }
  173.         }
  174.  
  175.         public class PermGroup
  176.         {
  177.             ///An object representing a permutation group
  178.             ///Does not check for validity in permutations
  179.  
  180.             //The set of permutations
  181.             public Permutation[] Symmetries;
  182.  
  183.             public PermGroup(Permutation[] newSymmetries)
  184.             {
  185.                 if(IsPermutationLengthEqual(newSymmetries))
  186.                 {
  187.                     Symmetries = newSymmetries;
  188.                 }
  189.                 else
  190.                 {
  191.                     Symmetries = newSymmetries;
  192.                     Console.Write("\nPermutation lengths in this PermutationGroup are not equal: \n" + this);
  193.  
  194.                     //Throw exception:
  195.                     Symmetries[0] = Symmetries[newSymmetries.Length];
  196.                 }
  197.             }
  198.  
  199.             //Checks if all the permutation lengths are equal
  200.             public bool IsPermutationLengthEqual(Permutation[] newSymmetries)
  201.             {
  202.                 if(newSymmetries.Length != 0)
  203.                 {
  204.                     int FirstLength = newSymmetries[0].Pi.Length;
  205.  
  206.                     for(int i = 0; i < newSymmetries.Length; i++)
  207.                     {
  208.                         if(newSymmetries[i].Pi.Length != FirstLength)
  209.                         {
  210.                             return false;
  211.                         }
  212.                     }
  213.  
  214.                     return true;
  215.                 }
  216.                 else
  217.                 {
  218.                     return true;
  219.                 }
  220.             }
  221.             public override string ToString()
  222.             {
  223.                 return ArrayToString(Symmetries);
  224.             }
  225.         }
  226.         public class CLSGroup
  227.         {
  228.             ///Cycle Length Short-notation Group
  229.             ///An object representing a group as a set of lengths of cycles in the symmetries on some set
  230.             ///Can't do operations on symmetries
  231.             ///But is really helpful in formulas like: Burnside's Lemma or Polya's Enumaration Theorem
  232.  
  233.             //The possible cycle lengths that a permutation can have in this group
  234.             public IntPL[] CycleLengths;
  235.             //The x-th number is the amount of permutations that have cycle lengths equal to the x-th term in CycleLengths
  236.             public int[] NumOfPermsOfType;
  237.  
  238.             public CLSGroup(IntPL[] newCycleLengths, int[] newNumOfPermsOfType)
  239.             {
  240.                 if(IsPermutationLengthEqual(newCycleLengths))
  241.                 {
  242.                     CycleLengths = newCycleLengths;
  243.  
  244.                     if(IsNumOfPermsCorrect(newCycleLengths, newNumOfPermsOfType))
  245.                     {
  246.                         NumOfPermsOfType = newNumOfPermsOfType;
  247.                     }
  248.                     else
  249.                     {
  250.                         NumOfPermsOfType = newNumOfPermsOfType;
  251.                         Console.WriteLine("The number of permutations that has certain cycle lengths is wrongly defined: \n" + this);
  252.  
  253.                         //Throw exception
  254.                         NumOfPermsOfType[0] = NumOfPermsOfType[NumOfPermsOfType.Length];
  255.                     }
  256.                 }
  257.                 else
  258.                 {
  259.                     CycleLengths = newCycleLengths;
  260.                     Console.WriteLine("The lengths of permutation in this CLSGroup are not equal: \n" + this);
  261.  
  262.                     //Throw exception
  263.                     CycleLengths[0] = CycleLengths[CycleLengths.Length];
  264.                 }
  265.             }
  266.  
  267.             //Checks if the sum of cycle lengths in each permutation is equal
  268.             public bool IsPermutationLengthEqual(IntPL[] newCycleLengths)
  269.             {
  270.                 if(newCycleLengths.Length != 0)
  271.                 {
  272.                     int FirstPermutationLength = 0;
  273.                     foreach(int CycleLength in newCycleLengths[0])
  274.                     {
  275.                         FirstPermutationLength += CycleLength;
  276.                     }
  277.  
  278.                     for(int i = 0; i < newCycleLengths.Length; i++)
  279.                     {
  280.                         int RunningLength = 0;
  281.                         foreach(int CycleLength in newCycleLengths[i])
  282.                         {
  283.                             RunningLength += CycleLength;
  284.                         }
  285.  
  286.                         if(RunningLength != FirstPermutationLength)
  287.                         {
  288.                             return false;
  289.                         }
  290.                     }
  291.  
  292.                     return true;
  293.                 }
  294.                 else
  295.                 {
  296.                     return true;
  297.                 }
  298.             }
  299.             //Checks if the lengths of newCycleLengths and newNumOfPermsOfType are equal and if all the elements of newNumOfPermsOfType are greater than 0
  300.             public bool IsNumOfPermsCorrect(IntPL[] newCycleLengths, int[] newNumOfPermsOfType)
  301.             {
  302.                 if (newNumOfPermsOfType.Length == newCycleLengths.Length)
  303.                 {
  304.                     for(int i = 0; i < newNumOfPermsOfType.Length; i++)
  305.                     {
  306.                         if(newNumOfPermsOfType[i] <= 0)
  307.                         {
  308.                             return false;
  309.                         }
  310.                     }
  311.                     return true;
  312.                 }
  313.                 else
  314.                 {
  315.                     return false;
  316.                 }
  317.             }
  318.             //Counts the number of symmetries in the group
  319.             public int NumOfSymmetries()
  320.             {
  321.                 int Total = 0;
  322.  
  323.                 for(int i = 0; i < NumOfPermsOfType.Length; i++)
  324.                 {
  325.                     Total += NumOfPermsOfType[i];
  326.                 }
  327.  
  328.                 return Total;
  329.             }
  330.             //Calculates the size of the set the group is acting on
  331.             public int GetSetSize()
  332.             {
  333.                 if(CycleLengths.Length > 0 && CycleLengths[0].Count > 0)
  334.                 {
  335.                     int LengthOfPermutation = 0;
  336.  
  337.                     foreach(int CycleLength in CycleLengths[0])
  338.                     {
  339.                         LengthOfPermutation += CycleLength;
  340.                     }
  341.  
  342.                     return LengthOfPermutation;
  343.                 }
  344.  
  345.                 return 0;
  346.             }
  347.  
  348.             public override string ToString()
  349.             {
  350.                 return ArrayToString(CycleLengths) + "\n" + ArrayToString(NumOfPermsOfType);
  351.             }
  352.         }
  353.  
  354.         static public void PrintArray(Array array)
  355.         {
  356.             Console.Write("{");
  357.             for(int i = 0; i < array.Length - 1; i++)
  358.             {
  359.                 Console.Write(array.GetValue(i) + "; ");
  360.             }
  361.             Console.Write(array.GetValue(array.Length - 1) + "}");
  362.         }
  363.         static public string ArrayToString(Array array)
  364.         {
  365.             string Output = "(";
  366.             for (int i = 0; i < array.Length - 1; i++)
  367.             {
  368.                 Output = Output.Insert(Output.Length, array.GetValue(i) + ", ");
  369.             }
  370.             Output =  Output.Insert(Output.Length, array.GetValue(array.Length - 1) + ")");
  371.  
  372.             return Output;
  373.         }
  374.  
  375.  
  376.         public static int BurnsidesLemma(CLSGroup Group, int NumOfColors)
  377.         {
  378.             int Total = 0;
  379.  
  380.             for(int i = 0; i < Group.NumOfPermsOfType.Length; i++)
  381.             {
  382.                 Total += Group.NumOfPermsOfType[i] * (int) MathF.Pow(NumOfColors, Group.CycleLengths[i].Count);
  383.             }
  384.  
  385.             Total /= Group.NumOfSymmetries();
  386.  
  387.             return Total;
  388.         }
  389.         public static int BurnsidesLemma(PermGroup Group, int NumOfColors)
  390.         {
  391.             int Total = 0;
  392.  
  393.             for(int i = 0; i < Group.Symmetries.Length; i++)
  394.             {
  395.                 Total += (int) MathF.Pow(NumOfColors, Group.Symmetries[i].ConvertToCycles().Length);
  396.             }
  397.  
  398.             Total /= Group.Symmetries.Length;
  399.  
  400.             return Total;
  401.         }
  402.         public static int PolyaEnumaration(CLSGroup Group, int[] ColorWeights)
  403.         {
  404.             int Total = 0;
  405.  
  406.             for(int SymmetryIndex = 0; SymmetryIndex < Group.CycleLengths.Length; SymmetryIndex++)
  407.             {
  408.                 int SymmetrySubTotal = Group.NumOfPermsOfType[SymmetryIndex];
  409.                
  410.                 for(int CycleIndex = 0; CycleIndex < Group.CycleLengths[SymmetryIndex].Count; CycleIndex++)
  411.                 {
  412.                     int CycleSubTotal = 0;
  413.  
  414.                     for(int ColorIndex = 0; ColorIndex < ColorWeights.Length; ColorIndex++)
  415.                     {
  416.                         CycleSubTotal += (int)MathF.Pow(ColorWeights[ColorIndex], Group.CycleLengths[SymmetryIndex].ToArray()[CycleIndex]);
  417.                     }
  418.  
  419.                     SymmetrySubTotal *= CycleSubTotal;
  420.                 }
  421.  
  422.                 Total += SymmetrySubTotal;
  423.             }
  424.  
  425.             Total /= Group.NumOfSymmetries();
  426.  
  427.             return Total;
  428.         }
  429.         public static int ColorEnumaration(CLSGroup SetGroup, CLSGroup ColorGroup)
  430.         {
  431.             long Total = 0;
  432.  
  433.             for(int ColorSymmetryIndex = 0; ColorSymmetryIndex < ColorGroup.CycleLengths.Length; ColorSymmetryIndex++)
  434.             {
  435.                 int SetSymmetrySubTotal = 0;
  436.  
  437.                 int[] TempColorSymmetryCycleLengths = ColorGroup.CycleLengths[ColorSymmetryIndex].ToArray();
  438.  
  439.                 for(int SetSymmetryIndex = 0; SetSymmetryIndex < SetGroup.CycleLengths.Length; SetSymmetryIndex++)
  440.                 {
  441.                     int SetCycleSubTotal = 1;
  442.  
  443.                     int[] TempSetSymmetryCycleLengths = SetGroup.CycleLengths[SetSymmetryIndex].ToArray();
  444.  
  445.                     for(int SetCycleIndex = 0; SetCycleIndex < TempSetSymmetryCycleLengths.Length; SetCycleIndex++)
  446.                     {
  447.                         int ColorCycleSubTotal = 0;
  448.  
  449.                         for(int ColorCycleIndex = 0; ColorCycleIndex < TempColorSymmetryCycleLengths.Length; ColorCycleIndex++)
  450.                         {
  451.                             if(TempSetSymmetryCycleLengths[SetCycleIndex] % TempColorSymmetryCycleLengths[ColorCycleIndex] == 0)
  452.                             {
  453.                                 ColorCycleSubTotal += TempColorSymmetryCycleLengths[ColorCycleIndex];
  454.                             }
  455.                         }
  456.  
  457.                         SetCycleSubTotal *= ColorCycleSubTotal;
  458.                     }
  459.  
  460.                     SetSymmetrySubTotal += SetCycleSubTotal * SetGroup.NumOfPermsOfType[SetSymmetryIndex];
  461.                 }
  462.  
  463.                 Total += SetSymmetrySubTotal * ColorGroup.NumOfPermsOfType[ColorSymmetryIndex];
  464.             }
  465.  
  466.             Total /= SetGroup.NumOfSymmetries() * ColorGroup.NumOfSymmetries();
  467.  
  468.             return (int) Total;
  469.         }
  470.  
  471.         public class CLSBasics
  472.         {
  473.             //Cycle groups - vertices of an n-gon - rotational symmetry
  474.             public CLSGroup C3 = new CLSGroup(new IntPL[] {
  475.                 new IntPL { 1, 1, 1 },
  476.                 new IntPL { 3 } }, new int[] { 1, 2 });
  477.             public CLSGroup C4 = new CLSGroup(new IntPL[] {
  478.                 new IntPL { 1, 1, 1, 1 },
  479.                 new IntPL { 2, 2 },
  480.                 new IntPL { 4 } }, new int[] { 1, 1, 2 });
  481.  
  482.             //Dihedral groups - vertices of an n-gon - rotational and mirror symmetry
  483.             public CLSGroup D4 = new CLSGroup(new IntPL[] {
  484.                 new IntPL { 1, 1, 1, 1 },
  485.                 new IntPL { 2, 1, 1 },
  486.                 new IntPL { 2, 2 },
  487.                 new IntPL { 4 } }, new int[] { 1, 2, 3, 2 });
  488.  
  489.             //Symmetric groups - disjoint set of points - all symmetries
  490.             public CLSGroup S2 = new CLSGroup(new IntPL[] {
  491.                 new IntPL { 1, 1 },
  492.                 new IntPL { 2 } }, new int[] { 1, 1 });
  493.             public CLSGroup S3 = new CLSGroup(new IntPL[] {
  494.                 new IntPL { 1, 1, 1 },
  495.                 new IntPL { 1, 2},
  496.                 new IntPL { 3 } }, new int[] { 1, 3, 2 });
  497.             public CLSGroup S4 = new CLSGroup(new IntPL[] {
  498.                 new IntPL { 1, 1, 1, 1 },
  499.                 new IntPL { 2, 1, 1 },
  500.                 new IntPL { 2, 2 },
  501.                 new IntPL { 3, 1 },
  502.                 new IntPL { 4 } }, new int[] { 1, 6, 3, 8, 6 });
  503.             public CLSGroup S8 = new CLSGroup(new IntPL[] {
  504.                 new IntPL { 1, 1, 1, 1, 1, 1, 1, 1 },
  505.                 new IntPL { 2, 1, 1, 1, 1, 1, 1 },
  506.                 new IntPL { 2, 2, 1, 1, 1, 1 },
  507.                 new IntPL { 2, 2, 2, 1, 1 },
  508.                 new IntPL { 2, 2, 2, 2 },
  509.                 new IntPL { 3, 1, 1, 1, 1, 1 },
  510.                 new IntPL { 3, 2, 1, 1, 1 },
  511.                 new IntPL { 3, 2, 2, 1 },
  512.                 new IntPL { 3, 3, 1, 1 },
  513.                 new IntPL { 3, 3, 2 },
  514.                 new IntPL { 4, 1, 1, 1, 1 },
  515.                 new IntPL { 4, 2, 1, 1 },
  516.                 new IntPL { 4, 2, 2 },
  517.                 new IntPL { 4, 3, 1 },
  518.                 new IntPL { 4, 4 },
  519.                 new IntPL { 5, 1, 1, 1 },
  520.                 new IntPL { 5, 2, 1 },
  521.                 new IntPL { 5, 3 },
  522.                 new IntPL { 6, 1, 1 },
  523.                 new IntPL { 6, 2 },
  524.                 new IntPL { 7, 1 },
  525.                 new IntPL { 8 } }, new int[] { 1, 28, 210, 420, 105, 112, 1120, 1680, 1120, 1120, 420, 2520, 1260, 3360, 1260, 1344, 4032, 2688, 3360, 3360, 5760, 5040 });
  526.  
  527.             //Octahedral symmetry - vertices of a cube - rotational and mirror symmetry
  528.             public CLSGroup O = new CLSGroup(new IntPL[] {
  529.                 new IntPL { 1, 1, 1, 1, 1, 1, 1, 1 },
  530.                 new IntPL { 2, 2, 1, 1, 1, 1 },
  531.                 new IntPL { 2, 2, 2, 2 },
  532.                 new IntPL { 3, 3, 1, 1 },
  533.                 new IntPL { 4, 4 },
  534.                 new IntPL { 6, 2 } }, new int[] { 1, 6, 13, 8, 12, 8 });
  535.             //Klein four-group - vertices of a rectangle - rotational and mirror symmetry
  536.             public CLSGroup V = new CLSGroup(new IntPL[] {
  537.                 new IntPL { 1, 1, 1, 1 },
  538.                 new IntPL { 2, 2 } }, new int[] { 1, 3 });
  539.             //Quaternion group - vertices of a cube - custom symmetry
  540.             public CLSGroup Q = new CLSGroup(new IntPL[] {
  541.                 new IntPL { 1, 1, 1, 1, 1, 1, 1, 1 },
  542.                 new IntPL { 2, 2, 2, 2 },
  543.                 new IntPL { 4, 4 } }, new int[] { 1, 1, 6 });
  544.  
  545.  
  546.             public CLSGroup Multiply(CLSGroup Group, int Multiple)
  547.             {
  548.                 IntPL[] newCycleLengths = new IntPL[Group.CycleLengths.Length];
  549.  
  550.                 for(int SymmetryIndex = 0; SymmetryIndex < Group.CycleLengths.Length; SymmetryIndex++)
  551.                 {
  552.                     int[] TempCycles = Group.CycleLengths[SymmetryIndex].ToArray();
  553.                     newCycleLengths[SymmetryIndex] = new IntPL();
  554.  
  555.                     for(int CycleIndex = 0; CycleIndex < Group.CycleLengths[SymmetryIndex].Count; CycleIndex++)
  556.                     {
  557.                         for(int M = 0; M < Multiple; M++)
  558.                         {
  559.                             newCycleLengths[SymmetryIndex].Add(TempCycles[CycleIndex]);
  560.                         }
  561.                     }
  562.                 }
  563.  
  564.                 return new CLSGroup(newCycleLengths, Group.NumOfPermsOfType);
  565.             }
  566.         }
  567.         public class PermBasics
  568.         {
  569.             public PermGroup C4 = new PermGroup(new Permutation[] {
  570.                 new Permutation(new int[] {1, 2, 3, 4}),
  571.                 new Permutation(new int[] {4, 1, 2, 3}),
  572.                 new Permutation(new int[] {3, 4, 1, 2}),
  573.                 new Permutation(new int[] {2, 3, 4, 1}) });
  574.         }
  575.  
  576.         static void Main(string[] args)
  577.         {
  578.             CLSBasics TC = new CLSBasics();
  579.             PermBasics TP = new PermBasics();
  580.             //Console.WriteLine(BurnsidesLemma(TP.C4, 10));
  581.             Console.WriteLine(ColorEnumaration(TC.O, TC.S8));
  582.         }
  583.     }
  584. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement