Пример #1
0
        private bool SelectNextValuesForCurrentDimensionCombination(DimensionValueIndexCombination currentCombination,
                                                                    ReadOnlyCollection <int> currentDimensionsToCover)
        {
            int  currentIndex = currentDimensionsToCover.Count - 1;
            bool selectNext   = true;

            // Continue enumerating pairwise indices until a value is selected (!selectNext)
            // or we exhaust all possibilities for the current pairwise combination
            // (selectNext) && (currentIndex == -1)
            while ((selectNext) && (currentIndex >= 0))
            {
                Debug.Assert(currentCombination[currentDimensionsToCover[currentIndex]] < currentCombination.GetDimensionSize(currentDimensionsToCover[currentIndex]));
                if (currentCombination[currentDimensionsToCover[currentIndex]] == currentCombination.GetDimensionSize(currentDimensionsToCover[currentIndex]) - 1)
                {
                    currentCombination[currentDimensionsToCover[currentIndex]] = 0;
                    selectNext = true;
                    currentIndex--;
                }
                else
                {
                    currentCombination[currentDimensionsToCover[currentIndex]]++;
                    selectNext = false;
                }
            }

            return(!selectNext || (currentIndex != -1));
        }
		/// <summary>
		/// Gets the allowed values for a given target dimension, given the values that have been set so far for other dimensions.
		/// </summary>
		/// <param name="targetDimension">The index of the target dimension (index is relative to the dimensionValues collection passed in at construction).</param>
		/// <param name="setDimensionIndexes">The indexes of the dimensions where we have chosen values.</param>
		/// <param name="currentCombination">The chosen values for the dimensions.</param>
		/// <returns>A list of indexes refering to values from the dimensionValues collection passed in at construction that are valid according to constraints.</returns>
		public ReadOnlyCollection<int> GetAllowedValueIndexesForDimension(int targetDimension, IEnumerable<int> setDimensionIndexes,
			DimensionValueIndexCombination currentCombination)
		{
			List<int> ret = new List<int>(Enumerable.Range(0, _dimensionValues[targetDimension].Values.Count));
			foreach (PossiblyExtendedConstraint constraint in _extendedConstraints.Where(c => c.IsRelevantConstraint(targetDimension, setDimensionIndexes)))
			{
				ret.RemoveAll(vi => !constraint.IsValid(currentCombination, targetDimension, vi));
			}
			return ret.AsReadOnly();
		}
Пример #3
0
 /// <summary>
 /// Adds all the combinations of the given order as covered.
 /// </summary>
 /// <param name="combination">The combination to cover.</param>
 /// <param name="dimensionIndexGenerator">The dimension index generator to use for getting all dimension index combinations we care about.</param>
 public void AddCoveredPairwiseCombinations(DimensionValueIndexCombination combination, DimensionIndexCombinationGenerator dimensionIndexGenerator)
 {
     foreach (ReadOnlyCollection <int> dimensionsOfInterest in dimensionIndexGenerator.Generate())
     {
         if (!IsCombinationCovered(dimensionsOfInterest, combination))
         {
             _coveredCombinations.Add(EncodeCombination(dimensionsOfInterest, combination));
         }
     }
 }
        /// <summary>
        /// Gets the allowed values for a given target dimension, given the values that have been set so far for other dimensions.
        /// </summary>
        /// <param name="targetDimension">The index of the target dimension (index is relative to the dimensionValues collection passed in at construction).</param>
        /// <param name="setDimensionIndexes">The indexes of the dimensions where we have chosen values.</param>
        /// <param name="currentCombination">The chosen values for the dimensions.</param>
        /// <returns>A list of indexes refering to values from the dimensionValues collection passed in at construction that are valid according to constraints.</returns>
        public ReadOnlyCollection <int> GetAllowedValueIndexesForDimension(int targetDimension, IEnumerable <int> setDimensionIndexes,
                                                                           DimensionValueIndexCombination currentCombination)
        {
            List <int> ret = new List <int>(Enumerable.Range(0, _dimensionValues[targetDimension].Values.Count));

            foreach (PossiblyExtendedConstraint constraint in _extendedConstraints.Where(c => c.IsRelevantConstraint(targetDimension, setDimensionIndexes)))
            {
                ret.RemoveAll(vi => !constraint.IsValid(currentCombination, targetDimension, vi));
            }
            return(ret.AsReadOnly());
        }
