Example #1
0
        /// <summary>
        /// Optimises an Algebra to a form that uses <see cref="LazyBgp">LazyBgp</see> where possible
        /// </summary>
        /// <param name="algebra">Algebra</param>
        /// <param name="depth">Depth</param>
        /// <returns></returns>
        /// <remarks>
        /// <para>
        /// By transforming a query to use <see cref="LazyBgp">LazyBgp</see> we can achieve much more efficient processing of some forms of queries
        /// </para>
        /// </remarks>
        protected override ISparqlAlgebra OptimiseInternal(ISparqlAlgebra algebra, int depth)
        {
            try
            {
                ISparqlAlgebra temp;

                //Note this first test is specifically for the default BGP implementation since other optimisers
                //may run before us and replace with other BGP implementations which we don't want to replace hence
                //why we don't check for IBgp here
                if (algebra is Bgp)
                {
                    temp = new LazyBgp(((Bgp)algebra).TriplePatterns);
                }
                //else if (algebra is ILeftJoin)
                //{
                //    ILeftJoin join = (ILeftJoin)algebra;
                //    temp = new LeftJoin(this.OptimiseInternal(join.Lhs, depth + 1), join.Rhs, ((LeftJoin)algebra).Filter);
                //}
                else if (algebra is IUnion)
                {
                    IUnion join = (IUnion)algebra;
                    temp = new LazyUnion(this.OptimiseInternal(join.Lhs, depth + 1), this.OptimiseInternal(join.Rhs, depth + 1));
                }
                else if (algebra is IJoin)
                {
                    IJoin join = (IJoin)algebra;
                    if (join.Lhs.Variables.IsDisjoint(join.Rhs.Variables))
                    {
                        //If the sides of the Join are disjoint then can fully transform the join since we only need to find the requisite number of
                        //solutions on either side to guarantee a product which meets/exceeds the required results
                        //temp = new Join(this.OptimiseInternal(join.Lhs, depth + 1), this.OptimiseInternal(join.Rhs, depth + 1));
                        temp = join.Transform(this);
                    }
                    else
                    {
                        //If the sides are not disjoint then the LHS must be fully evaluated but the RHS need only produce enough
                        //solutions that match
                        //temp = new Join(join.Lhs, this.OptimiseInternal(join.Rhs, depth + 1));
                        temp = join.TransformRhs(this);
                    }
                }
                else if (algebra is Algebra.Graph)
                {
                    //Algebra.Graph g = (Algebra.Graph)algebra;
                    //temp = new Algebra.Graph(this.OptimiseInternal(g.InnerAlgebra, depth + 1), g.GraphSpecifier);
                    IUnaryOperator op = (IUnaryOperator)algebra;
                    temp = op.Transform(this);
                }
                else
                {
                    temp = algebra;
                }
                return temp;
            }
            catch
            {
                //If the Optimise fails return the current algebra
                return algebra;
            }
        }
        public void SparqlStreamingBgpSelectEvaluation()
        {
            //Get the Data we want to query
            TripleStore store = new TripleStore();
            Graph g = new Graph();
            FileLoader.Load(g, "InferenceTest.ttl");
            store.Add(g);
            //g = new Graph();
            //FileLoader.Load(g, "noise.ttl");
            //store.Add(g);

            Console.WriteLine(store.Triples.Count() + " Triples in Store");

            //Create the Triple Pattern we want to query with
            IUriNode fordFiesta = g.CreateUriNode(new Uri("http://example.org/vehicles/FordFiesta"));
            IUriNode rdfType = g.CreateUriNode(new Uri(RdfSpecsHelper.RdfType));
            IUriNode rdfsLabel = g.CreateUriNode(new Uri(NamespaceMapper.RDFS + "label"));
            IUriNode speed = g.CreateUriNode(new Uri("http://example.org/vehicles/Speed"));
            IUriNode carClass = g.CreateUriNode(new Uri("http://example.org/vehicles/Car"));

            TriplePattern allTriples = new TriplePattern(new VariablePattern("?s"), new VariablePattern("?p"), new VariablePattern("?o"));
            TriplePattern allTriples2 = new TriplePattern(new VariablePattern("?x"), new VariablePattern("?y"), new VariablePattern("?z"));
            TriplePattern tp1 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(rdfType), new NodeMatchPattern(carClass));
            TriplePattern tp2 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(speed), new VariablePattern("?speed"));
            TriplePattern tp3 = new TriplePattern(new VariablePattern("?s"), new NodeMatchPattern(rdfsLabel), new VariablePattern("?label"));
            TriplePattern novars = new TriplePattern(new NodeMatchPattern(fordFiesta), new NodeMatchPattern(rdfType), new NodeMatchPattern(carClass));
            TriplePattern novars2 = new TriplePattern(new NodeMatchPattern(fordFiesta), new NodeMatchPattern(rdfsLabel), new NodeMatchPattern(carClass));
            FilterPattern blankSubject = new FilterPattern(new UnaryExpressionFilter(new IsBlankFunction(new VariableExpressionTerm("?s"))));
            List<List<ITriplePattern>> tests = new List<List<ITriplePattern>>()
            {
                new List<ITriplePattern>() { },
                new List<ITriplePattern>() { allTriples },
                new List<ITriplePattern>() { allTriples, allTriples2 },
                new List<ITriplePattern>() { tp1 },
                new List<ITriplePattern>() { tp1, tp2 },
                new List<ITriplePattern>() { tp1, tp3 },
                new List<ITriplePattern>() { novars },
                new List<ITriplePattern>() { novars, tp1 },
                new List<ITriplePattern>() { novars, tp1, tp2 },
                new List<ITriplePattern>() { novars2 },
                new List<ITriplePattern>() { tp1, blankSubject }
            };

            foreach (List<ITriplePattern> tps in tests)
            {
                Console.WriteLine(tps.Count + " Triple Patterns in the Query");
                foreach (ITriplePattern tp in tps)
                {
                    Console.WriteLine(tp.ToString());
                }
                Console.WriteLine();

                ISparqlAlgebra select = new Bgp(tps);
                ISparqlAlgebra selectOptimised = new LazyBgp(tps, 10);

                //Evaluate with timings
                Stopwatch timer = new Stopwatch();
                TimeSpan unopt, opt;
                timer.Start();
                BaseMultiset results1 = select.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store)));
                timer.Stop();
                unopt = timer.Elapsed;
                timer.Reset();
                timer.Start();
                BaseMultiset results2 = selectOptimised.Evaluate(new SparqlEvaluationContext(null, new InMemoryDataset(store)));
                timer.Stop();
                opt = timer.Elapsed;

                Console.WriteLine("SELECT = " + results1.GetType().ToString() + " (" + results1.Count + " Results) in " + unopt.ToString());
                Console.WriteLine("SELECT Optimised = " + results2.GetType().ToString() + " (" + results2.Count + " Results) in " + opt.ToString());

                Console.WriteLine();
                Console.WriteLine("Optimised Results");
                foreach (Set s in results2.Sets)
                {
                    Console.WriteLine(s.ToString());
                }

                Assert.IsTrue(results1.Count >= results2.Count, "Optimised Select should have produced as many/fewer results than Unoptimised Select");

                Console.WriteLine();
            }
        }