예제 #1
0
        public static PuzzleStateAndGenerator ApplyOrientation(CubePuzzle puzzle, CubeMove[] randomOrientation,
                                                               PuzzleStateAndGenerator psag, bool discardRedundantMoves)
        {
            if (randomOrientation.Length == 0)
            {
                return(psag);
            }

            // Append reorientation to scramble.
            try
            {
                var ab = new AlgorithmBuilder(MergingMode.NoMerging, puzzle.GetSolvedState());
                ab.AppendAlgorithm(psag.Generator);
                foreach (var cm in randomOrientation)
                {
                    ab.AppendMove(cm.ToString());
                }

                psag = ab.GetStateAndGenerator();
                return(psag);
            }
            catch (InvalidMoveException e)
            {
                azzert(false, e.Message);
                return(null);
            }
        }
예제 #2
0
        public override PuzzleStateAndGenerator GenerateRandomMoves(Random r)
        {
            var scramble = _threePhaseSearcher.RandomState(r);
            var ab       = new AlgorithmBuilder(MergingMode.CanonicalizeMoves, GetSolvedState());

            try
            {
                ab.AppendAlgorithm(scramble);
            }
            catch (InvalidMoveException e)
            {
                azzert(false, e.Message); //, new InvalidScrambleException(scramble, e));
            }
            return(ab.GetStateAndGenerator());
        }
예제 #3
0
        public override PuzzleStateAndGenerator GenerateRandomMoves(Random r)
        {
            var state    = _twoSolver.RandomState(r);
            var scramble = _twoSolver.GenerateExactly(state, TwoByTwoMinScrambleLength);

            var ab = new AlgorithmBuilder(MergingMode.CanonicalizeMoves, GetSolvedState());

            try
            {
                ab.AppendAlgorithm(scramble);
            }
            catch (InvalidMoveException e)
            {
                azzert(false, e.Message, new InvalidScrambleException(scramble, e));
            }
            return(ab.GetStateAndGenerator());
        }
예제 #4
0
        public ClusterSettingsViewModel(
            MultiAlignAnalysis analysis,
            ObservableCollection <DatasetInformationViewModel> datasets,
            IClusterViewFactory clusterViewFactory = null,
            IProgress <int> progressReporter       = null)
        {
            this.progress           = progressReporter ?? new Progress <int>();
            this.analysis           = analysis;
            this.Datasets           = datasets;
            this.options            = analysis.Options;
            this.builder            = new AlgorithmBuilder();
            this.clusterViewFactory = clusterViewFactory ?? new ClusterViewFactory(analysis.DataProviders);

            // When dataset state changes, update can executes.
            this.MessengerInstance.Register <PropertyChangedMessage <DatasetInformationViewModel.DatasetStates> >(this, args =>
            {
                if (args.Sender is DatasetInformationViewModel && args.PropertyName == "DatasetState")
                {
                    ThreadSafeDispatcher.Invoke(() => this.ClusterFeaturesCommand.RaiseCanExecuteChanged());
                    ThreadSafeDispatcher.Invoke(() => this.DisplayClustersCommand.RaiseCanExecuteChanged());
                }
            });

            this.ClusterFeaturesCommand = new RelayCommand(this.AsyncClusterFeatures, () => this.Datasets.Any(ds => ds.FeaturesFound));
            this.DisplayClustersCommand = new RelayCommand(
                async() => await this.DisplayFeatures(),
                () => this.Datasets.Any(ds => ds.IsClustered));

            this.DistanceMetrics = new ObservableCollection <DistanceMetric>();
            Enum.GetValues(typeof(DistanceMetric)).Cast <DistanceMetric>().ToList().ForEach(x => this.DistanceMetrics.Add(x));
            this.CentroidRepresentations = new ObservableCollection <ClusterCentroidRepresentation>
            {
                ClusterCentroidRepresentation.Mean,
                ClusterCentroidRepresentation.Median
            };

            this.ClusteringMethods = new ObservableCollection <LcmsFeatureClusteringAlgorithmType>();
            Enum.GetValues(typeof(LcmsFeatureClusteringAlgorithmType)).Cast <LcmsFeatureClusteringAlgorithmType>().ToList().ForEach(x => this.ClusteringMethods.Add(x));

            this.PostProcessingComparisonType = new ObservableCollection <ClusterPostProcessingOptions.ClusterComparisonType>(
                Enum.GetValues(typeof(ClusterPostProcessingOptions.ClusterComparisonType)).Cast <ClusterPostProcessingOptions.ClusterComparisonType>());
        }
