public void GraphDiffNullReferenceBoth()
        {
            GraphDiff       diff   = new GraphDiff();
            GraphDiffReport report = diff.Difference(null, null);

            TestTools.ShowDifferences(report);

            Assert.True(report.AreEqual, "Graphs should have been reported as equal for two null references");
            Assert.False(report.AreDifferentSizes, "Graphs should have been reported same size for two null references");
        }
        public void GraphDiffNullReferenceA()
        {
            Graph g = new Graph();

            g.LoadFromFile("resources\\InferenceTest.ttl");

            GraphDiff       diff   = new GraphDiff();
            GraphDiffReport report = diff.Difference(null, g);

            TestTools.ShowDifferences(report);

            Assert.False(report.AreEqual, "Graphs should have been reported as non-equal for one null reference");
            Assert.True(report.AreDifferentSizes, "Graphs should have been reported as different sizes for one null reference");
            Assert.True(report.AddedTriples.Any(), "Report should list added triples");
        }
예제 #3
0
        /// <summary>
        /// Computes MSGs for a Graph
        /// </summary>
        /// <param name="g">Graph</param>
        /// <param name="unassigned">Triples that need assigning to MSGs</param>
        /// <param name="msgs">MSGs list to populate</param>
        public static void ComputeMSGs(IGraph g, HashSet <Triple> unassigned, List <IGraph> msgs)
        {
            //While we have unassigned Triples build MSGs
            while (unassigned.Count > 0)
            {
                HashSet <INode> processed   = new HashSet <INode>();
                Queue <INode>   unprocessed = new Queue <INode>();

                //Get next Triple from unassigned
                Triple first = unassigned.First();
                unassigned.Remove(first);

                //Get the BNodes from it that need to be processed
                GraphDiff.GetNodesForProcessing(first, unprocessed);

                //Start building an MSG starting from the Triple
                Graph msg = new Graph();
                msg.Assert(first);
                while (unprocessed.Count > 0)
                {
                    INode next = unprocessed.Dequeue();
                    //Can safely skip Nodes we've already processed
                    if (processed.Contains(next))
                    {
                        continue;
                    }

                    //Get all the Triples that use the given Node and find any additional Blank Nodes for processing
                    foreach (Triple t in g.GetTriples(next))
                    {
                        //When a Triple is added to an MSG it is removed from the unassigned list
                        unassigned.Remove(t);
                        msg.Assert(t);
                        GraphDiff.GetNodesForProcessing(t, unprocessed);
                    }

                    processed.Add(next);
                }

                msgs.Add(msg);
            }
        }
        private IGraph ExecuteDiff(IGraph older, IGraph newer, Uri graphUri = null)
        {
            var diff   = new GraphDiff().Difference(older, newer);
            var update = diff.AsUpdate(graphUri);
            var sparql = update.ToString();

            output.WriteLine(sparql);

            older = older ?? new Graph();

            var ts = new TripleStore();

            ts.Add(older);

            var store = new InMemoryManager(ts) as IUpdateableStorage;

            store.Update(sparql);

            return(older);
        }
예제 #5
0
        /// <summary>
        /// Computes the Difference between this Graph the given Graph.
        /// </summary>
        /// <param name="g">Graph.</param>
        /// <returns></returns>
        /// <remarks>
        /// <para>
        /// Produces a report which shows the changes that must be made to this Graph to produce the given Graph.
        /// </para>
        /// </remarks>
        public GraphDiffReport Difference(IGraph g)
        {
            GraphDiff differ = new GraphDiff();

            return(differ.Difference(this, g));
        }
