Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added strong_product, disjunctive_product, lexicographical_product, h… #154

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions src/Graphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ export
join,
tensor_product,
cartesian_product,
strong_product,
disjunctive_product,
lexicographic_product,
homomorphic_product,
crosspath,
induced_subgraph,
egonet,
Expand Down
226 changes: 226 additions & 0 deletions src/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ end
Return the [cartesian product](https://en.wikipedia.org/wiki/Cartesian_product_of_graphs)
of `g` and `h`.

The cartesian product has edges (g₁, h₁) ∼ (g₂, h₂) when
(g₁ = g₂ ∧ h₁ ∼ h₂) ∨ (g₁ ∼ g₂ ∧ h₁ = h₂).

### Implementation Notes
Preserves the eltype of the input graph. Will error if the number of vertices
in the generated graph exceeds the eltype.
Expand Down Expand Up @@ -575,6 +578,8 @@ end
Return the [tensor product](https://en.wikipedia.org/wiki/Tensor_product_of_graphs)
of `g` and `h`.

The tensor product has edges (g₁, h₁) ∼ (g₂, h₂) when g₁ ∼ g₂ ∧ h₁ ∼ h₂.

### Implementation Notes
Preserves the eltype of the input graph. Will error if the number of vertices
in the generated graph exceeds the eltype.
Expand Down Expand Up @@ -615,6 +620,227 @@ function tensor_product(g::G, h::G) where {G<:AbstractGraph}
return z
end

"""
strong_product(g, h)

Return the [strong product](https://en.wikipedia.org/wiki/Strong_product_of_graphs)
of `g` and `h`.
dstahlke marked this conversation as resolved.
Show resolved Hide resolved

The strong product has edges (g₁, h₁) ∼ (g₂, h₂) when
(g₁ = g₂ ∧ h₁ ∼ h₂) ∨ (g₁ ∼ g₂ ∧ h₁ = h₂) ∨ (g₁ ∼ g₂ ∧ h₁ ∼ h₂).

### Implementation Notes
Preserves the eltype of the input graph. Will error if the number of vertices
in the generated graph exceeds the eltype.

# Examples
```jldoctest
julia> using Graphs

julia> a = star_graph(3);

julia> b = path_graph(3);

julia> g = strong_product(a, b)
{9, 20} undirected simple Int64 graph

julia> g == union(cartesian_product(a, b), tensor_product(a, b))
true
```
"""
function strong_product(g::G, h::G) where {G<:AbstractSimpleGraph}
z = G(nv(g) * nv(h))
id(i, j) = (i - 1) * nv(h) + j
undirected = !is_directed(g)
for e1 in edges(g)
i1, i2 = Tuple(e1)
for e2 in edges(h)
j1, j2 = Tuple(e2)
add_edge!(z, id(i1, j1), id(i2, j2))
if undirected
add_edge!(z, id(i1, j2), id(i2, j1))
end
end
end
for e in edges(g)
i1, i2 = Tuple(e)
for j in vertices(h)
add_edge!(z, id(i1, j), id(i2, j))
end
end
for e in edges(h)
j1, j2 = Tuple(e)
for i in vertices(g)
add_edge!(z, id(i, j1), id(i, j2))
end
end
return z
end

"""
disjunctive_product(g, h)

Return the [disjunctive product](https://en.wikipedia.org/wiki/Graph_product)
of `g` and `h`.

The disjunctive product has edges (g₁, h₁) ∼ (g₂, h₂) when g₁ ∼ g₂ ∨ h₁ ∼ h₂.

### Implementation Notes
Preserves the eltype of the input graph. Will error if the number of vertices
in the generated graph exceeds the eltype.

# Examples
```jldoctest
julia> using Graphs

julia> a = star_graph(3);

julia> b = path_graph(3);

julia> g = disjunctive_product(a, b)
{9, 28} undirected simple Int64 graph

julia> complement(g) == strong_product(complement(a), complement(b))
true
```
"""
function disjunctive_product(g::G, h::G) where {G<:AbstractSimpleGraph}
z = G(nv(g) * nv(h))
id(i, j) = (i - 1) * nv(h) + j
for e in edges(g)
i1, i2 = Tuple(e)
for j in vertices(h)
for k in vertices(h)
add_edge!(z, id(i1, j), id(i2, k))
end
end
end
for e in edges(h)
j1, j2 = Tuple(e)
for i in vertices(g)
for k in vertices(g)
add_edge!(z, id(i, j1), id(k, j2))
end
end
end
return z
end

"""
lexicographic_product(g, h)

Return the [lexicographic product](https://en.wikipedia.org/wiki/Lexicographic_product_of_graphs)
of `g` and `h`.

The lexicographic product has edges (g₁, h₁) ∼ (g₂, h₂) when (g₁ ∼ g₂) ∨ (g₁ = g₂ ∧ h₁ ∼ h₂).

### Implementation Notes
Preserves the eltype of the input graph. Will error if the number of vertices
in the generated graph exceeds the eltype.

# Examples
```jldoctest
julia> using Graphs

julia> g = lexicographic_product(star_graph(3), path_graph(3))
{9, 24} undirected simple Int64 graph

julia> adjacency_matrix(g)
9×9 SparseArrays.SparseMatrixCSC{Int64, Int64} with 48 stored entries:
⋅ 1 ⋅ 1 1 1 1 1 1
1 ⋅ 1 1 1 1 1 1 1
⋅ 1 ⋅ 1 1 1 1 1 1
1 1 1 ⋅ 1 ⋅ ⋅ ⋅ ⋅
1 1 1 1 ⋅ 1 ⋅ ⋅ ⋅
1 1 1 ⋅ 1 ⋅ ⋅ ⋅ ⋅
1 1 1 ⋅ ⋅ ⋅ ⋅ 1 ⋅
1 1 1 ⋅ ⋅ ⋅ 1 ⋅ 1
1 1 1 ⋅ ⋅ ⋅ ⋅ 1 ⋅
```
"""
function lexicographic_product(g::G, h::G) where {G<:AbstractSimpleGraph}
z = G(nv(g) * nv(h))
id(i, j) = (i - 1) * nv(h) + j
for e in edges(g)
i1, i2 = Tuple(e)
for j in vertices(h)
for k in vertices(h)
add_edge!(z, id(i1, j), id(i2, k))
end
end
end
for e in edges(h)
j1, j2 = Tuple(e)
for i in vertices(g)
add_edge!(z, id(i, j1), id(i, j2))
end
end
return z
end

"""
homomorphic_product(g, h)

Return the [homomorphic product](https://en.wikipedia.org/wiki/Graph_product)
of `g` and `h`.

The homomorphic product has edges (g₁, h₁) ∼ (g₂, h₂) when
(g₁ = g₂) ∨ (g₁ ∼ g₂ ∧ h₁ ≁ h₂).

### Implementation Notes
Preserves the eltype of the input graph. Will error if the number of vertices
in the generated graph exceeds the eltype.

# Examples
```jldoctest
julia> using Graphs

julia> g = homomorphic_product(star_graph(3), path_graph(3))
{9, 19} undirected simple Int64 graph

julia> adjacency_matrix(g)
9×9 SparseArrays.SparseMatrixCSC{Int64, Int64} with 38 stored entries:
⋅ 1 1 1 ⋅ 1 1 ⋅ 1
1 ⋅ 1 ⋅ 1 ⋅ ⋅ 1 ⋅
1 1 ⋅ 1 ⋅ 1 1 ⋅ 1
1 ⋅ 1 ⋅ 1 1 ⋅ ⋅ ⋅
⋅ 1 ⋅ 1 ⋅ 1 ⋅ ⋅ ⋅
1 ⋅ 1 1 1 ⋅ ⋅ ⋅ ⋅
1 ⋅ 1 ⋅ ⋅ ⋅ ⋅ 1 1
⋅ 1 ⋅ ⋅ ⋅ ⋅ 1 ⋅ 1
1 ⋅ 1 ⋅ ⋅ ⋅ 1 1 ⋅
```
"""
function homomorphic_product(g::G, h::G) where {G<:AbstractSimpleGraph}
z = G(nv(g) * nv(h))
id(i, j) = (i - 1) * nv(h) + j
undirected = !is_directed(g)
for i in vertices(g)
for j in vertices(h)
for k in vertices(h)
if k != j
add_edge!(z, id(i, j), id(i, k))
end
end
end
end
cmpl_h = complement(h)
for e in edges(g)
i1, i2 = Tuple(e)
for f in edges(cmpl_h)
j1, j2 = Tuple(f)
add_edge!(z, id(i1, j1), id(i2, j2))
if undirected
add_edge!(z, id(i1, j2), id(i2, j1))
end
end
for j in vertices(h)
add_edge!(z, id(i1, j), id(i2, j))
end
end
return z
end

## subgraphs ###

"""
Expand Down
17 changes: 17 additions & 0 deletions test/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,23 @@
end
end

gx = SimpleGraph(10, 20)
gy = SimpleGraph(15, 34)
@testset "Graph product edge counts" for (g1, g2) in zip(testgraphs(gx), testgraphs(gy))
v1 = nv(g1)
v2 = nv(g2)
e1 = ne(g1)
e2 = ne(g2)
# Edge counts from https://en.wikipedia.org/wiki/Graph_product
@test ne(cartesian_product(g1, g2)) == v1 * e2 + v2 * e1
@test ne(tensor_product(g1, g2)) == 2 * e1 * e2
@test ne(lexicographic_product(g1, g2)) == v1 * e2 + e1 * v2^2
@test ne(strong_product(g1, g2)) == v1 * e2 + v2 * e1 + 2 * e1 * e2
@test ne(disjunctive_product(g1, g2)) == v1^2 * e2 + e1 * v2^2 - 2 * e1 * e2
@test ne(homomorphic_product(g1, g2)) ==
v1 * v2 * (v2 - 1) / 2 + e1 * (v2^2 - 2 * e2)
end

## test subgraphs ##

gb = smallgraph(:bull)
Expand Down