Esempio n. 1
0
        /// <summary>
        /// Algo 1: Find subgraph frequency (mappings help in memory)
        /// </summary>
        /// <param name="inputGraph"></param>
        /// <param name="qGraph">The query graph to be searched for. If not available, we use expansion trees (MODA). Otherwise, we use Grochow's (Algo 2)</param>
        /// <param name="subgraphSize"></param>
        /// <param name="thresholdValue">Frequency value, above which we can comsider the subgraph a "frequent subgraph"</param>
        /// <returns></returns>
        public static Dictionary <QueryGraph, ICollection <Mapping> > Algorithm1(UndirectedGraph <int> inputGraph, QueryGraph qGraph, int subgraphSize = -1, int thresholdValue = 0)
        {
            // The enumeration module (Algo 3) needs the mappings generated from the previous run(s)
            Dictionary <QueryGraph, ICollection <Mapping> > allMappings;
            int numIterations = -1;

            if (inputGraph.VertexCount < 121)
            {
                numIterations = inputGraph.VertexCount;
            }

            if (qGraph == null) // Use MODA's expansion tree
            {
                #region Use MODA's expansion tree
                var treatedNodes = new HashSet <QueryGraph>();
                allMappings = new Dictionary <QueryGraph, ICollection <Mapping> >(_builder.NumberOfQueryGraphs);
                do
                {
                    qGraph = GetNextNode()?.QueryGraph;
                    if (qGraph == null)
                    {
                        break;
                    }
                    ICollection <Mapping> mappings;
                    if (qGraph.IsTree(subgraphSize))
                    {
                        if (UseModifiedGrochow)
                        {
                            // Modified Mapping module - MODA and Grockow & Kellis
                            mappings = Algorithm2_Modified(qGraph, inputGraph, numIterations, false);
                        }
                        else
                        {
                            // Mapping module - MODA and Grockow & Kellis.
                            var inputGraphClone = inputGraph.Clone();
                            mappings = Algorithm2(qGraph, inputGraphClone, numIterations, false);
                            inputGraphClone.Clear();
                            inputGraphClone = null;
                        }
                    }
                    else
                    {
                        // Enumeration moodule - MODA
                        // This is part of Algo 3; but performance tweaks makes it more useful to get it here
                        var parentQueryGraph = GetParent(qGraph, _builder.ExpansionTree);
                        if (parentQueryGraph.IsTree(subgraphSize))
                        {
                            treatedNodes.Add(parentQueryGraph);
                        }
                        string file;
                        mappings = Algorithm3(allMappings, inputGraph, qGraph, _builder.ExpansionTree, parentQueryGraph, out file);
                    }
                    if (mappings != null && mappings.Count > thresholdValue)
                    {
                        qGraph.IsFrequentSubgraph = true;
                    }
                    // Save mappings. Do we need to save to disk? Maybe not!

                    allMappings.Add(qGraph, mappings);
                    // Do not call mappings.Clear()
                    mappings = null;
                    // Check for complete-ness; if complete, break
                    if (qGraph.IsComplete(subgraphSize))
                    {
                        qGraph = null;
                        break;
                    }
                    qGraph = null;
                }while (true);

                if (treatedNodes.Count > 0)
                {
                    foreach (var mapping in allMappings)
                    {
                        if (mapping.Key.IsTree(subgraphSize) && !treatedNodes.Contains(mapping.Key))
                        {
                            mapping.Key.RemoveNonApplicableMappings(mapping.Value, inputGraph);
                        }
                    }
                    treatedNodes.Clear();
                }
                treatedNodes = null;
                #endregion
            }
            else
            {
                ICollection <Mapping> mappings;
                if (UseModifiedGrochow)
                {
                    // Modified Mapping module - MODA and Grockow & Kellis
                    mappings = Algorithm2_Modified(qGraph, inputGraph, numIterations, true);
                    // mappings = ModaAlgorithm2Parallelized.Algorithm2_Modified(qGraph, inputGraph, numIterations);
                }
                else
                {
                    mappings = Algorithm2(qGraph, inputGraph, numIterations, true);
                }

                qGraph.RemoveNonApplicableMappings(mappings, inputGraph);
                allMappings = new Dictionary <QueryGraph, ICollection <Mapping> >(1)
                {
                    { qGraph, mappings }
                };

                // Do not call mappings.Clear()
                mappings = null;
            }

            return(allMappings);
        }