Пример #5
0
            /// <summary>
            /// Determines whether the given combination has already been covered.
            /// </summary>
            /// <param name="dimensionsOfInterest">The dimensions of interest.</param>
            /// <param name="combination">The combination.</param>
            /// <returns>
            ///     <c>true</c> if the given combination is already covered; otherwise, <c>false</c>.
            /// </returns>
            public bool IsCombinationCovered(ICollection <int> dimensionsOfInterest, DimensionValueIndexCombination combination)
            {
                List <int> encodedCombination = EncodeCombination(dimensionsOfInterest, combination);

                foreach (List <int> covered in _coveredCombinations)
                {
                    if (AreEqual(covered, encodedCombination))
                    {
                        return(true);
                    }
                }
                return(false);
            }
			public bool IsValid(DimensionValueIndexCombination combination)
			{
				return IsValid(GetValueIndexes(combination));
			}
			public bool IsValid(DimensionValueIndexCombination combination, int targetDimensionIndex, int targetDimensionIndexValue)
			{
				return IsValid(GetValueIndexes(combination, targetDimensionIndex, targetDimensionIndexValue));
			}
Пример #8
0
		private bool SelectNextValuesForCurrentDimensionCombination(DimensionValueIndexCombination currentCombination,
			ReadOnlyCollection<int> currentDimensionsToCover)
		{
			int currentIndex = currentDimensionsToCover.Count - 1;
			bool selectNext = true;

			// Continue enumerating pairwise indices until a value is selected (!selectNext)
			// or we exhaust all possibilities for the current pairwise combination
			// (selectNext) && (currentIndex == -1)
			while ((selectNext) && (currentIndex >= 0))
			{
				Debug.Assert(currentCombination[currentDimensionsToCover[currentIndex]] < currentCombination.GetDimensionSize(currentDimensionsToCover[currentIndex]));
				if (currentCombination[currentDimensionsToCover[currentIndex]] == currentCombination.GetDimensionSize(currentDimensionsToCover[currentIndex]) - 1)
				{
					currentCombination[currentDimensionsToCover[currentIndex]] = 0;
					selectNext = true;
					currentIndex--;
				}
				else
				{
					currentCombination[currentDimensionsToCover[currentIndex]]++;
					selectNext = false;
				}
			}

			return !selectNext || (currentIndex != -1);
		}
 public bool IsValid(DimensionValueIndexCombination combination, int targetDimensionIndex, int targetDimensionIndexValue)
 {
     return(IsValid(GetValueIndexes(combination, targetDimensionIndex, targetDimensionIndexValue)));
 }
 private IEnumerable <int> GetValueIndexes(DimensionValueIndexCombination combination, int targetDimensionIndex, int targetDimensionIndexValue)
 {
     return(Enumerable.Range(0, _dimensionIndexes.Count).Select(i => GetValueIndex(i, combination, targetDimensionIndex, targetDimensionIndexValue)));
 }
Пример #11
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
                        }
                    }
                }
            }
        }
Пример #12
0
			/// <summary>
			/// Encodes the given combination as a list of integers
			/// </summary>
			/// <param name="dimensionsOfInterest"></param>
			/// <param name="combination"></param>
			/// <returns></returns>
			/// <remarks>
			/// I'll just encode a covered combination like: {D4:2,D1:10} as {1,10,4,2} (sort on dimension index first).
			/// </remarks>
			private static List<int> EncodeCombination(ICollection<int> dimensionsOfInterest, DimensionValueIndexCombination combination)
			{
				List<int> sortedDimensions = new List<int>(dimensionsOfInterest);
				sortedDimensions.Sort();
				List<int> ret = new List<int>(dimensionsOfInterest.Count * 2);
				foreach (int dimension in sortedDimensions)
				{
					ret.Add(dimension);
					ret.Add(combination[dimension]);
				}
				return ret;
			}
Пример #13
0
			/// <summary>
			/// Adds all the combinations of the given order as covered.
			/// </summary>
			/// <param name="combination">The combination to cover.</param>
			/// <param name="dimensionIndexGenerator">The dimension index generator to use for getting all dimension index combinations we care about.</param>
			public void AddCoveredPairwiseCombinations(DimensionValueIndexCombination combination, DimensionIndexCombinationGenerator dimensionIndexGenerator)
			{
				foreach (ReadOnlyCollection<int> dimensionsOfInterest in dimensionIndexGenerator.Generate())
				{
					if (!IsCombinationCovered(dimensionsOfInterest, combination))
						_coveredCombinations.Add(EncodeCombination(dimensionsOfInterest, combination));
				}
			}
