예제 #1
0
        /// <summary>
        /// Introduces a new object and handles all the needed communicated with the normalization helper.
        /// </summary>
        /// <returns>
        /// <param name="theoremsToProve">The theorems that are still left to be proven.</param>
        /// The tuple of objects that got removed and the object that got introduced. The object list will never
        /// be null, but might be empty. Also, the number of removed objects might be bigger than the number of
        /// previously introduced ones, because the normalization helper might have found equal ones in the meantime.
        /// If there has been no introduces, then the new object will be null.
        /// </returns>
        public (IReadOnlyList <ConstructedConfigurationObject> removedObjects, ConstructedConfigurationObject newObject) IntroduceObject(IEnumerable <Theorem> theoremsToProve)
        {
            #region Handle object removal

            // Prepare the removed objects
            var removedObjects = new List <ConstructedConfigurationObject>();

            // If the last introduced object was a point
            if (_lastIntroducedObject != null && _lastIntroducedObject.ObjectType == ConfigurationObjectType.Point)
            {
                // Let the normalization helper remove it, while returning everything what's been removed
                _helper.RemoveIntroducedObject(_lastIntroducedObject, out var removedObjectsLocal);

                // Mark the removed objects
                removedObjects.Add(removedObjectsLocal);
            }

            #endregion

            #region Handle object introduction

            // Find the object to introduce by calling the introducer
            var newObject = _introducer
                            // With the available objects equal to those
                            .IntroduceObjects(_helper.AllObjects
                            // That are in the original configuration (otherwise it would be explosive)
                                              .Where(_helper.IsInOriginalConfiguration)
                            // Enumerated
                                              .ToArray())
                            // Concat object introduced based on theorems to be proven
                            .Concat(theoremsToProve.SelectMany(PerformTheoremBasedIntroduction))
                            // The introducer offers us some options that we need to normalize by copying the construction
                            .Select(newObject => new ConstructedConfigurationObject(newObject.Construction,
                            // And normalizing each of the argument objects
                                                                                    newObject.PassedArguments.FlattenedList.Select(_helper.GetNormalVersionOfObjectOrNull).ToArray()))
                            // When we have options normalize, we need to filter those objects that have been introduced already
                            .Where(newObject => !_allIntroducedObjects.Contains(newObject)
                            // And aren't already known to the helper
                                   && !_helper.AllObjects.Contains(newObject)
                            // And haven't been ever known to the helper
                                   && !_helper.AllRemovedObjects.Contains(newObject))
                            // Enumerate
                            .ToArray()
                            // Sort them so that we first introduce non-points (lines and circles)
                            .OrderBy(newObject => newObject.ObjectType == ConfigurationObjectType.Point ? 1 : 0)
                            // Take the first option
                            .FirstOrDefault();

            // If there is something to be introduced
            if (newObject != null)
            {
                // Let the normalization helper know
                _helper.IntroduceNewObject(newObject);

                // Add the object to the set of all objects ever introduced
                _allIntroducedObjects.Add(newObject);
            }

            // Set the last introduced object
            _lastIntroducedObject = newObject;

            #endregion

            // Return the removed objects together with the new ones
            return(removedObjects, newObject);
        }