/// <summary> /// Explores the input (sub-)space to give (potentially dynamic) value factories. Each invocation may return a different set. /// </summary> /// <returns> /// A (reasonably-sized) stream of vector/value-factories from the (sub-)space. /// </returns> public override IEnumerable <IValueFactory <T> > DynamicExplore() { List <IValueFactory <T> > originalValues = new List <IValueFactory <T> >(WrappedStrategies[0].DynamicExplore()); RandomUtilities.ShuffleList(originalValues, _nextInt); return(originalValues); }
/// <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 } } } } }