コード例 #1
0
        public void SparqlAlgebraJoinMultiVariable1()
        {
            ISet x = new Set();

            x.Add("a", this._factory.CreateUriNode(UriFactory.Create("http://x")));
            x.Add("b", this._factory.CreateUriNode(UriFactory.Create("http://y")));

            ISet y1 = new Set();

            y1.Add("a", this._factory.CreateUriNode(UriFactory.Create("http://x")));
            y1.Add("b", this._factory.CreateUriNode(UriFactory.Create("http://y")));
            ISet y2 = new Set();

            y2.Add("a", this._factory.CreateUriNode(UriFactory.Create("http://x")));
            y2.Add("b", this._factory.CreateUriNode(UriFactory.Create("http://y")));

            BaseMultiset lhs = new Multiset();

            lhs.Add(x);
            BaseMultiset rhs = new Multiset();

            rhs.Add(y1);
            rhs.Add(y2);

            BaseMultiset joined = lhs.Join(rhs);

            Assert.AreEqual(2, joined.Count);
        }
コード例 #2
0
ファイル: JoinTests.cs プロジェクト: adamthe30/KADL-iet-2018
        public void SparqlAlgebraJoinMultiVariable4()
        {
            ISet x1 = new Set();

            x1.Add("a", this._factory.CreateUriNode(UriFactory.Create("http://x1")));
            x1.Add("b", this._factory.CreateUriNode(UriFactory.Create("http://y1")));
            ISet x2 = new Set();

            x2.Add("a", this._factory.CreateUriNode(UriFactory.Create("http://x2")));
            x2.Add("b", this._factory.CreateUriNode(UriFactory.Create("http://y2")));

            ISet y1 = new Set();

            y1.Add("a", this._factory.CreateUriNode(UriFactory.Create("http://x1")));
            y1.Add("b", this._factory.CreateUriNode(UriFactory.Create("http://y2")));
            ISet y2 = new Set();

            y2.Add("a", this._factory.CreateUriNode(UriFactory.Create("http://x2")));
            y2.Add("b", this._factory.CreateUriNode(UriFactory.Create("http://y1")));

            BaseMultiset lhs = new Multiset();

            lhs.Add(x1);
            lhs.Add(x2);
            BaseMultiset rhs = new Multiset();

            rhs.Add(y1);
            rhs.Add(y2);

            BaseMultiset joined = lhs.Join(rhs);

            Assert.Equal(0, joined.Count);
        }
コード例 #3
0
        /// <summary>
        /// Does a Union of this Multiset and another Multiset.
        /// </summary>
        /// <param name="other">Other Multiset.</param>
        /// <returns></returns>
        public override BaseMultiset Union(BaseMultiset other)
        {
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(this);
            }
            if (other.IsEmpty)
            {
                return(this);
            }

            Multiset m = new Multiset();

            foreach (ISet s in this.Sets)
            {
                m.Add(s.Copy());
            }
            foreach (ISet s in other.Sets)
            {
                m.Add(s.Copy());
            }
            return(m);
        }
コード例 #4
0
        /// <summary>
        /// Does a Product of this Multiset and another Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset Product(BaseMultiset other)
        {
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(other);
            }
            if (other.IsEmpty)
            {
                return(new NullMultiset());
            }

            Multiset productSet = new Multiset();

            foreach (ISet x in this.Sets)
            {
                foreach (ISet y in other.Sets)
                {
                    productSet.Add(x.Join(y));
                }
            }
            return(productSet);
        }
コード例 #5
0
        /// <summary>
        /// Does a Product of this Multiset and another Multiset.
        /// </summary>
        /// <param name="other">Other Multiset.</param>
        /// <returns></returns>
        public virtual BaseMultiset Product(BaseMultiset other)
        {
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(other);
            }
            if (other.IsEmpty)
            {
                return(new NullMultiset());
            }

#if NET40
            if (Options.UsePLinqEvaluation)
            {
                // Determine partition sizes so we can do a parallel product
                // Want to parallelize over whichever side is larger
                PartitionedMultiset partitionedSet;
                if (this.Count >= other.Count)
                {
                    partitionedSet = new PartitionedMultiset(this.Count, other.Count);
                    this.Sets.AsParallel().ForAll(x => this.EvalProduct(x, other, partitionedSet));
                }
                else
                {
                    partitionedSet = new PartitionedMultiset(other.Count, this.Count);
                    other.Sets.AsParallel().ForAll(y => this.EvalProduct(y, this, partitionedSet));
                }
                return(partitionedSet);
            }
            else
            {
                // Use serial calculation which is likely to really suck for big products
                Multiset productSet = new Multiset();
                foreach (ISet x in this.Sets)
                {
                    foreach (ISet y in other.Sets)
                    {
                        productSet.Add(x.Join(y));
                    }
                }
                return(productSet);
            }
#else
            // Use serial calculation which is likely to really suck for big products
            var productSet = new Multiset();
            foreach (var x in Sets)
            {
                foreach (var y in other.Sets)
                {
                    productSet.Add(x.Join(y));
                }
            }
            return(productSet);
#endif
        }
コード例 #6
0
        /// <summary>
        /// Joins this Multiset to another Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset Join(BaseMultiset other)
        {
            //If the Other is the Identity Multiset the result is this Multiset
            if (other is IdentityMultiset)
            {
                return(this);
            }
            //If the Other is the Null Multiset the result is the Null Multiset
            if (other is NullMultiset)
            {
                return(other);
            }
            //If the Other is Empty then the result is the Null Multiset
            if (other.IsEmpty)
            {
                return(new NullMultiset());
            }

            //Find the First Variable from this Multiset which is in both Multisets
            //If there is no Variable from this Multiset in the other Multiset then this
            //should be a Join operation instead of a LeftJoin
            List <String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                return(this.Product(other));
            }

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();

            foreach (ISet x in this.Sets)
            {
                //For sets to be compatible for every joinable variable they must either have a null for the
                //variable in one of the sets or if they have values the values must be equal

                ////This first check is to try speed things up, it looks whether there are solutions that may match
                ////without needing to do a full table scan of the RHS results as the subsequent LINQ call will do
                ////if (!joinVars.All(v => x[v] == null || other.ContainsValue(v, x[v]) || other.ContainsValue(v, null))) continue;

                IEnumerable <ISet> ys = other.Sets.Where(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
                //IEnumerable<ISet> ys = other.Sets.Where(s => s.IsCompatibleWith(x, joinVars));

                foreach (ISet y in ys)
                {
                    joinedSet.Add(x.Join(y));
                }
            }
            return(joinedSet);
        }
コード例 #7
0
        public void SparqlAlgebraJoinSingleVariable1()
        {
            ISet x = new Set();

            x.Add("a", this._factory.CreateUriNode(UriFactory.Create("http://x")));

            BaseMultiset lhs = new Multiset();

            lhs.Add(x);
            BaseMultiset rhs = new Multiset();

            rhs.Add(x);

            BaseMultiset joined = lhs.Join(rhs);

            Assert.AreEqual(1, joined.Count);
        }
コード例 #8
0
        /// <summary>
        /// Does a Minus Join of this Multiset to another Multiset where any joinable results are subtracted from this Multiset to give the resulting Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset MinusJoin(BaseMultiset other)
        {
            //If the other Multiset is the Identity/Null Multiset then minus-ing it doesn't alter this set
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(this);
            }
            //If the other Multiset is disjoint then minus-ing it also doesn't alter this set
            if (this.IsDisjointWith(other))
            {
                return(this);
            }

            //Find the Variables that are to be used for Joining
            List <String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                return(this.Product(other));
            }

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();

            foreach (ISet x in this.Sets)
            {
                //New Minus logic based on the improved Join() logic
                bool minus = other.Sets.Any(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));

                //If no compatible sets then this set is preserved
                if (!minus)
                {
                    joinedSet.Add(x);
                }
            }
            return(joinedSet);
        }
