/// <summary>
        /// Initializes a new instance of the <see cref="ConfigurationFilterBase"/> class.
        /// </summary>
        /// <param name="generatorInput">The input for the generator.</param>
        protected ConfigurationFilterBase(ConfigurationGeneratorInput generatorInput)
        {
            GeneratorInput = generatorInput ?? throw new ArgumentNullException(nameof(generatorInput));

            // Find the type
            Type = FindTypeFromClassName();
        }
Exemple #2
0
        /// <inheritdoc/>
        public IEnumerable <GeneratedConfiguration> Generate(ConfigurationGeneratorInput input)
        {
            // Let the factory create the filter to be used
            var configurationFilter = _factory.Create(input);

            // Prepare the stack holding the current enumerator
            var enumerators = new Stack <IEnumerator <GeneratedConfiguration> >();

            // The first one will be the one that uses the original configuration
            enumerators.Push(ExtendConfiguration(new GeneratedConfiguration(input.InitialConfiguration), input, configurationFilter));

            // Generate until there is something
            while (enumerators.Any())
            {
                // Find out if this is the final iteration
                var isThisFinalIteration = enumerators.Count == input.NumberOfIterations;

                // Take the current enumerator, without removing
                var currentEnumerator = enumerators.Peek();

                // If this is the final iteration...
                if (isThisFinalIteration)
                {
                    // Enumerate it to the end
                    while (currentEnumerator.MoveNext())
                    {
                        yield return(currentEnumerator.Current);
                    }

                    // We can safely remove it
                    enumerators.Pop();

                    // We're done for now
                    continue;
                }

                // Otherwise this is not the final iteration
                // In that case move the enumerator...
                // If it's at the end...
                if (!currentEnumerator.MoveNext())
                {
                    // Then we remove it
                    enumerators.Pop();

                    // And we're done
                    continue;
                }

                // Otherwise we have generated something on a lower iteration then the final
                yield return(currentEnumerator.Current);

                // Now we need to prepare the configurations that can be generated from this one
                enumerators.Push(ExtendConfiguration(currentEnumerator.Current, input, configurationFilter));
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MemoryEfficientConfigurationFilter"/> class.
        /// </summary>
        /// <param name="generatorInput">The input for the generator.</param>
        public MemoryEfficientConfigurationFilter(ConfigurationGeneratorInput generatorInput) : base(generatorInput)
        {
            // Set the initial objects
            _initialObjects = generatorInput.InitialConfiguration.ConstructedObjects;

            // Assign ids to loose objects
            generatorInput.InitialConfiguration.LooseObjects.ForEach((looseObject, index) => _looseObjectsId.Add(looseObject, index));

            // Assign ids to constructions used in the generation
            generatorInput.Constructions
            // As well as to the constructions from the initial objects that are not a part of the generation
            .Concat(generatorInput.InitialConfiguration.ConstructedObjects.Select(constructedObject => constructedObject.Construction))
            // We need distinct ones so that we don't identify the same one twice
            .Distinct()
            // Add the id to the dictionary
            .ForEach((construction, index) => _constructionsId.Add(construction, index));
        }
Exemple #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SimpleConfigurationFilter"/> class.
 /// </summary>
 /// <param name="generatorInput">The input for the generator.</param>
 public SimpleConfigurationFilter(ConfigurationGeneratorInput generatorInput) : base(generatorInput)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="FastConfigurationFilter"/> class.
 /// </summary>
 /// <param name="generatorInput">The input for the generator.</param>
 public FastConfigurationFilter(ConfigurationGeneratorInput generatorInput) : base(generatorInput)
 {
 }
Exemple #6
0
        /// <summary>
        /// Creates the enumerator that will enumerate all possible ways to extended a given configuration.
        /// </summary>
        /// <param name="currentConfiguration">The current configuration being extended.</param>
        /// <param name="input">The input for the generator.</param>
        /// <param name="filter">The filter of generated configurations that should ensure that we generate distinct configurations.</param>
        /// <returns>The enumerator of generated configurations.</returns>
        private static IEnumerator <GeneratedConfiguration> ExtendConfiguration(GeneratedConfiguration currentConfiguration, ConfigurationGeneratorInput input, IConfigurationFilter filter)
        {
            // For a given configuration we create all possible objects using the constructions from the input
            return(input.Constructions.SelectMany(construction =>
            {
                // First we check if we have enough object to match the signature
                if (!construction.Signature.CanBeMatched(currentConfiguration.ObjectMap))
                {
                    return Enumerable.Empty <ConstructedConfigurationObject>();
                }

                // Now we check whether adding an object of the current type wouldn't exceed the maximal number
                // Find the number of added objects of this type as all objects of this type
                var numberOfAddedObjectsOfTheCurrentType = currentConfiguration.ObjectMap.GetObjectsForKeys(construction.OutputType).Count()
                                                           // Minus initial objects of this type
                                                           - input.InitialConfiguration.ObjectMap.GetObjectsForKeys(construction.OutputType).Count();

                // If adding of a new object would exceed the maximal requested count, we're done
                if (numberOfAddedObjectsOfTheCurrentType + 1 > input.MaximalNumbersOfObjectsToAdd[construction.OutputType])
                {
                    return Enumerable.Empty <ConstructedConfigurationObject>();
                }

                // Now we're sure we can generate some objects
                // First we take all the available pairs [object type, objects]
                return currentConfiguration.ObjectMap
                // Those are wrapped in a dictionary mapping object types to particular objects
                // We take only those types that are required in our signature
                .Where(keyValue => construction.Signature.ObjectTypesToNeededCount.ContainsKey(keyValue.Key))
                // We cast each type to the IEnumerable of all possible variations of those objects
                // having the needed number of elements. Each of these variations represents a way to
                // use some objects of their type in our arguments
                .Select(keyValue => keyValue.Value.Variations(construction.Signature.ObjectTypesToNeededCount[keyValue.Key]))
                // We need to combine all these options for particular object types in every possible way
                // For example, if we need 2 points and 2 lines, and we have 4 pair of points and 5 pairs of lines
                // then there are 20 ways of combining these pairs. The result of this call will be an enumerable
                // where each element is an array of options (each array representing an option for some particular type)
                .Combine()
                // We need to create a single array representing an input for the signature.Match method
                .Select(arrays =>
                {
                    // Create a helper dictionary mapping types to an array of objects of these types
                    var typeToObjects = arrays.ToDictionary(objects => objects[0].ObjectType, objects => objects);

                    // Create a helper dictionary mapping types to the current index (pointer) on the next object
                    // of this type that should be returned
                    var typeToIndex = arrays.ToDictionary(objects => objects[0].ObjectType, objects => 0);

                    // We go through the requested types and for each we take the object of the given type
                    // and at the same moment increase the index so that it points out to the next object of this type
                    return construction.Signature.ObjectTypes.Select(type => typeToObjects[type][typeToIndex[type]++]).ToArray();
                })
                // After we have objects for the signature, we can match it to create arguments
                .Select(construction.Signature.Match)
                // And finally a constructed object using them
                .Select(arguments => new ConstructedConfigurationObject(construction, arguments))
                // We want distinct objects
                .Distinct();
            })
                   // Don't take the objects that would make duplicate objects in the configuration
                   .Where(newObject => !currentConfiguration.ConstructedObjectsSet.Contains(newObject))
                   // Add the object to the current configuration
                   .Select(newObject => new GeneratedConfiguration(currentConfiguration, newObject, currentConfiguration.IterationIndex + 1))
                   // Check the configuration by the filter
                   .Where(configuration => !filter.ShouldBeExcluded(configuration))
                   // Apply the custom configuration filter
                   .Where(input.ConfigurationFilter.Invoke)
                   // Finally get the enumerator
                   .GetEnumerator());
        }