Пример #14
0
			/// <summary>
			/// Determines whether the given combination has already been covered.
			/// </summary>
			/// <param name="dimensionsOfInterest">The dimensions of interest.</param>
			/// <param name="combination">The combination.</param>
			/// <returns>
			/// 	<c>true</c> if the given combination is already covered; otherwise, <c>false</c>.
			/// </returns>
			public bool IsCombinationCovered(ICollection<int> dimensionsOfInterest, DimensionValueIndexCombination combination)
			{
				List<int> encodedCombination = EncodeCombination(dimensionsOfInterest, combination);
				foreach (List<int> covered in _coveredCombinations)
				{
					if (AreEqual(covered, encodedCombination))
						return true;
				}
				return false;
			}
		/// <summary>
		/// Checks if the vector so far is valid according to constraints.
		/// </summary>
		/// <param name="combination">The combination with the values chosen so far.</param>
		/// <param name="setDimensionIndexes">The indexes of the dimensions where we have chosen values.</param>
		/// <returns><c>true</c></returns>
		public bool IsValidForApplicableConstraints(DimensionValueIndexCombination combination, IEnumerable<int> setDimensionIndexes)
		{
			return _extendedConstraints.Where(c => c.IsRelevantConstraint(setDimensionIndexes)).All(c => c.IsValid(combination));
		}
Пример #16
0
            /// <summary>
            /// Encodes the given combination as a list of integers
            /// </summary>
            /// <param name="dimensionsOfInterest"></param>
            /// <param name="combination"></param>
            /// <returns></returns>
            /// <remarks>
            /// I'll just encode a covered combination like: {D4:2,D1:10} as {1,10,4,2} (sort on dimension index first).
            /// </remarks>
            private static List <int> EncodeCombination(ICollection <int> dimensionsOfInterest, DimensionValueIndexCombination combination)
            {
                List <int> sortedDimensions = new List <int>(dimensionsOfInterest);

                sortedDimensions.Sort();
                List <int> ret = new List <int>(dimensionsOfInterest.Count * 2);

                foreach (int dimension in sortedDimensions)
                {
                    ret.Add(dimension);
                    ret.Add(combination[dimension]);
                }
                return(ret);
            }
 private int GetValueIndex(int dimensionIndexIndex, DimensionValueIndexCombination combination, int targetDimensionIndex, int targetDimensionIndexValue)
 {
     return(_dimensionIndexes[dimensionIndexIndex] == targetDimensionIndex ? targetDimensionIndexValue : combination[_dimensionIndexes[dimensionIndexIndex]]);
 }
			private int GetValueIndex(int dimensionIndexIndex, DimensionValueIndexCombination combination, int targetDimensionIndex, int targetDimensionIndexValue)
			{
				return _dimensionIndexes[dimensionIndexIndex] == targetDimensionIndex ? targetDimensionIndexValue : combination[_dimensionIndexes[dimensionIndexIndex]];
			}
 private IEnumerable <int> GetValueIndexes(DimensionValueIndexCombination combination)
 {
     return(_dimensionIndexes.Select(d => combination[d]));
 }
			private IEnumerable<int> GetValueIndexes(DimensionValueIndexCombination combination, int targetDimensionIndex, int targetDimensionIndexValue)
			{
				return Enumerable.Range(0, _dimensionIndexes.Count).Select(i => GetValueIndex(i, combination, targetDimensionIndex, targetDimensionIndexValue));
			}
 public bool IsValid(DimensionValueIndexCombination combination)
 {
     return(IsValid(GetValueIndexes(combination)));
 }
			private IEnumerable<int> GetValueIndexes(DimensionValueIndexCombination combination)
			{
				return _dimensionIndexes.Select(d => combination[d]);
			}
 /// <summary>
 /// Checks if the vector so far is valid according to constraints.
 /// </summary>
 /// <param name="combination">The combination with the values chosen so far.</param>
 /// <param name="setDimensionIndexes">The indexes of the dimensions where we have chosen values.</param>
 /// <returns><c>true</c></returns>
 public bool IsValidForApplicableConstraints(DimensionValueIndexCombination combination, IEnumerable <int> setDimensionIndexes)
 {
     return(_extendedConstraints.Where(c => c.IsRelevantConstraint(setDimensionIndexes)).All(c => c.IsValid(combination)));
 }
Пример #24
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
						}
					}
				}
			}
		}