Esempio n. 2
0
        /// <summary>
        /// Algo 1: Find subgraph frequency (mappings found are saved to disk to be retrieved later during Algo 3).
        /// The value of the dictionary returned is in the form: $"{mappings.Count}#{qGraph.Label}.ser"
        /// </summary>
        /// <param name="inputGraph"></param>
        /// <param name="qGraph">The query graph to be searched for. If not available, we use expansion trees (MODA). Otherwise, we use Grochow's (Algo 2)</param>
        /// <param name="subgraphSize"></param>
        /// <param name="thresholdValue">Frequency value, above which we can comsider the subgraph a "frequent subgraph"</param>
        /// <returns></returns>
        public static Dictionary <QueryGraph, string> Algorithm1_C(UndirectedGraph <int> inputGraph, QueryGraph qGraph, int subgraphSize, int thresholdValue)
        {
            // The enumeration module (Algo 3) needs the mappings generated from the previous run(s)
            Dictionary <QueryGraph, string> allMappings;
            int numIterations = -1;

            if (inputGraph.VertexCount < 121)
            {
                numIterations = inputGraph.VertexCount;
            }

            if (qGraph == null) // Use MODA's expansion tree
            {
                #region Use MODA's expansion tree
                var treatedNodes = new HashSet <QueryGraph>();
                allMappings = new Dictionary <QueryGraph, string>(_builder.NumberOfQueryGraphs);
                do
                {
                    qGraph = GetNextNode()?.QueryGraph;
                    if (qGraph == null)
                    {
                        break;
                    }
                    ICollection <Mapping> mappings;
                    if (qGraph.EdgeCount == (subgraphSize - 1)) // i.e. if qGraph is a tree
                    {
                        if (UseModifiedGrochow)
                        {
                            // Modified Mapping module - MODA and Grockow & Kellis
                            mappings = Algorithm2_Modified(qGraph, inputGraph, numIterations, false);
                        }
                        else
                        {
                            var inputGraphClone = inputGraph.Clone();
                            mappings = Algorithm2(qGraph, inputGraphClone, numIterations, false);
                            inputGraphClone.Clear();
                            inputGraphClone = null;
                        }

                        // Because we're saving to file, we're better off doing this now
                        qGraph.RemoveNonApplicableMappings(mappings, inputGraph, false);
                        treatedNodes.Add(qGraph);
                    }
                    else
                    {
                        // Enumeration moodule - MODA
                        // This is part of Algo 3; but performance tweaks makes it more useful to get it here
                        var parentQueryGraph = GetParent(qGraph, _builder.ExpansionTree);
                        if (parentQueryGraph.EdgeCount == (subgraphSize - 1))
                        {
                            treatedNodes.Add(parentQueryGraph);
                        }
                        string _filename;
                        if (allMappings.TryGetValue(parentQueryGraph, out _filename))
                        {
                            string newFileName; // for parentQueryGraph
                            mappings = Algorithm3(null, inputGraph, qGraph, _builder.ExpansionTree, parentQueryGraph, out newFileName, _filename);
                            if (!string.IsNullOrWhiteSpace(newFileName))
                            {
                                // We change the _filename value in the dictionary since this means some of the mappings from parent fit the child
                                allMappings[parentQueryGraph] = newFileName;
                            }
                        }
                        else
                        {
                            mappings = new Mapping[0];
                        }
                    }

                    if (mappings.Count > thresholdValue)
                    {
                        qGraph.IsFrequentSubgraph = true;
                    }

                    // Save mappings.
                    var fileName = qGraph.WriteMappingsToFile(mappings);
                    if (mappings.Count > 0)
                    {
                        mappings.Clear();
                    }
                    allMappings.Add(qGraph, fileName);

                    // Check for complete-ness; if complete, break
                    if (qGraph.IsComplete(subgraphSize))
                    {
                        qGraph = null;
                        break;
                    }
                    qGraph = null;
                }while (true);
                #endregion
            }
            else
            {
                ICollection <Mapping> mappings;
                if (UseModifiedGrochow)
                {
                    // Modified Mapping module - MODA and Grockow & Kellis
                    mappings = Algorithm2_Modified(qGraph, inputGraph, numIterations, true);
                }
                else
                {
                    mappings = Algorithm2(qGraph, inputGraph, numIterations, true);
                }
                qGraph.RemoveNonApplicableMappings(mappings, inputGraph);
                var fileName = $"{mappings.Count}#{qGraph.Identifier}.ser";
                System.IO.File.WriteAllText(fileName, Extensions.CompressString(Newtonsoft.Json.JsonConvert.SerializeObject(mappings)));
                if (mappings.Count > 0)
                {
                    mappings.Clear();
                }
                allMappings = new Dictionary <QueryGraph, string>(1)
                {
                    { qGraph, fileName }
                };
            }

            return(allMappings);
        }