コード例 #9
0
ファイル: Multiset.cs プロジェクト: jbunzel/MvcRQ_git
        /// <summary>
        /// Joins this Multiset to another Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset Join(BaseMultiset other)
        {
            //If the Other is the Identity Multiset the result is this Multiset
            if (other is IdentityMultiset) return this;
            //If the Other is the Null Multiset the result is the Null Multiset
            if (other is NullMultiset) return other;
            //If the Other is Empty then the result is the Null Multiset
            if (other.IsEmpty) return new NullMultiset();

            //Find the First Variable from this Multiset which is in both Multisets
            //If there is no Variable from this Multiset in the other Multiset then this
            //should be a Join operation instead of a LeftJoin
            List<String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();
            if (joinVars.Count == 0) return this.Product(other);

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();
            foreach (ISet x in this.Sets)
            {
                //For sets to be compatible for every joinable variable they must either have a null for the
                //variable in one of the sets or if they have values the values must be equal

                ////This first check is to try speed things up, it looks whether there are solutions that may match
                ////without needing to do a full table scan of the RHS results as the subsequent LINQ call will do
                ////if (!joinVars.All(v => x[v] == null || other.ContainsValue(v, x[v]) || other.ContainsValue(v, null))) continue;

                IEnumerable<ISet> ys = other.Sets.Where(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
                //IEnumerable<ISet> ys = other.Sets.Where(s => s.IsCompatibleWith(x, joinVars));

                foreach (ISet y in ys)
                {
                    joinedSet.Add(x.Join(y));
                }
            }
            return joinedSet;
        }
コード例 #10
0
        /// <summary>
        /// Evaluates a setp of the Path
        /// </summary>
        /// <param name="context">Context</param>
        /// <param name="path">Paths</param>
        /// <param name="reverse">Whether to evaluate Paths in reverse</param>
        /// <returns></returns>
        protected List<INode> EvaluateStep(SparqlEvaluationContext context, List<INode> path, bool reverse)
        {
            if (this.Path is Property)
            {
                HashSet<INode> nodes = new HashSet<INode>();
                INode predicate = ((Property)this.Path).Predicate;
                IEnumerable<Triple> ts = (reverse ? context.Data.GetTriplesWithPredicateObject(predicate, path[path.Count - 1]) : context.Data.GetTriplesWithSubjectPredicate(path[path.Count - 1], predicate));
                foreach (Triple t in ts)
                {
                    if (reverse)
                    {
                        if (!path.Contains(t.Subject))
                        {
                            nodes.Add(t.Subject);
                        }
                    }
                    else
                    {
                        if (!path.Contains(t.Object))
                        {
                            nodes.Add(t.Object);
                        }
                    }
                }
                return nodes.ToList();
            }
            else
            {
                List<INode> nodes = new List<INode>();

                BaseMultiset initialInput = context.InputMultiset;
                Multiset currInput = new Multiset();
                VariablePattern x = new VariablePattern("?x");
                VariablePattern y = new VariablePattern("?y");
                Set temp = new Set();
                if (reverse)
                {
                    temp.Add("y", path[path.Count - 1]);
                }
                else
                {
                    temp.Add("x", path[path.Count - 1]);
                }
                currInput.Add(temp);
                context.InputMultiset = currInput;

                Bgp bgp = new Bgp(new PropertyPathPattern(x, this.Path, y));
                BaseMultiset results = context.Evaluate(bgp);//bgp.Evaluate(context);
                context.InputMultiset = initialInput;

                if (!results.IsEmpty)
                {
                    foreach (Set s in results.Sets)
                    {
                        if (reverse)
                        {
                            if (s["x"] != null)
                            {
                                if (!path.Contains(s["x"]))
                                {
                                    nodes.Add(s["x"]);
                                }
                            }
                        }
                        else
                        {
                            if (s["y"] != null)
                            {
                                if (!path.Contains(s["y"]))
                                {
                                    nodes.Add(s["y"]);
                                }
                            }
                        }
                    }
                }

                return nodes;
            }
        }
コード例 #11
0
        /// <summary>
        /// Does a Left Join of this Multiset to another Multiset where the Join is predicated on the given Expression
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <param name="expr">Expression</param>
        /// <returns></returns>
        public override BaseMultiset LeftJoin(BaseMultiset other, ISparqlExpression expr)
        {
            //If the Other is the Identity/Null Multiset the result is this Multiset
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(this);
            }
            if (other.IsEmpty)
            {
                return(this);
            }

            Multiset joinedSet                 = new Multiset();
            LeviathanLeftJoinBinder binder     = new LeviathanLeftJoinBinder(joinedSet);
            SparqlEvaluationContext subcontext = new SparqlEvaluationContext(binder);

            //Find the First Variable from this Multiset which is in both Multisets
            //If there is no Variable from this Multiset in the other Multiset then this
            //should be a Join operation instead of a LeftJoin
            List <String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                //Calculate a Product filtering as we go
                foreach (ISet x in this.Sets)
                {
                    bool standalone = false;
                    foreach (ISet y in other.Sets)
                    {
                        ISet z = x.Join(y);
                        try
                        {
                            joinedSet.Add(z);
                            if (!expr.EffectiveBooleanValue(subcontext, z.ID))
                            {
                                joinedSet.Remove(z.ID);
                                standalone = true;
                            }
                        }
                        catch
                        {
                            joinedSet.Remove(z.ID);
                            standalone = true;
                        }
                    }
                    if (standalone)
                    {
                        joinedSet.Add(x);
                    }
                }
            }
            else
            {
                foreach (ISet x in this.Sets)
                {
                    IEnumerable <ISet> ys = other.Sets.Where(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
                    //IEnumerable<ISet> ys = other.Sets.Where(s => s.IsCompatibleWith(x, joinVars));
                    bool standalone = false;
                    int  i          = 0;
                    foreach (ISet y in ys)
                    {
                        i++;
                        ISet z = x.Join(y);
                        try
                        {
                            joinedSet.Add(z);
                            if (!expr.EffectiveBooleanValue(subcontext, z.ID))
                            {
                                joinedSet.Remove(z.ID);
                                standalone = true;
                            }
                        }
                        catch
                        {
                            joinedSet.Remove(z.ID);
                            standalone = true;
                        }
                    }
                    if (standalone || i == 0)
                    {
                        joinedSet.Add(x);
                    }
                }
            }
            return(joinedSet);
        }
コード例 #12
0
        /// <summary>
        /// Does an Exists Join of this Multiset to another Multiset where the Join is predicated on the existence/non-existence of a joinable solution on the RHS
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <param name="mustExist">Whether a solution must exist in the Other Multiset for the join to be made</param>
        /// <returns></returns>
        public override BaseMultiset ExistsJoin(BaseMultiset other, bool mustExist)
        {
            //For EXISTS and NOT EXISTS if the other is the Identity then it has no effect
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (mustExist)
            {
                //If an EXISTS then Null/Empty Other results in Null
                if (other is NullMultiset)
                {
                    return(other);
                }
                if (other.IsEmpty)
                {
                    return(new NullMultiset());
                }
            }
            else
            {
                //If a NOT EXISTS then Null/Empty results in this
                if (other is NullMultiset)
                {
                    return(this);
                }
                if (other.IsEmpty)
                {
                    return(this);
                }
            }

            //Find the Variables that are to be used for Joining
            List <String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                //All Disjoint Solutions are compatible
                if (mustExist)
                {
                    //If an EXISTS and disjoint then result is this
                    return(this);
                }
                else
                {
                    //If a NOT EXISTS and disjoint then result is null
                    return(new NullMultiset());
                }
            }

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();

            foreach (ISet x in this.Sets)
            {
                //New ExistsJoin() logic based on the improved Join() logic
                bool exists = other.Sets.Any(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
                //bool exists = other.Sets.Any(s => s.IsCompatibleWith(x, joinVars));

                if (exists)
                {
                    //If there are compatible sets and this is an EXIST then preserve the solution
                    if (mustExist)
                    {
                        joinedSet.Add(x);
                    }
                }
                else
                {
                    //If there are no compatible sets and this is a NOT EXISTS then preserve the solution
                    if (!mustExist)
                    {
                        joinedSet.Add(x);
                    }
                }
            }
            return(joinedSet);
        }
コード例 #13
0
ファイル: Graph.cs プロジェクト: adamthe30/KADL-iet-2018
        /// <summary>
        /// Evaluates the Graph Clause by setting up the dataset, applying the pattern and then generating additional bindings if necessary
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            // Q: Can we optimise GRAPH when the input is the Null Multiset to just return the Null Multiset?

            bool datasetOk = false;

            try
            {
                List <String> activeGraphs = new List <string>();

                // Get the URIs of Graphs that should be evaluated over
                if (_graphSpecifier.TokenType != Token.VARIABLE)
                {
                    switch (_graphSpecifier.TokenType)
                    {
                    case Token.URI:
                    case Token.QNAME:
                        Uri activeGraphUri = UriFactory.Create(Tools.ResolveUriOrQName(_graphSpecifier, context.Query.NamespaceMap, context.Query.BaseUri));
                        if (context.Data.HasGraph(activeGraphUri))
                        {
                            // If the Graph is explicitly specified and there are FROM/FROM NAMED present then the Graph
                            // URI must be in the graphs specified by a FROM/FROM NAMED or the result is null
                            if (context.Query == null ||
                                ((!context.Query.DefaultGraphs.Any() && !context.Query.NamedGraphs.Any()) ||
                                 context.Query.NamedGraphs.Any(u => EqualityHelper.AreUrisEqual(activeGraphUri, u)))
                                )
                            {
                                // Either there was no Query
                                // OR there were no Default/Named Graphs (hence any Graph URI is permitted)
                                // OR the specified URI was a Named Graph URI
                                // In any case we can go ahead and set the active Graph
                                activeGraphs.Add(activeGraphUri.AbsoluteUri);
                            }
                            else
                            {
                                // The specified URI was not present in the Named Graphs so return null
                                context.OutputMultiset = new NullMultiset();
                                return(context.OutputMultiset);
                            }
                        }
                        else
                        {
                            // If specifies a specific Graph and not in the Dataset result is a null multiset
                            context.OutputMultiset = new NullMultiset();
                            return(context.OutputMultiset);
                        }
                        break;

                    default:
                        throw new RdfQueryException("Cannot use a '" + _graphSpecifier.GetType().ToString() + "' Token to specify the Graph for a GRAPH clause");
                    }
                }
                else
                {
                    String gvar = _graphSpecifier.Value.Substring(1);

                    // Watch out for the case in which the Graph Variable is not bound for all Sets in which case
                    // we still need to operate over all Graphs
                    if (context.InputMultiset.ContainsVariable(gvar) && context.InputMultiset.Sets.All(s => s[gvar] != null))
                    {
                        // If there are already values bound to the Graph variable for all Input Solutions then we limit the Query to those Graphs
                        List <Uri> graphUris = new List <Uri>();
                        foreach (ISet s in context.InputMultiset.Sets)
                        {
                            INode temp = s[gvar];
                            if (temp == null)
                            {
                                continue;
                            }
                            if (temp.NodeType != NodeType.Uri)
                            {
                                continue;
                            }
                            activeGraphs.Add(temp.ToString());
                            graphUris.Add(((IUriNode)temp).Uri);
                        }
                    }
                    else
                    {
                        // Nothing yet bound to the Graph Variable so the Query is over all the named Graphs
                        if (context.Query != null && context.Query.NamedGraphs.Any())
                        {
                            // Query specifies one/more named Graphs
                            activeGraphs.AddRange(context.Query.NamedGraphs.Select(u => u.AbsoluteUri));
                        }
                        else if (context.Query != null && context.Query.DefaultGraphs.Any() && !context.Query.NamedGraphs.Any())
                        {
                            // Gives null since the query dataset does not include any named graphs
                            context.OutputMultiset = new NullMultiset();
                            return(context.OutputMultiset);
                        }
                        else
                        {
                            // Query is over entire dataset/default Graph since no named Graphs are explicitly specified
                            activeGraphs.AddRange(context.Data.GraphUris.Select(u => u.ToSafeString()));
                        }
                    }
                }

                // Remove all duplicates from Active Graphs to avoid duplicate results
                activeGraphs = activeGraphs.Distinct().ToList();

                // Evaluate the inner pattern
                BaseMultiset initialInput = context.InputMultiset;
                BaseMultiset finalResult  = new Multiset();

                // Evalute for each Graph URI and union the results
                foreach (String uri in activeGraphs)
                {
                    // Always use the same Input for each Graph URI and set that Graph to be the Active Graph
                    // Be sure to translate String.Empty back to the null URI to select the default graph
                    // correctly
                    context.InputMultiset = initialInput;
                    Uri currGraphUri = (uri.Equals(String.Empty)) ? null : UriFactory.Create(uri);

                    // Set Active Graph
                    if (currGraphUri == null)
                    {
                        // GRAPH operates over named graphs only so default graph gets skipped
                        continue;
                    }
                    // The result of the HasGraph() call is ignored we just make it so datasets with any kind of
                    // load on demand behaviour work properly
                    context.Data.HasGraph(currGraphUri);
                    // All we actually care about is setting the active graph
                    context.Data.SetActiveGraph(currGraphUri);
                    datasetOk = true;

                    // Evaluate for the current Active Graph
                    BaseMultiset result = context.Evaluate(_pattern);

                    // Merge the Results into our overall Results
                    if (result is NullMultiset)
                    {
                        // Don't do anything, adds nothing to the results
                    }
                    else if (result is IdentityMultiset)
                    {
                        // Adds a single row to the results
                        if (_graphSpecifier.TokenType == Token.VARIABLE)
                        {
                            // Include graph variable if not yet bound
                            INode currGraph = new UriNode(null, currGraphUri);
                            Set   s         = new Set();
                            s.Add(_graphSpecifier.Value.Substring(1), currGraph);
                            finalResult.Add(s);
                        }
                        else
                        {
                            finalResult.Add(new Set());
                        }
                    }
                    else
                    {
                        // If the Graph Specifier is a Variable then we must either bind the
                        // variable or eliminate solutions which have an incorrect value for it
                        if (_graphSpecifier.TokenType == Token.VARIABLE)
                        {
                            String gvar      = _graphSpecifier.Value.Substring(1);
                            INode  currGraph = new UriNode(null, currGraphUri);
                            foreach (int id in result.SetIDs.ToList())
                            {
                                ISet s = result[id];
                                if (s[gvar] == null)
                                {
                                    // If Graph Variable is not yet bound for solution bind it
                                    s.Add(gvar, currGraph);
                                }
                                else if (!s[gvar].Equals(currGraph))
                                {
                                    // If Graph Variable is bound for solution and doesn't match
                                    // current Graph then we have to remove the solution
                                    result.Remove(id);
                                }
                            }
                        }
                        // Union solutions into the Results
                        finalResult.Union(result);
                    }

                    // Reset the Active Graph after each pass
                    context.Data.ResetActiveGraph();
                    datasetOk = false;
                }

                // Return the final result
                if (finalResult.IsEmpty)
                {
                    finalResult = new NullMultiset();
                }
                context.OutputMultiset = finalResult;
            }
            finally
            {
                if (datasetOk)
                {
                    context.Data.ResetActiveGraph();
                }
            }

            return(context.OutputMultiset);
        }
