Skip to content

Commit

Permalink
Vertex cover (#19)
Browse files Browse the repository at this point in the history
* add vertex cover

* add vertex cover

* fix test and rename method

* docs

* fix docs + small fixes

* fix missing docstring

---------

Co-authored-by: Guillaume Dalle <22795598+gdalle@users.noreply.github.com>
  • Loading branch information
olegfafurin and gdalle authored Nov 10, 2023
1 parent d87b65d commit f2cf29d
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 0 deletions.
9 changes: 9 additions & 0 deletions docs/src/algorithms.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ min_cost_assignment
GraphsOptim.min_cost_assignment!
```

## Minimum Vertex Cover

```@docs
min_vertex_cover
GraphsOptim.min_vertex_cover!
```

Finds a subset $S \subset V$ of vertices of an undirected graph $G = (V,E)$ such that $\forall (u,v) \in E: u \in S \lor v \in S$

## Graph matching

!!! danger "Work in progress"
Expand Down
2 changes: 2 additions & 0 deletions src/GraphsOptim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ using OptimalTransport: sinkhorn
export min_cost_flow
export min_cost_assignment
export FAQ, GOAT, graph_matching
export min_vertex_cover
export fractional_chromatic_number, fractional_clique_number
export shortest_path

include("utils.jl")
include("flow.jl")
include("assignment.jl")
include("graph_matching.jl")
include("min_vertex_cover.jl")
include("fractional_coloring.jl")
include("shortest_path.jl")

Expand Down
67 changes: 67 additions & 0 deletions src/min_vertex_cover.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
min_vertex_cover!(
model, g;
var_name
)
Modify a JuMP model by adding the variable, constraints and objective necessary to compute a minimum vertex cove of an undirected graph.
The vertex cover indicator variable will be named `var_name`
"""
function min_vertex_cover!(model::Model, g::AbstractGraph; integer::Bool, var_name)
if is_directed(g)
throw(ArgumentError("The graph must not be directed"))
end

ver = collect(vertices(g))

f = @variable(model, [ver]; integer=integer, base_name=String(var_name))
model[Symbol(var_name)] = f

for v in ver
@constraint(model, f[v] >= 0)
@constraint(model, f[v] <= 1)
end

for e in edges(g)
@constraint(model, f[src(e)] + f[dst(e)] >= 1)
end

obj = objective_function(model)
for v in ver
add_to_expression!(obj, f[v])
end
@objective(model, Min, obj)

return model
end

"""
min_vertex_cover(
g, optimizer
)
Compute a minimum vertex cover of an undirected graph.
# Arguments
- `g::Graphs.AbstractGraph`: an undirected graph `G = (V, E)`
# Keyword arguments
- `optimizer`: JuMP-compatible solver (default is `HiGHS.Optimizer`)
"""
function min_vertex_cover(g::AbstractGraph; integer::Bool=true, optimizer=HiGHS.Optimizer)
model = Model(optimizer)
set_silent(model)

min_vertex_cover!(model, g; integer=integer, var_name=:cover)

optimize!(model)
@assert termination_status(model) == OPTIMAL

cover_values = Vector(value.(model[:cover]))
cover_vertices = findall(==(1), cover_values)

return cover_vertices
end
18 changes: 18 additions & 0 deletions test/min_vertex_cover.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Graphs: SimpleGraph
using GraphsOptim
using Test

adj_matrix = [
0 1 1 0 0 0
1 0 1 1 1 1
1 1 0 0 0 0
0 1 0 0 0 0
0 1 0 0 0 0
0 1 0 0 0 0
]

expected_ans_options = [Set([1, 2]), Set([2, 3])]

graph = SimpleGraph(adj_matrix)

@test Set(min_vertex_cover(graph)) in expected_ans_options
4 changes: 4 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ using Test
include("graph_matching.jl")
end

@testset verbose = true "Vertex cover" begin
include("min_vertex_cover.jl")
end

@testset verbose = true "Fractional coloring" begin
include("fractional_coloring.jl")
end
Expand Down

0 comments on commit f2cf29d

Please sign in to comment.