Esempio n. 3
0
        /// <summary>
        /// Mapping module; aka FindSubgraphInstances in Grochow & Kellis
        /// </summary>
        /// <param name="queryGraph">H</param>
        /// <param name="inputGraphClone">G</param>
        /// <param name="numberOfSamples">To be decided. If not set, we use the <paramref name="inputGraphClone"/> size / 3</param>
        internal static ICollection <Mapping> Algorithm2(QueryGraph queryGraph, UndirectedGraph <int> inputGraphClone, int numberOfSamples, bool getInducedMappingsOnly)
        {
            if (numberOfSamples <= 0)
            {
                numberOfSamples = inputGraphClone.VertexCount / 3;
            }

            // Do we need this clone? Can't we just remove the node directly from the graph?
            // We do need it.
            var theMappings        = new Dictionary <int[], List <Mapping> >(MappingNodesComparer);
            var inputGraphDegSeq   = inputGraphClone.GetNodesSortedByDegree(numberOfSamples);
            var queryGraphVertices = queryGraph.Vertices.ToArray();
            var queryGraphEdges    = queryGraph.Edges.ToArray();
            var subgraphSize       = queryGraphVertices.Length;
            var threadName         = System.Threading.Thread.CurrentThread.ManagedThreadId;

            Console.WriteLine("Thread {0}:\tCallingu Algo 2:\n", threadName);
            for (int i = 0; i < inputGraphDegSeq.Count; i++)
            {
                var g = inputGraphDegSeq[i];
                for (int j = 0; j < subgraphSize; j++)
                {
                    var h = queryGraphVertices[j];
                    if (Utils.CanSupport(queryGraph, h, inputGraphClone, g))
                    {
                        #region Can Support
                        //Remember: f(h) = g, so h is Domain and g is Range
                        var f = new Dictionary <int, int>(1);
                        f[h] = g;
                        var mappings = Utils.IsomorphicExtension(f, queryGraph, queryGraphEdges, inputGraphClone, getInducedMappingsOnly);
                        f.Clear();
                        f = null;
                        if (mappings.Count > 0)
                        {
                            foreach (var item in mappings)
                            {
                                if (item.Value.Count > 1)
                                {
                                    queryGraph.RemoveNonApplicableMappings(item.Value, inputGraphClone, getInducedMappingsOnly);
                                }
                                //Recall: f(h) = g
                                List <Mapping> maps;
                                if (theMappings.TryGetValue(item.Key, out maps))
                                {
                                    maps.AddRange(item.Value);
                                }
                                else
                                {
                                    theMappings[item.Key] = item.Value;
                                }
                            }
                            mappings.Clear();
                        }
                        mappings = null;
                        #endregion
                    }
                }

                //Remove g
                inputGraphClone.RemoveVertex(g);
                if (inputGraphClone.EdgeCount == 0)
                {
                    break;
                }
            }
            Array.Clear(queryGraphEdges, 0, queryGraphEdges.Length);
            queryGraphEdges = null;
            Array.Clear(queryGraphVertices, 0, subgraphSize);
            queryGraphVertices = null;
            inputGraphDegSeq.Clear();
            inputGraphDegSeq = null;

            var toReturn = GetSet(theMappings);
            theMappings = null;

            Console.WriteLine("Thread {0}:\tAlgorithm 2: All tasks completed. Number of mappings found: {1}.", threadName, toReturn.Count);
            return(toReturn);
        }