コード例 #14
0
        public void SparqlMultisetLeftJoin()
        {
            //Create a load of Nodes to use in the tests
            Graph g = new Graph();
            g.NamespaceMap.AddNamespace(String.Empty, new Uri("http://example.org"));
            IUriNode s1 = g.CreateUriNode(":s1");
            IUriNode s2 = g.CreateUriNode(":s2");
            IUriNode p1 = g.CreateUriNode(":p1");
            IUriNode p2 = g.CreateUriNode(":p2");
            IUriNode rdfsLabel = g.CreateUriNode("rdfs:label");
            ILiteralNode o1 = g.CreateLiteralNode("Some Text");
            ILiteralNode o2 = g.CreateLiteralNode("1", new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger));

            //Create an ID and Null Multiset
            IdentityMultiset id = new IdentityMultiset();
            NullMultiset nullset = new NullMultiset();

            //Create and Populate a Multiset
            Multiset m = new Multiset();
            Set s = new Set();
            s.Add("s", s1);
            s.Add("p", p1);
            s.Add("o", o1);
            m.Add(s);
            s = new Set();
            s.Add("s", s2);
            s.Add("p", p2);
            s.Add("o", o2);
            m.Add(s);

            //Create and Populate another Multiset
            Multiset n = new Multiset();
            s = new Set();
            s.Add("s", s1);
            s.Add("label", o1);
            n.Add(s);

            //Create and Populate another Multiset
            Multiset d = new Multiset();
            s = new Set();
            s.Add("s1", s1);
            s.Add("p1", p1);
            s.Add("o1", o1);
            d.Add(s);
            s = new Set();
            s.Add("s1", s2);
            s.Add("p1", p2);
            s.Add("o1", o2);
            d.Add(s);

            //Show the Sets
            Console.WriteLine("LHS");
            foreach (Set set in m.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();
            Console.WriteLine("RHS");
            foreach (Set set in n.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();
            Console.WriteLine("D");
            foreach (Set set in d.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Identity
            Console.WriteLine("Join ID-LHS");
            BaseMultiset join = id.Join(m);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Identity
            Console.WriteLine("Join LHS-ID");
            join = m.Join(id);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Null
            Console.WriteLine("Join NULL-LHS");
            join = nullset.Join(m);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Null
            Console.WriteLine("Join LHS-NULL");
            join = m.Join(nullset);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a LeftJoin
            Console.WriteLine("LeftJoin NULL-LHS");
            BaseMultiset leftjoin = nullset.LeftJoin(m, new BooleanExpressionTerm(true));
            foreach (Set set in leftjoin.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a LeftJoin
            Console.WriteLine("LeftJoin LHS-NULL");
            leftjoin = m.LeftJoin(nullset, new BooleanExpressionTerm(true));
            foreach (Set set in leftjoin.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join
            Console.WriteLine("Join LHS-RHS");
            join = m.Join(n);
            foreach (Set set in join.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();
           
            //Try a LeftOuterJoin
            Console.WriteLine("LeftJoin LHS-RHS");
            leftjoin = m.LeftJoin(n, new BooleanExpressionTerm(true));
            foreach (Set set in leftjoin.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Produce
            Console.WriteLine("Product LHS-RHS");
            BaseMultiset product = m.Product(n);
            foreach (Set set in product.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Join to Self
            Console.WriteLine("Product LHS-D");
            product = m.Product(d);
            foreach (Set set in product.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();

            //Try a Union
            Console.WriteLine("Union LHS-RHS");
            BaseMultiset union = m.Union(n);
            foreach (Set set in union.Sets)
            {
                Console.WriteLine(set.ToString());
            }
            Console.WriteLine();
        }
コード例 #15
0
ファイル: Multiset.cs プロジェクト: jmahmud/RDFer
        /// <summary>
        /// Does a Product of this Multiset and another Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset Product(BaseMultiset other)
        {
            if (other is IdentityMultiset) return this;
            if (other is NullMultiset) return other;
            if (other.IsEmpty) return new NullMultiset();

            Multiset productSet = new Multiset();
            foreach (ISet x in this.Sets)
            {
                foreach (ISet y in other.Sets)
                {
                    productSet.Add(x.Join(y));
                }
            }
            return productSet;
        }
コード例 #16
0
ファイル: Multiset.cs プロジェクト: jmahmud/RDFer
        /// <summary>
        /// Does a Left Join of this Multiset to another Multiset where the Join is predicated on the given Expression
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <param name="expr">Expression</param>
        /// <returns></returns>
        public override BaseMultiset LeftJoin(BaseMultiset other, ISparqlExpression expr)
        {
            //If the Other is the Identity/Null Multiset the result is this Multiset
            if (other is IdentityMultiset) return this;
            if (other is NullMultiset) return this;
            if (other.IsEmpty) return this;

            Multiset joinedSet = new Multiset();
            LeviathanLeftJoinBinder binder = new LeviathanLeftJoinBinder(joinedSet);
            SparqlEvaluationContext subcontext = new SparqlEvaluationContext(binder);

            //Find the First Variable from this Multiset which is in both Multisets
            //If there is no Variable from this Multiset in the other Multiset then this
            //should be a Join operation instead of a LeftJoin
            List<String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();
            if (joinVars.Count == 0)
            {
                //Calculate a Product filtering as we go
                foreach (ISet x in this.Sets)
                {
                    bool standalone = false;
                    foreach (ISet y in other.Sets)
                    {
                        ISet z = x.Join(y);
                        try
                        {
                            joinedSet.Add(z);
                            if (!expr.Evaluate(subcontext, z.ID).AsSafeBoolean())
                            {
                                joinedSet.Remove(z.ID);
                                standalone = true;
                            }
                        }
                        catch
                        {
                            joinedSet.Remove(z.ID);
                            standalone = true;
                        }
                    }
                    if (standalone) joinedSet.Add(x.Copy());
                }
            }
            else
            {
                //This is the old algorithm which is correct but has complexity O(n^2) so it scales terribly
                //foreach (ISet x in this.Sets)
                //{
                //    IEnumerable<ISet> ys = other.Sets.Where(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
                //    //IEnumerable<ISet> ys = other.Sets.Where(s => s.IsCompatibleWith(x, joinVars));
                //    bool standalone = false;
                //    int i = 0;
                //    foreach (ISet y in ys)
                //    {
                //        i++;
                //        ISet z = x.Join(y);
                //        try
                //        {
                //            joinedSet.Add(z);
                //            if (!expr.Evaluate(subcontext, z.ID).AsSafeBoolean())
                //            {
                //                joinedSet.Remove(z.ID);
                //                standalone = true;
                //            }
                //        }
                //        catch
                //        {
                //            joinedSet.Remove(z.ID);
                //            standalone = true;
                //        }
                //    }
                //    if (standalone || i == 0) joinedSet.Add(x);
                //}

                //This is the new Join algorithm which is also correct but is O(2n) so much faster and scalable
                //Downside is that it does require more memory than the old algorithm
                List<HashTable<INode, int>> values = new List<HashTable<INode, int>>();
                List<List<int>> nulls = new List<List<int>>();
                foreach (String var in joinVars)
                {
                    values.Add(new HashTable<INode, int>(HashTableBias.Enumeration));
                    nulls.Add(new List<int>());
                }

                //First do a pass over the LHS Result to find all possible values for joined variables
                HashSet<int> matched = new HashSet<int>();
                HashSet<int> standalone = new HashSet<int>();
                foreach (ISet x in this.Sets)
                {
                    int i = 0;
                    foreach (String var in joinVars)
                    {
                        INode value = x[var];
                        if (value != null)
                        {
                            values[i].Add(value, x.ID);
                        }
                        else
                        {
                            nulls[i].Add(x.ID);
                        }
                        i++;
                    }
                }

                //Then do a pass over the RHS and work out the intersections
                foreach (ISet y in other.Sets)
                {
                    IEnumerable<int> possMatches = null;
                    int i = 0;
                    foreach (String var in joinVars)
                    {
                        INode value = y[var];
                        if (value != null)
                        {
                            if (values[i].ContainsKey(value))
                            {
                                possMatches = (possMatches == null ? values[i].GetValues(value).Concat(nulls[i]) : possMatches.Intersect(values[i].GetValues(value).Concat(nulls[i])));
                            }
                            else
                            {
                                possMatches = Enumerable.Empty<int>();
                                break;
                            }
                        }
                        else
                        {
                            //Don't forget that a null will be potentially compatible with everything
                            possMatches = (possMatches == null ? this.SetIDs : possMatches.Intersect(this.SetIDs));
                        }
                        i++;
                    }
                    if (possMatches == null) continue;

                    //Now do the actual joins for the current set
                    //Note - We access the dictionary directly here because going through the this[int id] method
                    //incurs a Contains() call each time and we know the IDs must exist because they came from
                    //our dictionary originally!
                    foreach (int poss in possMatches)
                    {
                        if (this._sets[poss].IsCompatibleWith(y, joinVars))
                        {
                            ISet z = this._sets[poss].Join(y);
                            joinedSet.Add(z);
                            try
                            {
                                if (!expr.Evaluate(subcontext, z.ID).AsSafeBoolean())
                                {
                                    joinedSet.Remove(z.ID);
                                    standalone.Add(poss);
                                }
                                else
                                {
                                    matched.Add(poss);
                                }
                            }
                            catch
                            {
                                joinedSet.Remove(z.ID);
                                standalone.Add(poss);
                            }
                        }
                    }
                }

                //Finally add in unmatched sets from LHS
                foreach (int id in this.SetIDs)
                {
                    if (!matched.Contains(id) || standalone.Contains(id)) joinedSet.Add(this._sets[id].Copy());
                }
            }
            return joinedSet;
        }
コード例 #17
0
 public virtual BaseMultiset GetMultiset(IStore store)
 {
     var ms = new Multiset(Columns);
     foreach (var row in Rows)
     {
         var set = new Set();
         for (int i = 0; i < Columns.Count; i++)
         {
             if (row[i] > 0)
             {
                 set.Add(Columns[i], MakeNode(store, row[i]));
             }
         }
         ms.Add(set);
     }
     return ms;
 }
コード例 #18
0
        /// <summary>
        /// Does a Left Join of this Multiset to another Multiset where the Join is predicated on the given Expression
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <param name="expr">Expression</param>
        /// <returns></returns>
        public override BaseMultiset LeftJoin(BaseMultiset other, ISparqlExpression expr)
        {
            //If the Other is the Identity/Null Multiset the result is this Multiset
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(this);
            }
            if (other.IsEmpty)
            {
                return(this);
            }

            Multiset joinedSet                 = new Multiset();
            LeviathanLeftJoinBinder binder     = new LeviathanLeftJoinBinder(joinedSet);
            SparqlEvaluationContext subcontext = new SparqlEvaluationContext(binder);

            //Find the First Variable from this Multiset which is in both Multisets
            //If there is no Variable from this Multiset in the other Multiset then this
            //should be a Join operation instead of a LeftJoin
            List <String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                //Calculate a Product filtering as we go
                foreach (ISet x in this.Sets)
                {
                    bool standalone = false;
                    foreach (ISet y in other.Sets)
                    {
                        ISet z = x.Join(y);
                        try
                        {
                            joinedSet.Add(z);
                            if (!expr.Evaluate(subcontext, z.ID).AsSafeBoolean())
                            {
                                joinedSet.Remove(z.ID);
                                standalone = true;
                            }
                        }
                        catch
                        {
                            joinedSet.Remove(z.ID);
                            standalone = true;
                        }
                    }
                    if (standalone)
                    {
                        joinedSet.Add(x.Copy());
                    }
                }
            }
            else
            {
                //This is the old algorithm which is correct but has complexity O(n^2) so it scales terribly
                //foreach (ISet x in this.Sets)
                //{
                //    IEnumerable<ISet> ys = other.Sets.Where(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
                //    //IEnumerable<ISet> ys = other.Sets.Where(s => s.IsCompatibleWith(x, joinVars));
                //    bool standalone = false;
                //    int i = 0;
                //    foreach (ISet y in ys)
                //    {
                //        i++;
                //        ISet z = x.Join(y);
                //        try
                //        {
                //            joinedSet.Add(z);
                //            if (!expr.Evaluate(subcontext, z.ID).AsSafeBoolean())
                //            {
                //                joinedSet.Remove(z.ID);
                //                standalone = true;
                //            }
                //        }
                //        catch
                //        {
                //            joinedSet.Remove(z.ID);
                //            standalone = true;
                //        }
                //    }
                //    if (standalone || i == 0) joinedSet.Add(x);
                //}

                //This is the new Join algorithm which is also correct but is O(2n) so much faster and scalable
                //Downside is that it does require more memory than the old algorithm
                List <HashTable <INode, int> > values = new List <HashTable <INode, int> >();
                List <List <int> >             nulls  = new List <List <int> >();
                foreach (String var in joinVars)
                {
                    values.Add(new HashTable <INode, int>(HashTableBias.Enumeration));
                    nulls.Add(new List <int>());
                }

                //First do a pass over the LHS Result to find all possible values for joined variables
                HashSet <int> matched    = new HashSet <int>();
                HashSet <int> standalone = new HashSet <int>();
                foreach (ISet x in this.Sets)
                {
                    int i = 0;
                    foreach (String var in joinVars)
                    {
                        INode value = x[var];
                        if (value != null)
                        {
                            values[i].Add(value, x.ID);
                        }
                        else
                        {
                            nulls[i].Add(x.ID);
                        }
                        i++;
                    }
                }

                //Then do a pass over the RHS and work out the intersections
                foreach (ISet y in other.Sets)
                {
                    IEnumerable <int> possMatches = null;
                    int i = 0;
                    foreach (String var in joinVars)
                    {
                        INode value = y[var];
                        if (value != null)
                        {
                            if (values[i].ContainsKey(value))
                            {
                                possMatches = (possMatches == null ? values[i].GetValues(value).Concat(nulls[i]) : possMatches.Intersect(values[i].GetValues(value).Concat(nulls[i])));
                            }
                            else
                            {
                                possMatches = Enumerable.Empty <int>();
                                break;
                            }
                        }
                        else
                        {
                            //Don't forget that a null will be potentially compatible with everything
                            possMatches = (possMatches == null ? this.SetIDs : possMatches.Intersect(this.SetIDs));
                        }
                        i++;
                    }
                    if (possMatches == null)
                    {
                        continue;
                    }

                    //Now do the actual joins for the current set
                    //Note - We access the dictionary directly here because going through the this[int id] method
                    //incurs a Contains() call each time and we know the IDs must exist because they came from
                    //our dictionary originally!
                    foreach (int poss in possMatches)
                    {
                        if (this._sets[poss].IsCompatibleWith(y, joinVars))
                        {
                            ISet z = this._sets[poss].Join(y);
                            joinedSet.Add(z);
                            try
                            {
                                if (!expr.Evaluate(subcontext, z.ID).AsSafeBoolean())
                                {
                                    joinedSet.Remove(z.ID);
                                    standalone.Add(poss);
                                }
                                else
                                {
                                    matched.Add(poss);
                                }
                            }
                            catch
                            {
                                joinedSet.Remove(z.ID);
                                standalone.Add(poss);
                            }
                        }
                    }
                }

                //Finally add in unmatched sets from LHS
                foreach (int id in this.SetIDs)
                {
                    if (!matched.Contains(id) || standalone.Contains(id))
                    {
                        joinedSet.Add(this._sets[id].Copy());
                    }
                }
            }
            return(joinedSet);
        }
コード例 #19
0
        /// <summary>
        /// Does a Minus Join of this Multiset to another Multiset where any joinable results are subtracted from this Multiset to give the resulting Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset MinusJoin(BaseMultiset other)
        {
            //If the other Multiset is the Identity/Null Multiset then minus-ing it doesn't alter this set
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(this);
            }
            //If the other Multiset is disjoint then minus-ing it also doesn't alter this set
            if (this.IsDisjointWith(other))
            {
                return(this);
            }

            //Find the Variables that are to be used for Joining
            List <String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                return(this.Product(other));
            }

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();

            //This is the old algorithm which is correct but naive and has O(n^2) complexity
            //foreach (ISet x in this.Sets)
            //{
            //    //New Minus logic based on the improved Join() logic
            //    bool minus = other.Sets.Any(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));

            //    //If no compatible sets then this set is preserved
            //    if (!minus)
            //    {
            //        joinedSet.Add(x);
            //    }
            //}

            //This is the new algorithm which is also correct but is O(3n) so much faster and scalable
            //Downside is that it does require more memory than the old algorithm
            List <HashTable <INode, int> > values = new List <HashTable <INode, int> >();
            List <List <int> >             nulls  = new List <List <int> >();

            foreach (String var in joinVars)
            {
                values.Add(new HashTable <INode, int>(HashTableBias.Enumeration));
                nulls.Add(new List <int>());
            }

            //First do a pass over the LHS Result to find all possible values for joined variables
            foreach (ISet x in this.Sets)
            {
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = x[var];
                    if (value != null)
                    {
                        values[i].Add(value, x.ID);
                    }
                    else
                    {
                        nulls[i].Add(x.ID);
                    }
                    i++;
                }
            }

            //Then do a pass over the RHS and work out the intersections
            HashSet <int> toMinus = new HashSet <int>();

            foreach (ISet y in other.Sets)
            {
                IEnumerable <int> possMatches = null;
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = y[var];
                    if (value != null)
                    {
                        if (values[i].ContainsKey(value))
                        {
                            possMatches = (possMatches == null ? values[i].GetValues(value).Concat(nulls[i]) : possMatches.Intersect(values[i].GetValues(value).Concat(nulls[i])));
                        }
                        else
                        {
                            possMatches = Enumerable.Empty <int>();
                            break;
                        }
                    }
                    else
                    {
                        //Don't forget that a null will be potentially compatible with everything
                        possMatches = (possMatches == null ? this.SetIDs : possMatches.Intersect(this.SetIDs));
                    }
                    i++;
                }
                if (possMatches == null)
                {
                    continue;
                }

                //Look at possible matches, if is a valid match then mark the matched set for minus'ing
                //Don't reconsider sets which have already been marked for minusing
                foreach (int poss in possMatches)
                {
                    if (toMinus.Contains(poss))
                    {
                        continue;
                    }
                    if (this._sets[poss].IsCompatibleWith(y, joinVars))
                    {
                        toMinus.Add(poss);
                    }
                }
            }

            //Apply the actual minus
            if (toMinus.Count == this.Count)
            {
                //If number of sets to minus is equal to number of sets then we're minusing everything
                return(new NullMultiset());
            }
            else
            {
                //Otherwise iterate
                foreach (ISet x in this.Sets)
                {
                    if (!toMinus.Contains(x.ID))
                    {
                        joinedSet.Add(x.Copy());
                    }
                }
            }

            return(joinedSet);
        }
コード例 #20
0
        /// <summary>
        /// Does an Exists Join of this Multiset to another Multiset where the Join is predicated on the existence/non-existence of a joinable solution on the RHS
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <param name="mustExist">Whether a solution must exist in the Other Multiset for the join to be made</param>
        /// <returns></returns>
        public override BaseMultiset ExistsJoin(BaseMultiset other, bool mustExist)
        {
            //For EXISTS and NOT EXISTS if the other is the Identity then it has no effect
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (mustExist)
            {
                //If an EXISTS then Null/Empty Other results in Null
                if (other is NullMultiset)
                {
                    return(other);
                }
                if (other.IsEmpty)
                {
                    return(new NullMultiset());
                }
            }
            else
            {
                //If a NOT EXISTS then Null/Empty results in this
                if (other is NullMultiset)
                {
                    return(this);
                }
                if (other.IsEmpty)
                {
                    return(this);
                }
            }

            //Find the Variables that are to be used for Joining
            List <String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                //All Disjoint Solutions are compatible
                if (mustExist)
                {
                    //If an EXISTS and disjoint then result is this
                    return(this);
                }
                else
                {
                    //If a NOT EXISTS and disjoint then result is null
                    return(new NullMultiset());
                }
            }

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();

            //This is the old algorithm which is correct but naive with worse case O(n^2)
            //foreach (ISet x in this.Sets)
            //{
            //    //New ExistsJoin() logic based on the improved Join() logic
            //    bool exists = other.Sets.Any(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
            //    //bool exists = other.Sets.Any(s => s.IsCompatibleWith(x, joinVars));

            //    if (exists)
            //    {
            //        //If there are compatible sets and this is an EXIST then preserve the solution
            //        if (mustExist) joinedSet.Add(x);
            //    }
            //    else
            //    {
            //        //If there are no compatible sets and this is a NOT EXISTS then preserve the solution
            //        if (!mustExist) joinedSet.Add(x);
            //    }
            //}

            //This is the new algorithm which is also correct but is O(3n) so much faster and scalable
            //Downside is that it does require more memory than the old algorithm
            List <HashTable <INode, int> > values = new List <HashTable <INode, int> >();
            List <List <int> >             nulls  = new List <List <int> >();

            foreach (String var in joinVars)
            {
                values.Add(new HashTable <INode, int>(HashTableBias.Enumeration));
                nulls.Add(new List <int>());
            }

            //First do a pass over the LHS Result to find all possible values for joined variables
            foreach (ISet x in this.Sets)
            {
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = x[var];
                    if (value != null)
                    {
                        values[i].Add(value, x.ID);
                    }
                    else
                    {
                        nulls[i].Add(x.ID);
                    }
                    i++;
                }
            }

            //Then do a pass over the RHS and work out the intersections
            HashSet <int> exists = new HashSet <int>();

            foreach (ISet y in other.Sets)
            {
                IEnumerable <int> possMatches = null;
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = y[var];
                    if (value != null)
                    {
                        if (values[i].ContainsKey(value))
                        {
                            possMatches = (possMatches == null ? values[i].GetValues(value).Concat(nulls[i]) : possMatches.Intersect(values[i].GetValues(value).Concat(nulls[i])));
                        }
                        else
                        {
                            possMatches = Enumerable.Empty <int>();
                            break;
                        }
                    }
                    else
                    {
                        //Don't forget that a null will be potentially compatible with everything
                        possMatches = (possMatches == null ? this.SetIDs : possMatches.Intersect(this.SetIDs));
                    }
                    i++;
                }
                if (possMatches == null)
                {
                    continue;
                }

                //Look at possible matches, if is a valid match then mark the set as having an existing match
                //Don't reconsider sets which have already been marked as having an existing match
                foreach (int poss in possMatches)
                {
                    if (exists.Contains(poss))
                    {
                        continue;
                    }
                    if (this._sets[poss].IsCompatibleWith(y, joinVars))
                    {
                        exists.Add(poss);
                    }
                }
            }

            //Apply the actual exists
            if (exists.Count == this.Count)
            {
                //If number of sets that have a match is equal to number of sets then we're either returning everything or nothing
                if (mustExist)
                {
                    return(this);
                }
                else
                {
                    return(new NullMultiset());
                }
            }
            else
            {
                //Otherwise iterate
                foreach (ISet x in this.Sets)
                {
                    if (mustExist)
                    {
                        if (exists.Contains(x.ID))
                        {
                            joinedSet.Add(x.Copy());
                        }
                    }
                    else
                    {
                        if (!exists.Contains(x.ID))
                        {
                            joinedSet.Add(x.Copy());
                        }
                    }
                }
            }

            return(joinedSet);
        }
