Skip to contents

Match two given graphs, returns a list of graph matching results, including matching correspondence vector of \(G_2\) with respect to \(G_1\), doubly stochastic matrix and permutation matrix.

Usage

graph_match_convex(
  A,
  B,
  seeds = NULL,
  similarity = NULL,
  start = "bari",
  max_iter = 100,
  tol = 1e-05,
  lap_method = NULL
)

graph_match_indefinite(
  A,
  B,
  seeds = NULL,
  similarity = NULL,
  start = "bari",
  max_iter = 20,
  lap_method = NULL
)

graph_match_PATH(
  A,
  B,
  seeds = NULL,
  similarity = NULL,
  epsilon = 1,
  tol = 1e-05,
  max_iter = 20,
  lap_method = NULL
)

Arguments

A

A matrix, igraph object, or list of either.

B

A matrix, igraph object, or list of either.

seeds

A vector of integers or logicals, a matrix or a data frame. If the seed pairs have the same indices in both graphs then seeds can be a vector. If not, seeds must be a matrix or a data frame, with the first column being the indices of \(G_1\) and the second column being the corresponding indices of \(G_2\).

similarity

A matrix. An n-by-n matrix containing vertex similarities.

start

A matrix or a character. Any nns-by-nns matrix or character value like "bari", "rds" or "convex" to initialize the starting matrix.

max_iter

A number. Maximum number of replacing matches.

tol

A number. Tolerance of edge disagreements.

lap_method

Choice for lap method. One of "lapjv", "lapmod", or "clue".

epsilon

A small number

Value

graph_match_indefinite, graph_match_convex and graph_match_PATH

return an object of class "graphMatch" which is a list containing the following components:

corr_A

matching correspondence in \(G_1\)

corr_B

matching correspondence in \(G_2\)

soft

the doubly stochastic matrix from the last iteration with which one can extract more than one matching candidates

iter

number of iterations until convergence or reaches the max_iter

max_iter

Maximum number of replacing matches

lap_method

Choice for solving the LAP

seeds

a vector of logicals indicating if the corresponding vertex is a seed

References

Y. Aflalo and A. Bronstein and R. Kimmel (2014), On convex relaxation of graph isomorphism. Proceedings of the National Academy of Sciences, pages 2942-2947.

V. Lyzinski and D. E. Fishkind and M. Fiori and J. T. Vogelstein and C. E. Priebe and G. Sapiro (2016), Graph Matching: Relax at Your Own Risk. IEEE TPAMI, pages 60-73.

V. Lyzinski and D. E. Fishkind and C. E. Priebe (2014), Seeded Graph Matching for Correlated Erdos-Renyi Graphs.J. Mach. Learn. Res., pages 3513-3540.

M. Zaslavskiy, F. Bach and J. Vert (2009), A Path following algorithm for the graph matching problem. IEEE Trans Pattern Anal Mach Intell, pages 2227-2242.

Examples

# \donttest{
cgnp_pair <- sample_correlated_gnp_pair(n = 10, corr =  0.9, p =  0.5)
g1 <- cgnp_pair$graph1
g2 <- cgnp_pair$graph2
# match G_1 & G_2 with no seeds
gm(g1, g2, method = "convex", max_iter = 10)
#> Warning: Frank-Wolfe iterations reach the maximum iteration, convergence may not occur.
#> gm(A = g1, B = g2, method = "convex", max_iter = 10)
#> 
#> Match (10 x 10):
#>    corr_A corr_B
#> 1       1      7
#> 2       2      2
#> 3       3      3
#> 4       4      4
#> 5       5      5
#> 6       6      6
#> 7       7      1
#> 8       8      9
#> 9       9      8
#> 10     10     10
seeds <- 1:10 <= 3
gm(g1, g2, seeds, method = "convex", max_iter = 10)
#> Warning: Frank-Wolfe iterations reach the maximum iteration, convergence may not occur.
#> gm(A = g1, B = g2, seeds = seeds, method = "convex", max_iter = 10)
#> 
#> Match (10 x 10):
#>    corr_A corr_B
#> 1       1      1
#> 2       2      2
#> 3       3      3
#> 4       4      4
#> 5       5      5
#> 6       6      6
#> 7       7      7
#> 8       8      8
#> 9       9      9
#> 10     10     10
# }



# match G_1 & G_2 with some known node pairs as seeds
cgnp_pair <- sample_correlated_gnp_pair(n = 10, corr =  0.3, p =  0.5)
g1 <- cgnp_pair$graph1
g2 <- cgnp_pair$graph2
seeds <- 1:10 <= 3
GM_bari <- gm(g1, g2, seeds, method = "indefinite", start = "bari")
GM_bari
#> gm(A = g1, B = g2, seeds = seeds, method = "indefinite", start = "bari")
#> 
#> Match (10 x 10):
#>    corr_A corr_B
#> 1       1      1
#> 2       2      2
#> 3       3      3
#> 4       4      4
#> 5       5      7
#> 6       6      6
#> 7       7      8
#> 8       8      5
#> 9       9      9
#> 10     10     10
GM_bari[!GM_bari$seeds] # matching correspondence for non-seeds
#>    corr_A corr_B
#> 4       4      4
#> 5       5      7
#> 6       6      6
#> 7       7      8
#> 8       8      5
#> 9       9      9
#> 10     10     10

