public static void VerifyReverse() { for (int caseIdx = 0; caseIdx < 100; caseIdx++) { CubeAction a = CubeAction.Random(Utils.GlobalRandom.Next(1, 20)); CubeAction ra = a.Reverse(); CubeAction id = new CubeAction(); CubeAction ara = a.Mul(ra); CubeAction raa = ra.Mul(a); Utils.DebugAssert(id.Equals(ara)); Utils.DebugAssert(id.Equals(raa)); } }
private CubeAction DetermineBelongingCoset(CubeAction e) { var eState = new BlockSet(ToStablize); e.Act(eState.State); if (!OrbitToCoset.ContainsKey(eState)) { return(null); } var cosetRepresentative = OrbitToCoset[eState]; if (Utils.ShouldVerify()) { { var cosetReprState = new BlockSet(ToStablize); cosetRepresentative.Act(cosetReprState.State); Utils.DebugAssert(cosetReprState.Equals(eState)); } { // States in orbit 1-to-1 maps to each *left* coset (gH). I.e. // iff. e^(-1) * cosetRepresentative stablizes the BlockSet being // observed. This deduces that, group actions in same *left* // coset, always act the BlockSet being observed to the same state. var reCosetRep = e.Reverse().Mul(cosetRepresentative); Utils.DebugAssert(Stablized.IsStablizedBy(reCosetRep)); } { // Iff. e * cosetRepresentative^(-1) stablizes the BlockSet being // observed. This is the condition for *right* coset. It is not what // we need here, and group actions in same *right* coset, may act the // BlockSet being observed to different states. var eRCosetRep = e.Mul(cosetRepresentative.Reverse()); // Utils.DebugAssert(observed.IsStablizedBy(eRCosetRep)); // Doesn't hold } } return(cosetRepresentative); }
public CubeAction FilterGeneratorIncrementally(CubeAction newGenerator) { if (AcceptedGeneratorCount >= GeneratorCountLimit) { Utils.DebugAssert(AcceptedGeneratorCount == GeneratorCountLimit); if (!Utils.ShouldVerify()) { // To verify if generator limit reached, we won't be able to // add more generators return(null); } } var pair = GetActionPair(newGenerator); if (pair.Item1 < 0) { if (Utils.ShouldVerify()) { Utils.DebugAssert(newGenerator.Equals(new CubeAction())); } return(null); } if (pair.Item1 <= StablizedIdx) { // This means the newGenerator didn't stablize the required cube blocks throw new ArgumentException(); } CubeAction replacedGenerator; var existingGenerator = ActionGrid[pair.Item1, pair.Item2]; if (null == existingGenerator) { Utils.DebugAssert(null == ActionGrid[pair.Item2, pair.Item1]); var cyclePath = DetectCycle( pair.Item1, pair.Item1, pair.Item2, new List <Tuple <int, int> >() { new Tuple <int, int>(pair.Item1, pair.Item2) }); if (null == cyclePath) { // Note: g's ActionPair is (i, j) doesn't means g^(-1) ActionPair is (j, i). // We store g^(-1) here just for convenience. But g^(-1) must map j to i. ActionGrid[pair.Item1, pair.Item2] = newGenerator; ActionGrid[pair.Item2, pair.Item1] = newGenerator.Reverse(); Utils.DebugAssert(AcceptedGeneratorCount < GeneratorCountLimit); AcceptedGeneratorCount++; return(newGenerator); } else { // // Temporarily put the newGenerator in. We will remove another generator // to break the cycle. // ActionGrid[pair.Item1, pair.Item2] = newGenerator; ActionGrid[pair.Item2, pair.Item1] = newGenerator.Reverse(); cyclePath = RearrangeCycleFromSmallest(cyclePath); replacedGenerator = CalculateCyclePathProduct(cyclePath); ActionGrid[cyclePath[0].Item1, cyclePath[0].Item2] = null; ActionGrid[cyclePath[0].Item2, cyclePath[0].Item1] = null; if (Utils.ShouldVerify()) { var replacedPair = GetActionPair(replacedGenerator); if (replacedPair.Item1 >= 0) { // This ensures the recursive call will end Utils.DebugAssert(replacedPair.Item1 > cyclePath[0].Item1); } } } } else { var reversedExistingGenerator = ActionGrid[pair.Item2, pair.Item1]; if (Utils.ShouldVerify()) { Utils.DebugAssert(reversedExistingGenerator.Equals(existingGenerator.Reverse())); } replacedGenerator = reversedExistingGenerator.Mul(newGenerator); if (Utils.ShouldVerify()) { var replacedPair = GetActionPair(replacedGenerator); if (replacedPair.Item1 >= 0) { // This ensures the recursive call will end Utils.DebugAssert(replacedPair.Item1 > pair.Item1); } } } JumpCount++; return(FilterGeneratorIncrementally(replacedGenerator)); }