コード例 #21
0
        /// <summary>
        /// Evaluates the filtered product
        /// </summary>
        /// <param name="context">Evaluation Context</param>
        /// <returns></returns>
        public BaseMultiset Evaluate(SparqlEvaluationContext context)
        {
            BaseMultiset initialInput = context.InputMultiset;
            BaseMultiset lhsResults   = context.Evaluate(this._lhs);

            if (lhsResults is NullMultiset || lhsResults.IsEmpty)
            {
                //If LHS Results are Null/Empty then end result will always be null so short circuit
                context.OutputMultiset = new NullMultiset();
            }
            else
            {
                context.InputMultiset = initialInput;
                BaseMultiset rhsResults = context.Evaluate(this._rhs);
                if (rhsResults is NullMultiset || rhsResults.IsEmpty)
                {
                    //If RHS Results are Null/Empty then end results will always be null so short circuit
                    context.OutputMultiset = new NullMultiset();
                }
                else if (rhsResults is IdentityMultiset)
                {
                    //Apply Filter over LHS Results only - defer evaluation to filter implementation
                    context.InputMultiset = lhsResults;
                    UnaryExpressionFilter filter = new UnaryExpressionFilter(this._expr);
                    filter.Evaluate(context);
                    context.OutputMultiset = lhsResults;
                }
                else
                {
                    //Calculate the product applying the filter as we go
#if NET40 && !SILVERLIGHT
                    if (Options.UsePLinqEvaluation && this._expr.CanParallelise)
                    {
                        PartitionedMultiset partitionedSet;
                        SparqlResultBinder  binder = context.Binder;
                        if (lhsResults.Count >= rhsResults.Count)
                        {
                            partitionedSet = new PartitionedMultiset(lhsResults.Count, rhsResults.Count);
                            context.Binder = new LeviathanLeftJoinBinder(partitionedSet);
                            lhsResults.Sets.AsParallel().ForAll(x => this.EvalFilteredProduct(context, x, rhsResults, partitionedSet));
                        }
                        else
                        {
                            partitionedSet = new PartitionedMultiset(rhsResults.Count, lhsResults.Count);
                            context.Binder = new LeviathanLeftJoinBinder(partitionedSet);
                            rhsResults.Sets.AsParallel().ForAll(y => this.EvalFilteredProduct(context, y, lhsResults, partitionedSet));
                        }

                        context.Binder         = binder;
                        context.OutputMultiset = partitionedSet;
                    }
                    else
                    {
#endif
                    BaseMultiset productSet   = new Multiset();
                    SparqlResultBinder binder = context.Binder;
                    context.Binder = new LeviathanLeftJoinBinder(productSet);
                    foreach (ISet x in lhsResults.Sets)
                    {
                        foreach (ISet y in rhsResults.Sets)
                        {
                            ISet z = x.Join(y);
                            productSet.Add(z);
                            try
                            {
                                if (!this._expr.Evaluate(context, z.ID).AsSafeBoolean())
                                {
                                    //Means the expression evaluates to false so we discard the solution
                                    productSet.Remove(z.ID);
                                }
                            }
                            catch
                            {
                                //Means this solution does not meet the FILTER and can be discarded
                                productSet.Remove(z.ID);
                            }
                        }
                        //Remember to check for timeouts occassionaly
                        context.CheckTimeout();
                    }
                    context.Binder         = binder;
                    context.OutputMultiset = productSet;
#if NET40 && !SILVERLIGHT
                }
#endif
                }
            }
            return(context.OutputMultiset);
        }
