コード例 #1
0
            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));
                }
            }
コード例 #2
0
                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);
                }
コード例 #3
0
            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));
            }