예제 #5
0
        public PuzzleStateAndGenerator GenerateRandomMoves(Random r, string firstAxisRestriction,
                                                           string lastAxisRestriction)
        {
            var randomState = Tools.RandomCube(r);
            var scramble    =
                _twoPhaseSearcher.Solution(randomState, ThreeByThreeMaxScrambleLength, ThreeByThreeTimeout,
                                           ThreeByThreeTimemin, Search.INVERSE_SOLUTION, firstAxisRestriction, lastAxisRestriction).Trim();

            var ab = new AlgorithmBuilder(MergingMode.CanonicalizeMoves, GetSolvedState());

            try
            {
                ab.AppendAlgorithm(scramble);
            }
            catch (InvalidMoveException e)
            {
                azzert(false, e.Message); //, new InvalidScrambleException(scramble, e));
            }
            return(ab.GetStateAndGenerator());
        }
        public static PuzzleStateAndGenerator ApplyOrientation(CubePuzzle puzzle, CubeMove[] randomOrientation,
                                                               PuzzleStateAndGenerator psag, bool discardRedundantMoves)
        {
            if (randomOrientation.Length == 0)
            {
                return(psag);
            }

            // Append reorientation to scramble.
            try
            {
                var ab = new AlgorithmBuilder(MergingMode.NoMerging, puzzle.GetSolvedState());
                ab.AppendAlgorithm(psag.Generator);
                // Check if our reorientation is going to cancel with the last
                // turn of our scramble. If it does, then we just discard
                // that last turn of our scramble. This ensures we have a scramble
                // with no redundant turns, and I can't see how it could hurt the
                // quality of our scrambles to do this.
                var firstReorientMove = randomOrientation[0].ToString();
                while (ab.IsRedundant(firstReorientMove))
                {
                    //azzert(discardRedundantMoves);
                    var im = ab.FindBestIndexForMove(firstReorientMove, MergingMode.CanonicalizeMoves);
                    ab.PopMove(im.Index);
                }
                foreach (var cm in randomOrientation)
                {
                    ab.AppendMove(cm.ToString());
                }

                psag = ab.GetStateAndGenerator();
                return(psag);
            }
            catch (InvalidMoveException e)
            {
                azzert(false, e.Message);
                return(null);
            }
        }