コード例 #22
0
ファイル: Multiset.cs プロジェクト: jbunzel/MvcRQ_git
        /// <summary>
        /// Does a Left Join of this Multiset to another Multiset where the Join is predicated on the given Expression
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <param name="expr">Expression</param>
        /// <returns></returns>
        public override BaseMultiset LeftJoin(BaseMultiset other, ISparqlExpression expr)
        {
            //If the Other is the Identity/Null Multiset the result is this Multiset
            if (other is IdentityMultiset) return this;
            if (other is NullMultiset) return this;
            if (other.IsEmpty) return this;

            Multiset joinedSet = new Multiset();
            LeviathanLeftJoinBinder binder = new LeviathanLeftJoinBinder(joinedSet);
            SparqlEvaluationContext subcontext = new SparqlEvaluationContext(binder);

            //Find the First Variable from this Multiset which is in both Multisets
            //If there is no Variable from this Multiset in the other Multiset then this
            //should be a Join operation instead of a LeftJoin
            List<String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();
            if (joinVars.Count == 0)
            {
                //Calculate a Product filtering as we go
                foreach (ISet x in this.Sets)
                {
                    bool standalone = false;
                    foreach (ISet y in other.Sets)
                    {
                        ISet z = x.Join(y);
                        try
                        {
                            joinedSet.Add(z);
                            if (!expr.EffectiveBooleanValue(subcontext, z.ID))
                            {
                                joinedSet.Remove(z.ID);
                                standalone = true;
                            }
                        }
                        catch
                        {
                            joinedSet.Remove(z.ID);
                            standalone = true;
                        }
                    }
                    if (standalone) joinedSet.Add(x);
                }
            }
            else
            {
                foreach (ISet x in this.Sets)
                {
                    IEnumerable<ISet> ys = other.Sets.Where(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
                    //IEnumerable<ISet> ys = other.Sets.Where(s => s.IsCompatibleWith(x, joinVars));
                    bool standalone = false;
                    int i = 0;
                    foreach (ISet y in ys)
                    {
                        i++;
                        ISet z = x.Join(y);
                        try
                        {
                            joinedSet.Add(z);
                            if (!expr.EffectiveBooleanValue(subcontext, z.ID))
                            {
                                joinedSet.Remove(z.ID);
                                standalone = true;
                            }
                        }
                        catch
                        {
                            joinedSet.Remove(z.ID);
                            standalone = true;
                        }
                    }
                    if (standalone || i == 0) joinedSet.Add(x);
                }
            }
            return joinedSet;
        }
コード例 #23
0
ファイル: Multiset.cs プロジェクト: jmahmud/RDFer
        /// <summary>
        /// Does an Exists Join of this Multiset to another Multiset where the Join is predicated on the existence/non-existence of a joinable solution on the RHS
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <param name="mustExist">Whether a solution must exist in the Other Multiset for the join to be made</param>
        /// <returns></returns>
        public override BaseMultiset ExistsJoin(BaseMultiset other, bool mustExist)
        {
            //For EXISTS and NOT EXISTS if the other is the Identity then it has no effect
            if (other is IdentityMultiset) return this;
            if (mustExist)
            {
                //If an EXISTS then Null/Empty Other results in Null
                if (other is NullMultiset) return other;
                if (other.IsEmpty) return new NullMultiset();
            }
            else
            {
                //If a NOT EXISTS then Null/Empty results in this
                if (other is NullMultiset) return this;
                if (other.IsEmpty) return this;
            }

            //Find the Variables that are to be used for Joining
            List<String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();
            if (joinVars.Count == 0)
            {
                //All Disjoint Solutions are compatible
                if (mustExist)
                {
                    //If an EXISTS and disjoint then result is this
                    return this;
                }
                else
                {
                    //If a NOT EXISTS and disjoint then result is null
                    return new NullMultiset();
                }
            }

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();

            //This is the old algorithm which is correct but naive with worse case O(n^2)
            //foreach (ISet x in this.Sets)
            //{
            //    //New ExistsJoin() logic based on the improved Join() logic
            //    bool exists = other.Sets.Any(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
            //    //bool exists = other.Sets.Any(s => s.IsCompatibleWith(x, joinVars));

            //    if (exists)
            //    {
            //        //If there are compatible sets and this is an EXIST then preserve the solution
            //        if (mustExist) joinedSet.Add(x);
            //    }
            //    else
            //    {
            //        //If there are no compatible sets and this is a NOT EXISTS then preserve the solution
            //        if (!mustExist) joinedSet.Add(x);
            //    }
            //}

            //This is the new algorithm which is also correct but is O(3n) so much faster and scalable
            //Downside is that it does require more memory than the old algorithm
            List<HashTable<INode, int>> values = new List<HashTable<INode, int>>();
            List<List<int>> nulls = new List<List<int>>();
            foreach (String var in joinVars)
            {
                values.Add(new HashTable<INode, int>(HashTableBias.Enumeration));
                nulls.Add(new List<int>());
            }

            //First do a pass over the LHS Result to find all possible values for joined variables
            foreach (ISet x in this.Sets)
            {
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = x[var];
                    if (value != null)
                    {
                        values[i].Add(value, x.ID);
                    }
                    else
                    {
                        nulls[i].Add(x.ID);
                    }
                    i++;
                }
            }

            //Then do a pass over the RHS and work out the intersections
            HashSet<int> exists = new HashSet<int>();
            foreach (ISet y in other.Sets)
            {
                IEnumerable<int> possMatches = null;
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = y[var];
                    if (value != null)
                    {
                        if (values[i].ContainsKey(value))
                        {
                            possMatches = (possMatches == null ? values[i].GetValues(value).Concat(nulls[i]) : possMatches.Intersect(values[i].GetValues(value).Concat(nulls[i])));
                        }
                        else
                        {
                            possMatches = Enumerable.Empty<int>();
                            break;
                        }
                    }
                    else
                    {
                        //Don't forget that a null will be potentially compatible with everything
                        possMatches = (possMatches == null ? this.SetIDs : possMatches.Intersect(this.SetIDs));
                    }
                    i++;
                }
                if (possMatches == null) continue;

                //Look at possible matches, if is a valid match then mark the set as having an existing match
                //Don't reconsider sets which have already been marked as having an existing match
                foreach (int poss in possMatches)
                {
                    if (exists.Contains(poss)) continue;
                    if (this._sets[poss].IsCompatibleWith(y, joinVars))
                    {
                        exists.Add(poss);
                    }
                }
            }

            //Apply the actual exists
            if (exists.Count == this.Count)
            {
                //If number of sets that have a match is equal to number of sets then we're either returning everything or nothing
                if (mustExist)
                {
                    return this;
                }
                else
                {
                    return new NullMultiset();
                }
            }
            else
            {
                //Otherwise iterate
                foreach (ISet x in this.Sets)
                {
                    if (mustExist)
                    {
                        if (exists.Contains(x.ID))
                        {
                            joinedSet.Add(x.Copy());
                        }
                    }
                    else
                    {
                        if (!exists.Contains(x.ID))
                        {
                            joinedSet.Add(x.Copy());
                        }
                    }
                }
            }

            return joinedSet;
        }
