Пример #1
0
        /// <summary>
        /// Compute the tree edit distance
        /// </summary>
        /// <returns>Returns a tuple. The first item is the cost. The second item is the
        /// sequence of edit operations</returns>
        public EditDistance  Compute()
        {
            GenerateNodes(PreviousTree, CurrentTree);
            _l1 = ComputeL(T1, A);
            _l2 = ComputeL(T2, B);
            _k1 = ComputeK(T1, _l1);
            _k2 = ComputeK(T2, _l2);

            _treedists = new EditDistance[T1.Length + 1, T2.Length + 1];

            _treedists[0, 0] = new EditDistance()
            {
                Distance = 0
            };

            foreach (var x in _k1)
            {
                foreach (var y in _k2)
                {
                    Treedists(x, y);
                }
            }

            return(_treedists[T1.Length, T2.Length]);
        }
Пример #2
0
        private void Treedists(int i, int j)
        {
            var m = i - _l1[i] + 2;
            var n = j - _l2[j] + 2;

            var fd = new EditDistance[m, n];

            fd[0, 0] = new EditDistance()
            {
                Distance = 0
            };
            var ioff = _l1[i] - 1;
            var joff = _l2[j] - 1;

            for (int x = 1; x < m; x++)
            {
                var edits      = new List <Edit>(fd[x - 1, 0].Edits);
                var pythonNode = A[x + ioff - 1];
                edits.Add(new Delete(pythonNode, pythonNode.Parent));
                fd[x, 0] = new EditDistance()
                {
                    Distance = fd[x - 1, 0].Distance + 1, Edits = edits, Mapping = new Dictionary <PythonNode, PythonNode>(fd[x - 1, 0].Mapping)
                };
            }
            for (int y = 1; y < n; y++)
            {
                var node  = B[y - 1 + joff];
                var edits = new List <Edit>(fd[0, y - 1].Edits);
                edits.Add(new Insert(node, node.Parent));
                fd[0, y] = new EditDistance()
                {
                    Distance = fd[0, y - 1].Distance + 1, Edits = edits, Mapping = new Dictionary <PythonNode, PythonNode>(fd[0, y - 1].Mapping)
                };
            }

            for (int x = 1; x < m; x++)
            {
                for (int y = 1; y < n; y++)
                {
                    if (_l1[i] == _l1[x + ioff] && _l2[j] == _l2[y + joff])
                    {
                        var value = Math.Min(Math.Min(fd[x - 1, y].Distance + 1,                                        //cost to remove is 1
                                                      fd[x, y - 1].Distance + 1),                                       //cost to insert is 1
                                             fd[x - 1, y - 1].Distance + CostUpdate(A[x + ioff - 1], B[y + joff - 1])); //cost to Edit depends

                        List <Edit> edits;
                        Dictionary <PythonNode, PythonNode> mapping;
                        if (value == fd[x - 1, y].Distance + 1)
                        {
                            var node = A[x - 1 + ioff];
                            edits = new List <Edit>(fd[x - 1, y].Edits)
                            {
                                new Delete(node, node.Parent)
                            };
                            mapping = new Dictionary <PythonNode, PythonNode>(fd[x - 1, y].Mapping);
                        }
                        else if (value == fd[x, y - 1].Distance + 1)
                        {
                            var node = B[y - 1 + joff];
                            edits = new List <Edit>(fd[x, y - 1].Edits)
                            {
                                new Insert(node, node.Parent)
                            };
                            mapping = new Dictionary <PythonNode, PythonNode>(fd[x, y - 1].Mapping);
                        }
                        else
                        {
                            edits = new List <Edit>(fd[x - 1, y - 1].Edits);
                            var oldNode = A[x + ioff - 1];
                            var newNode = B[y + joff - 1];

                            if (CostUpdate(oldNode, newNode) > 0)
                            {
                                edits.Add(new Update(newNode, oldNode));
                            }

                            mapping = new Dictionary <PythonNode, PythonNode>(fd[x - 1, y - 1].Mapping);

                            if (mapping.ContainsKey(newNode))
                            {
                                mapping.Remove(newNode);
                            }

                            mapping.Add(newNode, oldNode);
                        }

                        fd[x, y] = new EditDistance()
                        {
                            Distance = value, Edits = edits, Mapping = mapping
                        };
                        _treedists[x + ioff, y + joff] = fd[x, y];
                    }
                    else
                    {
                        var p = _l1[x + ioff] - 1 - ioff;
                        var q = _l2[y + joff] - 1 - joff;

                        var value = Math.Min(fd[p, q].Distance + _treedists[x + ioff, y + joff].Distance,
                                             Math.Min(fd[x - 1, y].Distance + 1, fd[x, y - 1].Distance + 1));

                        List <Edit> edits;
                        Dictionary <PythonNode, PythonNode> mapping;
                        if (value == fd[p, q].Distance + _treedists[x + ioff, y + joff].Distance)
                        {
                            edits = new List <Edit>(fd[p, q].Edits);
                            edits.AddRange(_treedists[x + ioff, y + joff].Edits);
                            mapping = new Dictionary <PythonNode, PythonNode>(fd[p, q].Mapping);
                            foreach (var keyValuePair in _treedists[x + ioff, y + joff].Mapping)
                            {
                                //todo there is problem a bug here
                                //it should check whether the maps come from each one of them.
                                if (mapping.ContainsKey(keyValuePair.Key))
                                {
                                    mapping.Remove(keyValuePair.Key);
                                }

                                PythonNode key = null;
                                foreach (var keyValue in mapping)
                                {
                                    if (keyValue.Value.Equals(keyValuePair.Value))
                                    {
                                        key = keyValue.Key;
                                    }
                                }
                                if (key != null)
                                {
                                    mapping.Remove(key);
                                }

                                mapping.Add(keyValuePair.Key, keyValuePair.Value);
                            }
                        }
                        else if (value == fd[x - 1, y].Distance + 1)
                        {
                            edits = new List <Edit>(fd[x - 1, y].Edits);
                            var pythonNode = A[x - 1 + ioff];
                            edits.Add(new Delete(pythonNode, pythonNode.Parent));
                            mapping = new Dictionary <PythonNode, PythonNode>(fd[x - 1, y].Mapping);
                        }
                        else
                        {
                            edits = new List <Edit>(fd[x, y - 1].Edits);
                            var pythonNode = B[y - 1 + joff];
                            edits.Add(new Insert(pythonNode, pythonNode.Parent));
                            mapping = new Dictionary <PythonNode, PythonNode>(fd[x, y - 1].Mapping);
                        }

                        fd[x, y] = new EditDistance()
                        {
                            Distance = value, Edits = edits, Mapping = mapping
                        };
                    }
                }
            }
        }