Пример #1
0
 public T GetValue()
 {
     return((T)(RandomUtilities.ChooseRandomEnumValue(typeof(T), _nextInt)));
 }
Пример #2
0
        /// <summary>
        /// Explores the input (sub-)space. Each invocation may return a different set.
        /// </summary>
        /// <returns>
        /// A (reasonably-sized) stream of vectors/values from the (sub-)space.
        /// </returns>
        public override IEnumerable <Vector> Explore()
        {
            if (TargetMatrix.Dimensions.Count == 0)
            {
                // No dimensions to explore, then yield one empty vector.
                yield return(new Vector());

                yield break;
            }

            ReadOnlyCollection <DimensionWithValues> dimensionValues = GetAllDimensionValues();

            if (dimensionValues.Any(dim => dim.Values.Count == 0))
            {
                yield break;                 // One of the dimensions is empty
            }

            if (dimensionValues.Count < _order)
            {
                // This is really non-sensical to ask for an n-wise strategy for a matrix with less than n dimensions
                // but I'd rather return a good default than throw. So I'll just cheat and do an exhaustive strategy instead
                ExhaustiveCombinatorialStrategy exhaustiveStrategy = new ExhaustiveCombinatorialStrategy(this);
                foreach (Vector v in exhaustiveStrategy.Explore())
                {
                    yield return(v);
                }
                yield break;
            }

            CoveredPairwiseCombinations coveredCombinations = new CoveredPairwiseCombinations();

            DimensionValueIndexCombination     currentCombination      = new DimensionValueIndexCombination(dimensionValues);
            DimensionIndexCombinationGenerator dimensionIndexGenerator = CreateDimensionIndexCombinationGenerator(dimensionValues);
            Vector currentVector = currentCombination.GenerateVector();

            if (IsValidVector(currentVector))
            {
                coveredCombinations.AddCoveredPairwiseCombinations(currentCombination, dimensionIndexGenerator);
                yield return(currentVector);
            }

            PartialVectorConstraintChecker partialConstraintChecker = UsePartialConstraintChecker ?
                                                                      new PartialVectorConstraintChecker(dimensionValues, Constraints) : null;

            foreach (ReadOnlyCollection <int> currentDimensionsToCover in dimensionIndexGenerator.Generate())
            {
                // Initialize the selection of values in the newly selected pairwise combination
                for (int i = 0; i < currentDimensionsToCover.Count; i++)
                {
                    currentCombination[currentDimensionsToCover[i]] = 0;
                }

                while (true)
                {
                    bool selectionSucceeded = SelectNextValuesForCurrentDimensionCombination(currentCombination, currentDimensionsToCover);

                    if (!selectionSucceeded)
                    {
                        // We exhausted all combinations of values for the current pairwise combination
                        // select the next pairwise combination
                        break;
                    }

                    if (coveredCombinations.IsCombinationCovered(currentDimensionsToCover, currentCombination))
                    {
                        continue;
                    }

                    if (partialConstraintChecker != null &&
                        !partialConstraintChecker.IsValidForApplicableConstraints(currentCombination, currentDimensionsToCover))
                    {
                        // This combination is forbidden by constraints - carry on
                        continue;
                    }

                    // Randomize other values, try at most MAXTRIES since we might hit invalid combinations
                    for (int i = 0; i < MAXTRIES; i++)
                    {
                        List <int> remainingDimensionIndexes = Enumerable.Range(0, dimensionValues.Count)
                                                               .Where(di => !currentDimensionsToCover.Contains(di)) // Don't randomize the pair currently worked on
                                                               .ToList();
                        RandomUtilities.ShuffleList(remainingDimensionIndexes, _nextInt);
                        List <int> setDimensionIndexes = new List <int>(currentDimensionsToCover);
                        foreach (int dimensionIndex in remainingDimensionIndexes)
                        {
                            ReadOnlyCollection <int> allowedValueIndexes = UsePartialConstraintChecker ?
                                                                           partialConstraintChecker.GetAllowedValueIndexesForDimension(dimensionIndex, setDimensionIndexes, currentCombination) :
                                                                           Enumerable.Range(0, currentCombination.GetDimensionSize(dimensionIndex)).ToList().AsReadOnly();
                            if (allowedValueIndexes.Count == 0)
                            {
                                break;
                            }
                            currentCombination[dimensionIndex] = allowedValueIndexes[_nextInt(allowedValueIndexes.Count)];
                            setDimensionIndexes.Add(dimensionIndex);
                        }
                        if (setDimensionIndexes.Count < dimensionValues.Count)
                        {
                            // Couldn't set all dimension values, try again (or quit)
                            continue;
                        }

                        currentVector = currentCombination.GenerateVector();
                        if (partialConstraintChecker != null || IsValidVector(currentVector))
                        {
                            coveredCombinations.AddCoveredPairwiseCombinations(currentCombination, dimensionIndexGenerator);
                            yield return(currentVector);

                            break;                             // Out of the MAXTRIES loop
                        }
                    }
                }
            }
        }