コード例 #24
0
ファイル: Multiset.cs プロジェクト: jbunzel/MvcRQ_git
        /// <summary>
        /// Does an Exists Join of this Multiset to another Multiset where the Join is predicated on the existence/non-existence of a joinable solution on the RHS
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <param name="mustExist">Whether a solution must exist in the Other Multiset for the join to be made</param>
        /// <returns></returns>
        public override BaseMultiset ExistsJoin(BaseMultiset other, bool mustExist)
        {
            //For EXISTS and NOT EXISTS if the other is the Identity then it has no effect
            if (other is IdentityMultiset) return this;
            if (mustExist)
            {
                //If an EXISTS then Null/Empty Other results in Null
                if (other is NullMultiset) return other;
                if (other.IsEmpty) return new NullMultiset();
            }
            else
            {
                //If a NOT EXISTS then Null/Empty results in this
                if (other is NullMultiset) return this;
                if (other.IsEmpty) return this;
            }

            //Find the Variables that are to be used for Joining
            List<String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();
            if (joinVars.Count == 0)
            {
                //All Disjoint Solutions are compatible
                if (mustExist)
                {
                    //If an EXISTS and disjoint then result is this
                    return this;
                }
                else
                {
                    //If a NOT EXISTS and disjoint then result is null
                    return new NullMultiset();
                }
            }

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();
            foreach (ISet x in this.Sets)
            {
                //New ExistsJoin() logic based on the improved Join() logic
                bool exists = other.Sets.Any(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));
                //bool exists = other.Sets.Any(s => s.IsCompatibleWith(x, joinVars));

                if (exists)
                {
                    //If there are compatible sets and this is an EXIST then preserve the solution
                    if (mustExist) joinedSet.Add(x);
                }
                else
                {
                    //If there are no compatible sets and this is a NOT EXISTS then preserve the solution
                    if (!mustExist) joinedSet.Add(x);
                }
            }
            return joinedSet;
        }