summary(GM_bari, g1, g2, true_label = 1:10)
#> Call: gm(A = g1, B = g2, seeds = seeds, method = "indefinite", start = "bari")
#> 
#> # Matches: 7
#> # True Matches:  4, # Seeds:  3, # Vertices:  10, 10
#>                        
#>   common_edges 16.00000
#>  missing_edges  3.00000
#>    extra_edges 10.00000
#>          fnorm  5.09902

# match G_1 & G_2 with some incorrect seeds
hard_seeds <- matrix(c(4,6,5,4),2)
seeds <- rbind(as.matrix(check_seeds(seeds, nv = 10)$seeds),hard_seeds)
GM_badseed <- gm(g1, g2, seeds, method = "indefinite")

GM_badseed[] # get the corresponding permutation matrix
#> 10 x 10 sparse Matrix of class "dgCMatrix"
#>                          
#>  [1,] 1 . . . . . . . . .
#>  [2,] . 1 . . . . . . . .
#>  [3,] . . 1 . . . . . . .
#>  [4,] . . . . 1 . . . . .
#>  [5,] . . . . . . . . . 1
#>  [6,] . . . 1 . . . . . .
#>  [7,] . . . . . . 1 . . .
#>  [8,] . . . . . 1 . . . .
#>  [9,] . . . . . . . . 1 .
#> [10,] . . . . . . . 1 . .
GM_badseed %*% g2 # permute the second graph according to match result: PBP^T
#> IGRAPH 8771406 UN-- 10 26 -- Erdos-Renyi (gnp) graph
#> + attr: name_1 (g/c), name_2 (g/c), type_1 (g/c), type_2 (g/c), loops_1
#> | (g/l), loops_2 (g/l), p_1 (g/n), p_2 (g/n), name (g/c), type (g/c),
#> | loops (g/l), p (g/n), name (v/n)
#> + edges from 8771406 (vertex names):
#>  [1]  8-- 9  7--10  7-- 9  8-- 7  6-- 9  6-- 7 10-- 5  9-- 5  8-- 5  7-- 5
#> [11]  6-- 5  4--10  4-- 9  6-- 4  3-- 9  3-- 8  3-- 6  3-- 5  2--10  2-- 8
#> [21]  2-- 4  2-- 3  1-- 8  1-- 7  1-- 4  1-- 2
GM_badseed$soft # doubly stochastic matrix from the last step of Frank-Wolfe iterations
#> 10 x 10 sparse Matrix of class "dgCMatrix"
#>                          
#>  [1,] 1 . . . . . . . . .
#>  [2,] . 1 . . . . . . . .
#>  [3,] . . 1 . . . . . . .
#>  [4,] . . . . 1 . . . . .
#>  [5,] . . . . . . . . . 1
#>  [6,] . . . 1 . . . . . .
#>  [7,] . . . . . . 1 . . .
#>  [8,] . . . . . 1 . . . .
#>  [9,] . . . . . . . . 1 .
#> [10,] . . . . . . . 1 . .
GM_badseed$iter # number of iterations
#> [1] 3
GM_badseed$max_iter # preset maximum number of iterations: 20
#> [1] 20

# match two multi-layer graphs
gp_list <- replicate(3, sample_correlated_gnp_pair(20, .3, .5), simplify = FALSE)
A <- lapply(gp_list, function(gp)gp[[1]])
B <- lapply(gp_list, function(gp)gp[[2]])

match_multi_layer <- gm(A, B, seeds = 1:10, method = "indefinite", start = "bari", max_iter = 20)
summary(match_multi_layer, A, B)
#> Call: gm(A = A, B = B, seeds = 1:10, method = "indefinite", start = "bari", 
#>     max_iter = 20)
#> 
#> # Matches: 10, # Seeds:  10, # Vertices:  20, 20
#>          layer       1        2        3
#>   common_edges 65.0000 60.00000 69.00000
#>  missing_edges 37.0000 30.00000 34.00000
#>    extra_edges 31.0000 30.00000 35.00000
#>          fnorm 11.6619 10.95445 11.74734

# match G_1 & G_2 using PATH algorithm
gm(g1, g2, method = "PATH")
#> Warning: Frank-Wolfe iterations reach the maximum iteration, convergence may not occur.
#> gm(A = g1, B = g2, method = "PATH")
#> 
#> Match (10 x 10):
#>    corr_A corr_B
#> 1       1      4
#> 2       2      1
#> 3       3      9
#> 4       4     10
#> 5       5      5
#> 6       6      3
#> 7       7      6
#> 8       8      2
#> 9       9      8
#> 10     10      7