コード例 #1
0
ファイル: GraphMatch.py プロジェクト: malcolmreynolds/APGL
    def distance2(self, graph1, graph2, permutation):
        """
        Compute a graph distance metric between two graphs give a permutation 
        vector. This is given by F(P) = (1-alpha)/(||W1||^2_F + ||W2||^2_F)
        (||W1 - P W2 P.T||^2_F) - alpha 1/(||V1||_F^2 + ||V2||_F^2) ||V1 - P.T V2||^2_F 
        and is bounded between 0 and 1. 
        
        :param graph1: A graph object 
        
        :param graph2: The second graph object to match 
        
        :param permutation: An array of permutation indices matching the first to second graph 
        :type permutation: `numpy.ndarray`
        
        """
        if self.useWeightM:         
            W1 = graph1.getWeightMatrix()
            W2 = graph2.getWeightMatrix()
        else: 
            W1 = graph1.adjacencyMatrix()
            W2 = graph2.adjacencyMatrix()
        
        if W1.shape[0] < W2.shape[0]: 
            W1 = Util.extendArray(W1, W2.shape)
        elif W2.shape[0] < W1.shape[0]:
            W2 = Util.extendArray(W2, W1.shape)
        
        n = W1.shape[0]
        P = numpy.zeros((n, n)) 
        P[(numpy.arange(n), permutation)] = 1
        dist1 = numpy.linalg.norm(W1 - P.dot(W2).dot(P.T))**2
        
        #Now compute the vertex similarities distance         
        V1 = graph1.getVertexList().getVertices()
        V2 = graph2.getVertexList().getVertices()
        
        if V1.shape[0] < V2.shape[0]: 
            V1 = Util.extendArray(V1, V2.shape)
        elif V2.shape[0] < V1.shape[0]: 
            V2 = Util.extendArray(V2, V1.shape)
        
        dist2 = numpy.sum((V1 - P.T.dot(V2))**2)

        norm1 = ((W1**2).sum() + (W2**2).sum())
        norm2 = ((V1**2).sum() + (V2**2).sum())
        
        if norm1!= 0: 
            dist1 = dist1/norm1
        if norm2!= 0:
            dist2 = dist2/norm2         
        
        dist = (1-self.alpha)*dist1 + self.alpha*dist2
        
        return dist 
コード例 #2
0
 def testExtendArray(self): 
     X = numpy.random.rand(5, 5)
     X2 = Util.extendArray(X, (10, 5))
     
     nptst.assert_array_equal(X, X2[0:5, :])
     nptst.assert_array_equal(0, X2[5:, :])          
     
     X2 = Util.extendArray(X, (10, 5), 1.23)
     
     nptst.assert_array_equal(X, X2[0:5, :])
     nptst.assert_array_equal(1.23, X2[5:, :])  
     
     #Now try extending using an array 
     X2 = Util.extendArray(X, (10, 5), numpy.array([1, 2, 3, 4, 5]))
     nptst.assert_array_equal(X, X2[0:5, :])
     
     for i in range(5, 10): 
         nptst.assert_array_equal(numpy.array([1, 2, 3, 4, 5]), X2[i, :])          
コード例 #3
0
ファイル: GraphMatch.py プロジェクト: malcolmreynolds/APGL
    def distance(self, graph1, graph2, permutation, normalised=False, nonNeg=False, verbose=False):
        """
        Compute the graph distance metric between two graphs given a permutation 
        vector. This is given by F(P) = (1-alpha)/(||W1||^2_F + ||W2||^2_F)(||W1 - P W2 P.T||^2_F)
        - alpha 1/||C||_F tr(C.T P) in the normalised case. If we want an unnormalised 
        solution it is computed as (1-alpha)/(||W1 - P W2 P.T||^2_F) - alpha tr C.T P 
        and finally there is a standardised case in which the distance is between 
        0 and 1, where ||C||_F is used to normalise the vertex similarities and 
        we assume 0 <= C_ij <= 1. 
        
        :param graph1: A graph object 
        
        :param graph2: The second graph object to match 
        
        :param permutation: An array of permutation indices matching the first to second graph 
        :type permutation: `numpy.ndarray`
        
        :param normalised: Specify whether to normalise the objective function 
        :type normalised: `bool`
        
        :param nonNeg: Specify whether we want a non-negative solution.  
        :type nonNeg: `bool`
        
        :param verbose: Specify whether to return graph and label distance 
        :type nonNeg: `bool`
        """
        if graph1.size == 0 and graph2.size == 0: 
            if not verbose: 
                return 0.0
            else: 
                return 0.0, 0.0, 0.0
        elif graph1.size == 0 or graph2.size == 0: 
            if normalised: 
                if not verbose: 
                    return 1-self.alpha
                else: 
                    return 1-self.alpha, 1-self.alpha, 0.0
            else: 
                raise ValueError("Unsupported case")
        
        if self.useWeightM:         
            W1 = graph1.getWeightMatrix()
            W2 = graph2.getWeightMatrix()
        else: 
            W1 = graph1.adjacencyMatrix()
            W2 = graph2.adjacencyMatrix()
        
        if W1.shape[0] < W2.shape[0]: 
            W1 = Util.extendArray(W1, W2.shape, self.rho)
        elif W2.shape[0] < W1.shape[0]:
            W2 = Util.extendArray(W2, W1.shape, self.rho)
        
        n = W1.shape[0]
        P = numpy.zeros((n, n)) 
        P[(numpy.arange(n), permutation)] = 1
        dist1 = numpy.linalg.norm(W1 - P.dot(W2).dot(P.T))**2
        
        #Now compute the vertex similarities trace         
        C = self.vertexSimilarities(graph1, graph2)
        minC = numpy.min(C)
        maxC = numpy.max(C)
        C = Util.extendArray(C, (n, n), minC + self.gamma*(maxC-minC))

        dist2 = numpy.trace(C.T.dot(P))
        
        if normalised: 
            norm1 = ((W1**2).sum() + (W2**2).sum())
            norm2 = numpy.linalg.norm(C) 
            if norm1!= 0: 
                dist1 = dist1/norm1
            if norm2!= 0:
                dist2 = dist2/norm2
        
        dist = (1-self.alpha)*dist1 - self.alpha*dist2
        
        #If nonNeg = True then we add a term to the distance to ensure it is 
        #always positive. The numerator is an upper bound on tr(C.T P)
        if nonNeg and normalised:
            normC = norm2
    
            logging.debug("Graph distance: " + str(dist1) + " label distance: " + str(dist2) + " distance offset: " + str(self.alpha*n/normC) + " graph sizes: " + str((graph1.size, graph2.size)))           

            if normC != 0: 
                dist = dist + self.alpha*n/normC 
        else: 
            logging.debug("Graph distance: " + str(dist1) + " label distance: " + str(dist2) + " graph sizes: " + str((graph1.size, graph2.size)))   
        
        if verbose: 
            return dist, dist1, dist2
        else: 
            return dist 
コード例 #4
0
 def addVertices(self, n):
     """
     Adds n vertices to this object. 
     """
     self.V = Util.extendArray(self.V,
                               (self.V.shape[0] + n, self.V.shape[1]))
コード例 #5
0
 def addVertices(self, n): 
     """
     Adds n vertices to this object. 
     """
     self.V = Util.extendArray(self.V, (self.V.shape[0] + n, self.V.shape[1]))