コード例 #25
0
ファイル: Multiset.cs プロジェクト: jmahmud/RDFer
        /// <summary>
        /// Does a Minus Join of this Multiset to another Multiset where any joinable results are subtracted from this Multiset to give the resulting Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset MinusJoin(BaseMultiset other)
        {
            //If the other Multiset is the Identity/Null Multiset then minus-ing it doesn't alter this set
            if (other is IdentityMultiset) return this;
            if (other is NullMultiset) return this;
            //If the other Multiset is disjoint then minus-ing it also doesn't alter this set
            if (this.IsDisjointWith(other)) return this;

            //Find the Variables that are to be used for Joining
            List<String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();
            if (joinVars.Count == 0) return this.Product(other);

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();

            //This is the old algorithm which is correct but naive and has O(n^2) complexity
            //foreach (ISet x in this.Sets)
            //{
            //    //New Minus logic based on the improved Join() logic
            //    bool minus = other.Sets.Any(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));

            //    //If no compatible sets then this set is preserved
            //    if (!minus)
            //    {
            //        joinedSet.Add(x);
            //    }
            //}

            //This is the new algorithm which is also correct but is O(3n) so much faster and scalable
            //Downside is that it does require more memory than the old algorithm
            List<HashTable<INode, int>> values = new List<HashTable<INode, int>>();
            List<List<int>> nulls = new List<List<int>>();
            foreach (String var in joinVars)
            {
                values.Add(new HashTable<INode, int>(HashTableBias.Enumeration));
                nulls.Add(new List<int>());
            }

            //First do a pass over the LHS Result to find all possible values for joined variables
            foreach (ISet x in this.Sets)
            {
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = x[var];
                    if (value != null)
                    {
                        values[i].Add(value, x.ID);
                    }
                    else
                    {
                        nulls[i].Add(x.ID);
                    }
                    i++;
                }
            }

            //Then do a pass over the RHS and work out the intersections
            HashSet<int> toMinus = new HashSet<int>();
            foreach (ISet y in other.Sets)
            {
                IEnumerable<int> possMatches = null;
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = y[var];
                    if (value != null)
                    {
                        if (values[i].ContainsKey(value))
                        {
                            possMatches = (possMatches == null ? values[i].GetValues(value).Concat(nulls[i]) : possMatches.Intersect(values[i].GetValues(value).Concat(nulls[i])));
                        }
                        else
                        {
                            possMatches = Enumerable.Empty<int>();
                            break;
                        }
                    }
                    else
                    {
                        //Don't forget that a null will be potentially compatible with everything
                        possMatches = (possMatches == null ? this.SetIDs : possMatches.Intersect(this.SetIDs));
                    }
                    i++;
                }
                if (possMatches == null) continue;

                //Look at possible matches, if is a valid match then mark the matched set for minus'ing
                //Don't reconsider sets which have already been marked for minusing
                foreach (int poss in possMatches)
                {
                    if (toMinus.Contains(poss)) continue;
                    if (this._sets[poss].IsCompatibleWith(y, joinVars))
                    {
                        toMinus.Add(poss);
                    }
                }
            }

            //Apply the actual minus
            if (toMinus.Count == this.Count)
            {
                //If number of sets to minus is equal to number of sets then we're minusing everything
                return new NullMultiset();
            }
            else
            {
                //Otherwise iterate
                foreach (ISet x in this.Sets)
                {
                    if (!toMinus.Contains(x.ID))
                    {
                        joinedSet.Add(x.Copy());
                    }
                }
            }

            return joinedSet;
        }
コード例 #26
0
ファイル: Multiset.cs プロジェクト: jbunzel/MvcRQ_git
        /// <summary>
        /// Does a Minus Join of this Multiset to another Multiset where any joinable results are subtracted from this Multiset to give the resulting Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset MinusJoin(BaseMultiset other)
        {
            //If the other Multiset is the Identity/Null Multiset then minus-ing it doesn't alter this set
            if (other is IdentityMultiset) return this;
            if (other is NullMultiset) return this;
            //If the other Multiset is disjoint then minus-ing it also doesn't alter this set
            if (this.IsDisjointWith(other)) return this;

            //Find the Variables that are to be used for Joining
            List<String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();
            if (joinVars.Count == 0) return this.Product(other);

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();
            foreach (ISet x in this.Sets)
            {
                //New Minus logic based on the improved Join() logic
                bool minus = other.Sets.Any(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));

                //If no compatible sets then this set is preserved
                if (!minus)
                {
                    joinedSet.Add(x);
                }
            }
            return joinedSet;
        }
コード例 #27
0
ファイル: BindingsPattern.cs プロジェクト: jbunzel/MvcRQ_git
 /// <summary>
 /// Converts a Bindings Clause to a Multiset
 /// </summary>
 /// <returns></returns>
 public BaseMultiset ToMultiset()
 {
     if (this._vars.Any())
     {
         Multiset m = new Multiset();
         foreach (String var in this._vars)
         {
             m.AddVariable(var);
         }
         foreach (BindingTuple tuple in this._tuples)
         {
             m.Add(new Set(tuple));
         }
         return m;
     }
     else
     {
         return new IdentityMultiset();
     }
 }
コード例 #28
0
        /// <summary>
        /// Does a Left Join of this Multiset to another Multiset where the Join is predicated on the given Expression.
        /// </summary>
        /// <param name="other">Other Multiset.</param>
        /// <param name="expr">Expression.</param>
        /// <returns></returns>
        public virtual BaseMultiset LeftJoin(BaseMultiset other, ISparqlExpression expr)
        {
            // If the Other is the Identity/Null Multiset the result is this Multiset
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(this);
            }
            if (other.IsEmpty)
            {
                return(this);
            }

            Multiset joinedSet                 = new Multiset();
            LeviathanLeftJoinBinder binder     = new LeviathanLeftJoinBinder(joinedSet);
            SparqlEvaluationContext subcontext = new SparqlEvaluationContext(binder);

            // Find the First Variable from this Multiset which is in both Multisets
            // If there is no Variable from this Multiset in the other Multiset then this
            // should be a Join operation instead of a LeftJoin
            List <String> joinVars = Variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
#if NET40
                if (Options.UsePLinqEvaluation && expr.CanParallelise)
                {
                    PartitionedMultiset partitionedSet = new PartitionedMultiset(this.Count, other.Count + 1);
                    this.Sets.AsParallel().ForAll(x => EvalLeftJoinProduct(x, other, partitionedSet, expr));
                    return(partitionedSet);
                }
#endif
                // Do a serial Left Join Product

                // Calculate a Product filtering as we go
                foreach (ISet x in Sets)
                {
                    bool standalone = false;
                    bool matched    = false;
                    foreach (ISet y in other.Sets)
                    {
                        ISet z = x.Join(y);
                        try
                        {
                            joinedSet.Add(z);
                            if (!expr.Evaluate(subcontext, z.ID).AsSafeBoolean())
                            {
                                joinedSet.Remove(z.ID);
                                standalone = true;
                            }
                            else
                            {
                                matched = true;
                            }
                        }
                        catch
                        {
                            joinedSet.Remove(z.ID);
                            standalone = true;
                        }
                    }
                    if (standalone && !matched)
                    {
                        joinedSet.Add(x.Copy());
                    }
                }
#if NET40
#endif
            }
            else
            {
                // This is the new Join algorithm which is also correct but is O(2n) so much faster and scalable
                // Downside is that it does require more memory than the old algorithm
                List <MultiDictionary <INode, List <int> > > values = new List <MultiDictionary <INode, List <int> > >();
                List <List <int> > nulls = new List <List <int> >();
                foreach (String var in joinVars)
                {
                    joinedSet.AddVariable(var);
                    values.Add(new MultiDictionary <INode, List <int> >(new FastVirtualNodeComparer()));
                    nulls.Add(new List <int>());
                }

                // First do a pass over the RHS Result to find all possible values for joined variables
                foreach (ISet y in other.Sets)
                {
                    int i = 0;
                    foreach (String var in joinVars)
                    {
                        INode value = y[var];
                        if (value != null)
                        {
                            if (values[i].TryGetValue(value, out List <int> ids))
                            {
                                ids.Add(y.ID);
                            }
                            else
                            {
                                values[i].Add(value, new List <int> {
                                    y.ID
                                });
                            }
                        }
                        else
                        {
                            nulls[i].Add(y.ID);
                        }
                        i++;
                    }
                }

                // Then do a pass over the LHS and work out the intersections
#if NET40
                if (Options.UsePLinqEvaluation && expr.CanParallelise)
                {
                    this.Sets.AsParallel().ForAll(x => EvalLeftJoin(x, other, joinVars, values, nulls, joinedSet, subcontext, expr));
                }
                else
                {
                    // Use a Serial Left Join
                    foreach (ISet x in this.Sets)
                    {
                        this.EvalLeftJoin(x, other, joinVars, values, nulls, joinedSet, subcontext, expr);
                    }
                }
#else
                // Use a Serial Left Join
                foreach (var x in Sets)
                {
                    EvalLeftJoin(x, other, joinVars, values, nulls, joinedSet, subcontext, expr);
                }
#endif
            }
            return(joinedSet);
        }
