Esempio n. 1
0
        public void ElementPseudo()
        {
            AtomMatcher matcher = AtomMatcher.CreateElementMatcher();
            var         m_atom1 = new Mock <IPseudoAtom>();
            var         m_atom2 = new Mock <IPseudoAtom>();

            Assert.IsTrue(matcher.Matches(m_atom1.Object, m_atom2.Object));
            Assert.IsTrue(matcher.Matches(m_atom2.Object, m_atom1.Object));
        }
Esempio n. 2
0
        public void ElementMismatch()
        {
            AtomMatcher matcher = AtomMatcher.CreateElementMatcher();
            var         m_atom1 = new Mock <IAtom>();
            var         m_atom2 = new Mock <IAtom>();

            m_atom1.SetupGet(n => n.AtomicNumber).Returns(6);
            m_atom2.SetupGet(n => n.AtomicNumber).Returns(8);
            Assert.IsFalse(matcher.Matches(m_atom1.Object, m_atom2.Object));
            Assert.IsFalse(matcher.Matches(m_atom2.Object, m_atom1.Object));
        }
Esempio n. 3
0
        public void QueryMatch()
        {
            AtomMatcher matcher = AtomMatcher.CreateQueryMatcher();
            var         m_atom1 = new Mock <IQueryAtom>();
            var         m_atom2 = new Mock <IAtom>();
            var         m_atom3 = new Mock <IAtom>();

            m_atom1.Setup(n => n.Matches(m_atom2.Object)).Returns(true);
            m_atom1.Setup(n => n.Matches(m_atom3.Object)).Returns(false);
            Assert.IsTrue(matcher.Matches(m_atom1.Object, m_atom2.Object));
            Assert.IsFalse(matcher.Matches(m_atom1.Object, m_atom3.Object));
        }
Esempio n. 4
0
        /// <summary>
        /// Create a state for matching subgraphs using the Ullmann refinement
        /// procedure.
        /// </summary>
        /// <param name="container1">query container</param>
        /// <param name="container2">target container</param>
        /// <param name="g1">query container adjacency list</param>
        /// <param name="g2">target container adjacency list</param>
        /// <param name="bonds1">query container bond map</param>
        /// <param name="bonds2">target container bond map</param>
        /// <param name="atomMatcher">method of matching atom semantics</param>
        /// <param name="bondMatcher">method of matching bond semantics</param>
        public UllmannState(IAtomContainer container1, IAtomContainer container2, int[][] g1, int[][] g2,
                            EdgeToBondMap bonds1, EdgeToBondMap bonds2, AtomMatcher atomMatcher, BondMatcher bondMatcher)
        {
            this.bondMatcher = bondMatcher;
            this.g1          = g1;
            this.g2          = g2;
            this.bond1       = bonds1;
            this.bonds2      = bonds2;
            this.m1          = new int[g1.Length];
            this.m2          = new int[g2.Length];
            Arrays.Fill(m1, UNMAPPED);
            Arrays.Fill(m2, UNMAPPED);

            // build up compatibility matrix
            matrix = new CompatibilityMatrix(g1.Length, g2.Length);
            for (int i = 0; i < g1.Length; i++)
            {
                for (int j = 0; j < g2.Length; j++)
                {
                    if (g1[i].Length <= g2[j].Length && atomMatcher.Matches(container1.Atoms[i], container2.Atoms[j]))
                    {
                        matrix.Set1(i, j);
                    }
                }
            }
        }
Esempio n. 5
0
        public void AnyMatch()
        {
            AtomMatcher matcher = AtomMatcher.CreateAnyMatcher();
            var         m_atom1 = new Mock <IAtom>();
            var         m_atom2 = new Mock <IAtom>();
            var         m_atom3 = new Mock <IAtom>();

            m_atom1.SetupGet(n => n.AtomicNumber).Returns(6);
            m_atom2.SetupGet(n => n.AtomicNumber).Returns(7);
            m_atom3.SetupGet(n => n.AtomicNumber).Returns(8);
            Assert.IsTrue(matcher.Matches(m_atom1.Object, m_atom2.Object));
            Assert.IsTrue(matcher.Matches(m_atom2.Object, m_atom1.Object));
            Assert.IsTrue(matcher.Matches(m_atom1.Object, m_atom3.Object));
            Assert.IsTrue(matcher.Matches(m_atom3.Object, m_atom1.Object));
            Assert.IsTrue(matcher.Matches(m_atom2.Object, m_atom3.Object));
            Assert.IsTrue(matcher.Matches(m_atom1.Object, null));
            Assert.IsTrue(matcher.Matches(null, null));
        }