예제 #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AlignmentSettingsViewModel"/> class.
        /// </summary>
        /// <param name="analysis">The analysis information to run alignment on.</param>
        /// <param name="datasets">List of all potential datasets to run alignment on.</param>
        /// <param name="alignmentWindowFactory">
        /// Factory for creating windows related to alignment (such as alignment plot windows).
        /// </param>
        public AlignmentSettingsViewModel(MultiAlignAnalysis analysis,
                                          ObservableCollection <DatasetInformationViewModel> datasets,
                                          IAlignmentWindowFactory alignmentWindowFactory = null)
        {
            this.analysis = analysis;
            this.Datasets = datasets;
            if (analysis.MetaData.BaselineDataset != null)
            {
                // Don't set baseline if there are no files to choose from yet
                this.selectedBaseline = datasets.First(x => x.Name == analysis.MetaData.BaselineDataset.DatasetName);
            }

            this.alignmentWindowFactory = alignmentWindowFactory ?? new AlignmentViewFactory();
            this.aligner             = new LCMSFeatureAligner();
            this.builder             = new AlgorithmBuilder();
            this.CalibrationOptions  = new ObservableCollection <LcmsWarpAlignmentType>(Enum.GetValues(typeof(LcmsWarpAlignmentType)).Cast <LcmsWarpAlignmentType>());
            this.AlignmentAlgorithms = new ObservableCollection <FeatureAlignmentType>(
                Enum.GetValues(typeof(FeatureAlignmentType)).Cast <FeatureAlignmentType>());
            this.alignmentInformation = new List <AlignmentData>();

            this.DatabaseSelectionViewModel = DatabaseSelectionViewModel.Instance;

            // When dataset is selected/unselected, update CanExecutes for alignment and plotting commands.
            this.MessengerInstance.Register <PropertyChangedMessage <bool> >(
                this,
                args =>
            {
                if (args.Sender is DatasetInformationViewModel && args.PropertyName == "IsSelected")
                {
                    ThreadSafeDispatcher.Invoke(() => this.AlignCommand.RaiseCanExecuteChanged());
                    ThreadSafeDispatcher.Invoke(() => this.DisplayAlignmentCommand.RaiseCanExecuteChanged());
                    ThreadSafeDispatcher.Invoke(() => this.SaveAlignmentPlotsCommand.RaiseCanExecuteChanged());
                }
            });

            // When dataset state changes, update CanExecutes for alignment and plotting commands.
            this.MessengerInstance.Register <PropertyChangedMessage <DatasetInformationViewModel.DatasetStates> >(
                this,
                args =>
            {
                if (args.Sender is DatasetInformationViewModel && args.PropertyName == "DatasetState")
                {
                    ThreadSafeDispatcher.Invoke(() => this.AlignCommand.RaiseCanExecuteChanged());
                    ThreadSafeDispatcher.Invoke(() => this.DisplayAlignmentCommand.RaiseCanExecuteChanged());
                    ThreadSafeDispatcher.Invoke(() => this.SaveAlignmentPlotsCommand.RaiseCanExecuteChanged());
                }
            });

            // When database server is selected, update CanExecute for the alignment command.
            this.MessengerInstance.Register <PropertyChangedMessage <DmsDatabaseServerViewModel> >(
                this,
                args =>
            {
                if (args.Sender is DatabaseSelectionViewModel && args.PropertyName == "SelectedDatabase")
                {
                    ThreadSafeDispatcher.Invoke(() => this.AlignCommand.RaiseCanExecuteChanged());
                }
            });

            this.AlignCommand = new RelayCommand(this.AsyncAlign, this.CanAlign);

            // Executable if the selected files are aligned and alignment information is available.
            this.DisplayAlignmentCommand = new RelayCommand(
                this.DisplayAlignment,
                () => this.Datasets.Any(file => file.IsAligned && file.IsSelected &&
                                        this.alignmentInformation.Any(data => data.DatasetID == file.DatasetId)));

            // Executable if the selected files are aligned and alignment information is available.
            this.SaveAlignmentPlotsCommand = new RelayCommand(
                this.SaveAlignmentPlots,
                () => this.Datasets.Any(file => file.IsAligned && file.IsSelected &&
                                        this.alignmentInformation.Any(data => data.DatasetID == file.DatasetId)));

            this.RestoreDefaultsCommand = new RelayCommand(this.RestoreDefaults);
        }
        public override PuzzleStateAndGenerator GenerateRandomMoves(Random r)
        {
            // For fewest moves, we want to minimize the probability that the
            // scramble has useful "stuff" in it. The problem with conventional
            // Kociemba 2 phase solutions is that there's a pretty obvious
            // orientation step, which competitors might intentionally (or even
            // accidentally!) use in their solution. To lower the probability of this happening,
            // we intentionally generate dumbed down solutions.

            // We eventually decided to go with "Tom2", which is described by Tom
            // Rokicki (https://groups.google.com/d/msg/wca-admin/vVnuhk92hqg/P5oaJJQjDQAJ):

            // START TOM MESSAGE
            // If we're going this direction, and the exact length isn't critical, why not combine a bunch of the
            // ideas we've seen so far into something this simple:
            //
            // 1. Fix a set of prefix/suffix moves, say, U F R / U F R.
            // 2. For a given position p, find *any* solution where that solution prefixed and suffixed with
            //    the appropriate moves is canonical.
            //
            // That's it.  So we generate a random position, then find any two-phase solution g such
            // that U F R g U F R is a canonical sequence, and that's our FMC scramble.
            //
            // The prefix/suffix will be easily recognizable and memorable and ideally finger-trick
            // friendly (if it matters).
            //
            // Someone wanting to practice speed FMC (hehe) can make up their own scrambles just
            // by manually doing the prefix/suffix thing on any existing scrambler.
            //
            // It does not perturb the uniformity of the random position selection.
            //
            // It's simple enough that it is less likely to suffer from subtle defects due to the
            // perturbation of the two-phase search (unlikely those these may be).
            //
            // And even if the two-phase solution is short, adding U F R to the front and back makes it
            // no longer be unusually short (with high probability).
            // END TOM MESSAGE

            // Michael Young suggested using R' U' F as our padding (https://groups.google.com/d/msg/wca-admin/vVnuhk92hqg/EzQfG_vPBgAJ):

            // START MICHAEL MESSSAGE
            // I think that something more like R' U' F (some sequence that
            // involves a quarter-turn on all three "axes") is better because it
            // guarantees at least one bad edge in every orientation; with EO-first
            // options becoming more popular, "guaranteeing" that solving EO
            // optimally can't be derived from the scramble is a nice thing to
            // have, I think.  (Someone who was both unscrupulous and lucky could
            // see that R' F R doesn't affect U2/D2 EO, and therefore find out how
            // to solve EO by looking at the solution ignoring the R' F R.  That
            // being said, it still does change things, and I like how
            // finger-tricky/reversible the current prefix is.)  Just my two cents,
            // 'tho.
            // END MICHAEL MESSSAGE
            var scramblePrefix = SplitAlgorithm("R' U' F");
            var scrambleSuffix = SplitAlgorithm("R' U' F");

            // super.generateRandomMoves(...) will pick a random state S and find a solution:
            //  solution = sol_0, sol_1, ..., sol_n-1, sol_n
            // We then invert that solution to create a scramble:
            //  scramble = sol_n' + sol_(n-1)' + ... + sol_1' + sol_0'
            // We then prefix the scramble with scramblePrefix and suffix it with
            // scrambleSuffix to create paddedScramble:
            //  paddedScramble = scramblePrefix + scramble + scrambleSuffix
            //  paddedScramble = scramblePrefix + (sol_n' + sol_(n-1)' + ... + sol_1' + sol_0') + scrambleSuffix
            //
            // We don't want any moves to cancel here, so we need to make sure that
            // sol_n' doesn't cancel with the first move of scramblePrefix:
            var solutionLastAxisRestriction = scramblePrefix[scramblePrefix.Length - 1].Substring(0, 1);
            // and we need to make sure that sol_0' doesn't cancel with the first move of
            // scrambleSuffix:
            var solutionFirstAxisRestriction = scrambleSuffix[0].Substring(0, 1);
            var psag = GenerateRandomMoves(r, solutionFirstAxisRestriction, solutionLastAxisRestriction);
            var ab   = new AlgorithmBuilder(MergingMode.NoMerging, GetSolvedState());

            try
            {
                ab.AppendAlgorithms(scramblePrefix);
                ab.AppendAlgorithm(psag.Generator);
                ab.AppendAlgorithms(scrambleSuffix);
            }
            catch (InvalidMoveException e)
            {
                azzert(false, e.Message, e);
                return(null);
            }
            return(ab.GetStateAndGenerator());
        }