コード例 #29
0
        /// <summary>
        /// Does an Exists Join of this Multiset to another Multiset where the Join is predicated on the existence/non-existence of a joinable solution on the RHS.
        /// </summary>
        /// <param name="other">Other Multiset.</param>
        /// <param name="mustExist">Whether a solution must exist in the Other Multiset for the join to be made.</param>
        /// <returns></returns>
        public virtual BaseMultiset ExistsJoin(BaseMultiset other, bool mustExist)
        {
            // For EXISTS and NOT EXISTS if the other is the Identity then it has no effect
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (mustExist)
            {
                // If an EXISTS then Null/Empty Other results in Null
                if (other is NullMultiset)
                {
                    return(other);
                }
                if (other.IsEmpty)
                {
                    return(new NullMultiset());
                }
            }
            else
            {
                // If a NOT EXISTS then Null/Empty results in this
                if (other is NullMultiset)
                {
                    return(this);
                }
                if (other.IsEmpty)
                {
                    return(this);
                }
            }

            // Find the Variables that are to be used for Joining
            List <String> joinVars = Variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                // All Disjoint Solutions are compatible
                if (mustExist)
                {
                    // If an EXISTS and disjoint then result is this
                    return(this);
                }
                else
                {
                    // If a NOT EXISTS and disjoint then result is null
                    return(new NullMultiset());
                }
            }

            // Start building the Joined Set
            Multiset joinedSet = new Multiset();

            // This is the new algorithm which is also correct but is O(3n) so much faster and scalable
            // Downside is that it does require more memory than the old algorithm
            List <MultiDictionary <INode, List <int> > > values = new List <MultiDictionary <INode, List <int> > >();
            List <List <int> > nulls = new List <List <int> >();

            foreach (String var in joinVars)
            {
                joinedSet.AddVariable(var);
                values.Add(new MultiDictionary <INode, List <int> >(new FastVirtualNodeComparer()));
                nulls.Add(new List <int>());
            }

            // First do a pass over the LHS Result to find all possible values for joined variables
            foreach (ISet x in Sets)
            {
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = x[var];
                    if (value != null)
                    {
                        if (values[i].TryGetValue(value, out List <int> ids))
                        {
                            ids.Add(x.ID);
                        }
                        else
                        {
                            values[i].Add(value, new List <int> {
                                x.ID
                            });
                        }
                    }
                    else
                    {
                        nulls[i].Add(x.ID);
                    }
                    i++;
                }
            }

            // Then do a pass over the RHS and work out the intersections
            HashSet <int> exists = new HashSet <int>();

            foreach (ISet y in other.Sets)
            {
                IEnumerable <int> possMatches = null;
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = y[var];
                    if (value != null)
                    {
                        if (values[i].ContainsKey(value))
                        {
                            possMatches = (possMatches == null ? values[i][value].Concat(nulls[i]) : possMatches.Intersect(values[i][value].Concat(nulls[i])));
                        }
                        else
                        {
                            possMatches = Enumerable.Empty <int>();
                            break;
                        }
                    }
                    else
                    {
                        // Don't forget that a null will be potentially compatible with everything
                        possMatches = (possMatches == null ? SetIDs : possMatches.Intersect(SetIDs));
                    }
                    i++;
                }
                if (possMatches == null)
                {
                    continue;
                }

                // Look at possible matches, if is a valid match then mark the set as having an existing match
                // Don't reconsider sets which have already been marked as having an existing match
                foreach (int poss in possMatches)
                {
                    if (exists.Contains(poss))
                    {
                        continue;
                    }
                    if (this[poss].IsCompatibleWith(y, joinVars))
                    {
                        exists.Add(poss);
                    }
                }
            }

            // Apply the actual exists
            if (exists.Count == Count)
            {
                // If number of sets that have a match is equal to number of sets then we're either returning everything or nothing
                if (mustExist)
                {
                    return(this);
                }
                else
                {
                    return(new NullMultiset());
                }
            }
            else
            {
                // Otherwise iterate
                foreach (ISet x in Sets)
                {
                    if (mustExist)
                    {
                        if (exists.Contains(x.ID))
                        {
                            joinedSet.Add(x.Copy());
                        }
                    }
                    else
                    {
                        if (!exists.Contains(x.ID))
                        {
                            joinedSet.Add(x.Copy());
                        }
                    }
                }
            }

            return(joinedSet);
        }
コード例 #30
0
        /// <summary>
        /// Does a Minus Join of this Multiset to another Multiset where any joinable results are subtracted from this Multiset to give the resulting Multiset.
        /// </summary>
        /// <param name="other">Other Multiset.</param>
        /// <returns></returns>
        public virtual BaseMultiset MinusJoin(BaseMultiset other)
        {
            // If the other Multiset is the Identity/Null Multiset then minus-ing it doesn't alter this set
            if (other is IdentityMultiset)
            {
                return(this);
            }
            if (other is NullMultiset)
            {
                return(this);
            }
            // If the other Multiset is disjoint then minus-ing it also doesn't alter this set
            if (IsDisjointWith(other))
            {
                return(this);
            }

            // Find the Variables that are to be used for Joining
            List <String> joinVars = Variables.Where(v => other.Variables.Contains(v)).ToList();

            if (joinVars.Count == 0)
            {
                return(Product(other));
            }

            // Start building the Joined Set
            Multiset joinedSet = new Multiset();

            // This is the new algorithm which is also correct but is O(3n) so much faster and scalable
            // Downside is that it does require more memory than the old algorithm
            List <MultiDictionary <INode, List <int> > > values = new List <MultiDictionary <INode, List <int> > >();
            List <List <int> > nulls = new List <List <int> >();

            foreach (String var in joinVars)
            {
                values.Add(new MultiDictionary <INode, List <int> >(new FastVirtualNodeComparer()));
                nulls.Add(new List <int>());
            }

            // First do a pass over the LHS Result to find all possible values for joined variables
            foreach (ISet x in Sets)
            {
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = x[var];
                    if (value != null)
                    {
                        if (values[i].TryGetValue(value, out List <int> ids))
                        {
                            ids.Add(x.ID);
                        }
                        else
                        {
                            values[i].Add(value, new List <int> {
                                x.ID
                            });
                        }
                    }
                    else
                    {
                        nulls[i].Add(x.ID);
                    }
                    i++;
                }
            }

            // Then do a pass over the RHS and work out the intersections
            HashSet <int> toMinus = new HashSet <int>();

            foreach (ISet y in other.Sets)
            {
                IEnumerable <int> possMatches = null;
                int i = 0;
                foreach (String var in joinVars)
                {
                    INode value = y[var];
                    if (value != null)
                    {
                        if (values[i].ContainsKey(value))
                        {
                            possMatches = (possMatches == null ? values[i][value].Concat(nulls[i]) : possMatches.Intersect(values[i][value].Concat(nulls[i])));
                        }
                        else
                        {
                            possMatches = Enumerable.Empty <int>();
                            break;
                        }
                    }
                    else
                    {
                        // Don't forget that a null will be potentially compatible with everything
                        possMatches = (possMatches == null ? SetIDs : possMatches.Intersect(SetIDs));
                    }
                    i++;
                }
                if (possMatches == null)
                {
                    continue;
                }

                // Look at possible matches, if is a valid match then mark the matched set for minus'ing
                // Don't reconsider sets which have already been marked for minusing
                foreach (int poss in possMatches)
                {
                    if (toMinus.Contains(poss))
                    {
                        continue;
                    }
                    if (this[poss].IsMinusCompatibleWith(y, joinVars))
                    {
                        toMinus.Add(poss);
                    }
                }
            }

            // Apply the actual minus
            if (toMinus.Count == Count)
            {
                // If number of sets to minus is equal to number of sets then we're minusing everything
                return(new NullMultiset());
            }
            else
            {
                // Otherwise iterate
                foreach (ISet x in Sets)
                {
                    if (!toMinus.Contains(x.ID))
                    {
                        joinedSet.Add(x.Copy());
                    }
                }
            }

            return(joinedSet);
        }
コード例 #31
0
        /// <summary>
        /// Evaluates a setp of the Path
        /// </summary>
        /// <param name="context">Context</param>
        /// <param name="path">Paths</param>
        /// <param name="reverse">Whether to evaluate Paths in reverse</param>
        /// <returns></returns>
        protected List <INode> EvaluateStep(SparqlEvaluationContext context, List <INode> path, bool reverse)
        {
            if (this.Path is Property)
            {
                HashSet <INode>      nodes     = new HashSet <INode>();
                INode                predicate = ((Property)this.Path).Predicate;
                IEnumerable <Triple> ts        = (reverse ? context.Data.GetTriplesWithPredicateObject(predicate, path[path.Count - 1]) : context.Data.GetTriplesWithSubjectPredicate(path[path.Count - 1], predicate));
                foreach (Triple t in ts)
                {
                    if (reverse)
                    {
                        if (!path.Contains(t.Subject))
                        {
                            nodes.Add(t.Subject);
                        }
                    }
                    else
                    {
                        if (!path.Contains(t.Object))
                        {
                            nodes.Add(t.Object);
                        }
                    }
                }
                return(nodes.ToList());
            }
            else
            {
                HashSet <INode> nodes = new HashSet <INode>();

                BaseMultiset    initialInput = context.InputMultiset;
                Multiset        currInput    = new Multiset();
                VariablePattern x            = new VariablePattern("?x");
                VariablePattern y            = new VariablePattern("?y");
                Set             temp         = new Set();
                if (reverse)
                {
                    temp.Add("y", path[path.Count - 1]);
                }
                else
                {
                    temp.Add("x", path[path.Count - 1]);
                }
                currInput.Add(temp);
                context.InputMultiset = currInput;

                Bgp          bgp     = new Bgp(new PropertyPathPattern(x, this.Path, y));
                BaseMultiset results = context.Evaluate(bgp); //bgp.Evaluate(context);
                context.InputMultiset = initialInput;

                if (!results.IsEmpty)
                {
                    foreach (ISet s in results.Sets)
                    {
                        if (reverse)
                        {
                            if (s["x"] != null)
                            {
                                if (!path.Contains(s["x"]))
                                {
                                    nodes.Add(s["x"]);
                                }
                            }
                        }
                        else
                        {
                            if (s["y"] != null)
                            {
                                if (!path.Contains(s["y"]))
                                {
                                    nodes.Add(s["y"]);
                                }
                            }
                        }
                    }
                }

                return(nodes.ToList());
            }
        }
コード例 #32
0
ファイル: Multiset.cs プロジェクト: almostEric/DotNetRDF-4.0
        /// <summary>
        /// Joins this Multiset to another Multiset
        /// </summary>
        /// <param name="other">Other Multiset</param>
        /// <returns></returns>
        public override BaseMultiset Join(BaseMultiset other)
        {
            //If the Other is the Identity Multiset the result is this Multiset
            if (other is IdentityMultiset) return this;
            //If the Other is the Null Multiset the result is the Null Multiset
            if (other is NullMultiset) return other;
            //If the Other is Empty then the result is the Null Multiset
            if (other.IsEmpty) return new NullMultiset();

            //Find the First Variable from this Multiset which is in both Multisets
            //If there is no Variable from this Multiset in the other Multiset then this
            //should be a Join operation instead of a LeftJoin
            List<String> joinVars = this._variables.Where(v => other.Variables.Contains(v)).ToList();
            if (joinVars.Count == 0) return this.Product(other);

            //Start building the Joined Set
            Multiset joinedSet = new Multiset();
            foreach (Set x in this.Sets)
            {
                //For sets to be compatible for every joinable variable they must either have a null for the
                //variable in one of the sets or if they have values the values must be equal

                IEnumerable<Set> ys = other.Sets.Where(s => joinVars.All(v => x[v] == null || s[v] == null || x[v].Equals(s[v])));

                foreach (Set y in ys)
                {
                    joinedSet.Add(new Set(x, y));
                }
            }
            return joinedSet;
        }