Esempio n. 6
0
        /// <summary>
        /// Check the feasibility of the candidate pair {n, m}.
        /// </summary>
        /// <remarks>
        /// <para>
        /// A candidate pair is
        /// syntactically feasible iff all k-look-ahead rules hold. These look ahead
        /// rules check adjacency relation of the mapping. If an edge is mapped in g1
        /// it should also be mapped in g2 and vise-versa (0-look-ahead). If an edge
        /// in g1 is unmapped but the edge is adjacent to an another mapped vertex
        /// (terminal) then the number of such edges should be less or equal in g1
        /// compared to g2 (1-look-ahead). If the edge is unmapped and non-terminal
        /// then the number of such edges should be less or equal in g1 compared to
        /// g2 (2-look-ahead).
        /// </para>
        /// <para>
        /// The above feasibility rules are for
        /// subgraph-isomorphism and have been adapted for subgraph-monomorphism. For
        /// a monomorphism a mapped edge in g2 does not have to be present in g1. The
        /// 2-look-ahead also requires summing the terminal and remaining counts (or
        /// sorting the vertices).
        /// </para>
        /// <para>
        /// The semantic feasibility verifies that the
        /// labels the label n, m are compatabile and that the label on each matched
        /// edge is compatabile.
        /// </para>
        /// </remarks>
        /// <param name="n">a candidate vertex from g1</param>
        /// <param name="m">a candidate vertex from g2</param>
        /// <returns>the mapping is feasible</returns>
        public override bool Feasible(int n, int m)
        {
            // verify atom semantic feasibility
            if (!atomMatcher.Matches(container1.Atoms[n], container2.Atoms[m]))
            {
                return(false);
            }

            // unmapped terminal vertices n and m are adjacent to
            int nTerminal1 = 0, nTerminal2 = 0;
            // unmapped non-terminal (remaining) vertices n and m are adjacent to
            int nRemain1 = 0, nRemain2 = 0;

            // 0-look-ahead: check each adjacent edge for being mapped, and count
            // terminal or remaining
            foreach (var n_prime in g1[n])
            {
                var m_prime = m1[n_prime];

                // v is already mapped, there should be an edge {m, w} in g2.
                if (m_prime != UNMAPPED)
                {
                    var bond2 = bonds2[m, m_prime];
                    if (bond2 == null) // the bond is not present in the target
                    {
                        return(false);
                    }
                    // verify bond semantic feasibility
                    if (!bondMatcher.Matches(bonds1[n, n_prime], bond2))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (t1[n_prime] > 0)
                    {
                        nTerminal1++;
                    }
                    else
                    {
                        nRemain1++;
                    }
                }
            }

            // monomorphism: each mapped edge in g2 doesn't need to be in g1 so
            // only the terminal and remaining edges are counted
            foreach (var m_prime in g2[m])
            {
                if (m2[m_prime] == UNMAPPED)
                {
                    if (t2[m_prime] > 0)
                    {
                        nTerminal2++;
                    }
                    else
                    {
                        nRemain2++;
                    }
                }
            }

            // 1-look-ahead : the mapping {n, m} is feasible iff the number of
            // terminal vertices (t1) adjacent to n is less than or equal to the
            // number of terminal vertices (t2) adjacent to m.
            //
            // 2-look-ahead: the mapping {n, m} is feasible iff the number of
            // vertices adjacent to n that are neither in m1 or t1 is less than or
            // equal to the number of the number of vertices adjacent to m that
            // are neither in m2 or t2. To allow mapping of monomorphisms we add the
            // number of adjacent terminal vertices.
            return(nTerminal1 <= nTerminal2 && (nRemain1 + nTerminal1) <= (nRemain2 + nTerminal2));
        }
Esempio n. 7
0
        /// <summary>
        /// Check the feasibility of the candidate pair {n, m}. A candidate pair is
        /// syntactically feasible iff all k-look-ahead rules hold. These look ahead
        /// rules check adjacency relation of the mapping. If an edge is mapped in g1
        /// it should also be mapped in g2 and vise-versa (0-look-ahead). If an edge
        /// in g1 is unmapped but the edge is adjacent to an another mapped vertex
        /// (terminal) then the number of such edges should be equal in g1 compared
        /// to g2 (1-look-ahead). If the edge is unmapped and non-terminal then the
        /// number of such edges should be equal in g1 compared to g2 (2-look-ahead).
        /// </summary>
        /// <param name="n">a candidate vertex from g1</param>
        /// <param name="m">a candidate vertex from g2</param>
        /// <returns>the mapping is feasible</returns>
        public override bool Feasible(int n, int m)
        {
            // verify atom semantic feasibility
            if (!atomMatcher.Matches(container1.Atoms[n], container2.Atoms[m]))
            {
                return(false);
            }

            // unmapped terminal vertices n and m are adjacent to
            int nTerminal1 = 0, nTerminal2 = 0;
            // unmapped non-terminal (remaining) vertices n and m are adjacent to
            int nRemain1 = 0, nRemain2 = 0;

            // 0-look-ahead: check each adjacent edge for being mapped, and count
            // terminal or remaining
            foreach (var n_prime in g1[n])
            {
                int m_prime = m1[n_prime];

                // v is already mapped, there should be an edge {m, w} in g2.
                if (m_prime != UNMAPPED)
                {
                    IBond bond2 = bonds2[m, m_prime];
                    // the bond is not present in the target
                    if (bond2 == null)
                    {
                        return(false);
                    }
                    // verify bond semantic feasibility
                    if (!bondMatcher.Matches(bonds1[n, n_prime], bond2))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (t1[n_prime] > 0)
                    {
                        nTerminal1++;
                    }
                    else
                    {
                        nRemain1++;
                    }
                }
            }

            // 0-look-ahead: check each adjacent edge for being mapped, and count
            // terminal or remaining
            foreach (var m_prime in g2[m])
            {
                int n_prime = m2[m_prime];

                if (n_prime != UNMAPPED)
                {
                    IBond bond1 = bonds1[n, n_prime];
                    // the bond is not present in the query
                    if (bond1 == null)
                    {
                        return(false);
                    }
                    // verify bond semantic feasibility
                    if (!bondMatcher.Matches(bond1, bonds2[m, m_prime]))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (t2[m_prime] > 0)
                    {
                        nTerminal2++;
                    }
                    else
                    {
                        nRemain2++;
                    }
                }
            }

            // 1-look-ahead : the mapping {n, m} is feasible iff the number of
            // terminal vertices (t1) adjacent to n is equal to the
            // number of terminal vertices (t2) adjacent to m.
            //
            // 2-look-ahead: the mapping {n, m} is feasible iff the number of
            // vertices adjacent to n that are neither in m1 or t1 is equal to
            // the number of the number of vertices adjacent to m that are neither
            // in m2 or t2.
            return(nTerminal1 == nTerminal2 && nRemain1 == nRemain2);
        }