Example #1
0
        /// <summary>
        /// One level of GenericJoin, taking functions acting on the stream of candidates as if they were the relations.
        /// </summary>
        /// <typeparam name="V">The new value type</typeparam>
        /// <typeparam name="T">The current tuple type</typeparam>
        /// <param name="Candidates">A stream of candidates of type T</param>
        /// <param name="Relations">Representatives of each relation</param>
        /// <returns>A stream of Pair(T, V[]) corresponding to extensions of Candidates validated by all relations.</returns>
        public static Stream <Pair <T, V[]>, Epoch> GenericJoinLayer <V, T>(this Stream <T, Epoch> Candidates,
                                                                            PrefixExtender <T, V>[] Relations)
            where V : IComparable <V>
        {
            // count the extensions in each relation, maintain the smallest.
            var Smallest = Relations[0].CountExtensions(Candidates, 0);

            foreach (var index in Enumerable.Range(1, Relations.Length - 1))
            {
                Smallest = Relations[index].ImproveExtensions(Smallest, index);
            }

            // propose extensions for each relation, filter by other relations.
            var Proposals = new Stream <Pair <T, V[]>, Epoch> [Relations.Length];

            foreach (var index in Enumerable.Range(0, Relations.Length))
            {
                Proposals[index] = Relations[index].ExtendPrefixes(Smallest, index);
                foreach (var otherIndex in Enumerable.Range(0, Relations.Length))
                {
                    if (otherIndex != index)
                    {
                        Proposals[index] = Relations[otherIndex].ValidateExtensions(Proposals[index]);
                    }
                }
            }

            // return all proposals which passed all filtering steps.
            return(Proposals.Aggregate((x, y) => x.Concat(y)));
        }