예제 #6
0
        /// <summary>
        /// Calculates the Difference between the two Graphs i.e. the changes required to get from the 1st Graph to the 2nd Graph
        /// </summary>
        /// <param name="a">First Graph</param>
        /// <param name="b">Second Graph</param>
        /// <returns></returns>
        public GraphDiffReport Difference(IGraph a, IGraph b)
        {
            GraphDiffReport report = new GraphDiffReport();

            if (a == null)
            {
                if (b == null)
                {
                    //Both Graphs are null so considered equal with no differences
                    report.AreEqual          = true;
                    report.AreDifferentSizes = false;
                    return(report);
                }
                else
                {
                    //A is null and B is non-null so considered non-equal with everything from B listed as added
                    report.AreEqual          = false;
                    report.AreDifferentSizes = true;
                    foreach (Triple t in b.Triples)
                    {
                        if (t.IsGroundTriple)
                        {
                            report.AddAddedTriple(t);
                        }
                        else
                        {
                            this._rhsUnassigned.Add(t);
                        }
                    }
                    GraphDiff.ComputeMSGs(b, this._rhsUnassigned, this._rhsMSGs);
                    foreach (IGraph msg in this._rhsMSGs)
                    {
                        report.AddAddedMSG(msg);
                    }
                    return(report);
                }
            }
            else if (b == null)
            {
                //A is non-null and B is null so considered non-equal with everything from A listed as removed
                report.AreEqual          = false;
                report.AreDifferentSizes = true;
                foreach (Triple t in a.Triples)
                {
                    if (t.IsGroundTriple)
                    {
                        report.AddRemovedTriple(t);
                    }
                    else
                    {
                        this._lhsUnassigned.Add(t);
                    }
                }
                GraphDiff.ComputeMSGs(a, this._lhsUnassigned, this._lhsMSGs);
                foreach (IGraph msg in this._lhsMSGs)
                {
                    report.AddRemovedMSG(msg);
                }
                return(report);
            }

            //Firstly check for Graph Equality
            Dictionary <INode, INode> equalityMapping = new Dictionary <INode, INode>();

            if (a.Equals(b, out equalityMapping))
            {
                //If Graphs are equal set AreEqual to true, assign the mapping and return
                report.AreEqual = true;
                if (equalityMapping != null)
                {
                    report.Mapping = equalityMapping;
                }
                return(report);
            }
            Debug.WriteLine(String.Empty);

            report.AreDifferentSizes = (a.Triples.Count != b.Triples.Count);

            //Next check for changes in Ground Triples
            //Iterate over the Ground Triples in the 1st Graph to find those that have been removed in the 2nd
            foreach (Triple t in a.Triples.Where(t => t.IsGroundTriple))
            {
                if (!b.Triples.Contains(t))
                {
                    report.AddRemovedTriple(t);
                }
            }
            //Iterate over the Ground Triples in the 2nd Graph to find those that have been added in the 2nd
            foreach (Triple t in b.Triples.Where(t => t.IsGroundTriple))
            {
                if (!a.Triples.Contains(t))
                {
                    report.AddAddedTriple(t);
                }
            }

            //Do we need to compute MSGs?
            //If all Triples are Ground Triples then this step gets skipped which saves on computation
            if (a.Triples.Any(t => !t.IsGroundTriple) || b.Triples.Any(t => !t.IsGroundTriple))
            {
                //Some non-ground Triples so start computing MSGs

                //First build 2 HashSets of the non-ground Triples from the Graphs
                foreach (Triple t in a.Triples.Where(t => !t.IsGroundTriple))
                {
                    this._lhsUnassigned.Add(t);
                }
                foreach (Triple t in b.Triples.Where(t => !t.IsGroundTriple))
                {
                    this._rhsUnassigned.Add(t);
                }

                //Then compute all the MSGs
                GraphDiff.ComputeMSGs(a, this._lhsUnassigned, this._lhsMSGs);
                GraphDiff.ComputeMSGs(b, this._rhsUnassigned, this._rhsMSGs);

                //Sort MSGs by size - this is just so we start checking MSG equality from smallest MSGs first for efficiency
                GraphSizeComparer comparer = new GraphSizeComparer();
                this._lhsMSGs.Sort(comparer);
                this._rhsMSGs.Sort(comparer);

                //Now start trying to match MSG
                foreach (IGraph msg in this._lhsMSGs)
                {
                    //Get Candidate MSGs from RHS i.e. those of equal size
                    List <IGraph> candidates = (from g in this._rhsMSGs
                                                where g.Triples.Count == msg.Triples.Count
                                                select g).ToList();

                    if (candidates.Count == 0)
                    {
                        //No Candidate Matches so this MSG is not present in the 2nd Graph so add to report as a Removed MSG
                        report.AddRemovedMSG(msg);
                    }
                    else
                    {
                        //Do any of the candidates match?
                        bool hasMatch = false;
                        foreach (IGraph candidate in candidates)
                        {
                            Dictionary <INode, INode> tempMapping = new Dictionary <INode, INode>();
                            if (msg.Equals(candidate, out tempMapping))
                            {
                                //This MSG has a Match in the 2nd Graph so add the Mapping information
                                hasMatch = true;
                                try
                                {
                                    this.MergeMapping(report, tempMapping);
                                }
                                catch (RdfException)
                                {
                                    //If the Mapping cannot be merged it is a bad mapping and we try other candidates
                                    hasMatch = false;
                                    continue;
                                }

                                //Remove the matched MSG from the RHS MSGs so we cannot match another LHS MSG to it later
                                //We use ReferenceEquals for this remove to avoid potentially costly Graph Equality calculations
                                this._rhsMSGs.RemoveAll(g => ReferenceEquals(g, candidate));
                            }
                        }

                        //No match was found so the MSG is removed from the 2nd Graph
                        if (!hasMatch)
                        {
                            report.AddRemovedMSG(msg);
                        }
                    }
                }

                //If we are left with any MSGs in the RHS then these are added MSG
                foreach (IGraph msg in this._rhsMSGs)
                {
                    report.AddAddedMSG(msg);
                }
            }
            return(report);
        }