Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
c4e71b8
Add variable structs for three types of formulations
Jabbermuggel Jun 24, 2026
375584d
Add function to create model variables
Jabbermuggel Jun 24, 2026
bd86e20
Add node and edge map constraint functions
Jabbermuggel Jun 24, 2026
856b61e
Add topology constraints
Jabbermuggel Jun 24, 2026
81134b1
fixup! Add variable structs for three types of formulations
Jabbermuggel Jun 24, 2026
bb7a42e
Add objective functions
Jabbermuggel Jun 24, 2026
1d8a45c
Add model constructing functions
Jabbermuggel Jun 24, 2026
fd39fe0
Add missing imports and the Graph typehints
Jabbermuggel Jun 24, 2026
079366a
Remove model returns from mutating construct functions
Jabbermuggel Jun 26, 2026
6dc705e
Rework construct functions to use type system instead of different names
Jabbermuggel Jun 26, 2026
0cfab0b
Add common dispatch point
Jabbermuggel Jun 26, 2026
fe5de9d
Remove typehints to account for empty edgesets
Jabbermuggel Jun 28, 2026
a34d1bf
Fix code for the case where one graph has no edges
Jabbermuggel Jun 28, 2026
66f4dcb
Fix objective for the case where at least one graph has no nodes
Jabbermuggel Jul 1, 2026
42994c0
Add export for main function and Formulation symbols
Jabbermuggel Jul 1, 2026
5a5cb16
Add unit tests for edit distance code
Jabbermuggel Jul 1, 2026
74353be
Remove unnecessary imports
Jabbermuggel Jul 1, 2026
1ef64fb
Add VariableRef back in
Jabbermuggel Jul 4, 2026
5c29188
Add function that constructs the model in-place
Jabbermuggel Jul 4, 2026
7d959f8
Improve existing comments
Jabbermuggel Jul 4, 2026
39309b9
Add docstring for edit_distance functions
Jabbermuggel Jul 4, 2026
f812412
Add docstring to construct_formulation!
Jabbermuggel Jul 5, 2026
1d32cd8
Add docstring to Formulation types
Jabbermuggel Jul 5, 2026
e6b031e
Add docstring to the variable structs
Jabbermuggel Jul 5, 2026
adff0e0
Add docstring to variable creation functions
Jabbermuggel Jul 5, 2026
67848c0
Add docstring to cost functions
Jabbermuggel Jul 5, 2026
817fcdc
Add docstring to objective generating functions
Jabbermuggel Jul 5, 2026
37556f2
Add docstring to node and edge map functions
Jabbermuggel Jul 5, 2026
de9f0bb
Add docstring to topology constraint functions
Jabbermuggel Jul 5, 2026
bd202e7
Add mathematical description and paper reference in algorithms.md
Jabbermuggel Jul 5, 2026
9e52ce4
Improve formatting in unit tests
Jabbermuggel Jul 5, 2026
7483f5f
Fix spaces in parentheses
Jabbermuggel Jul 5, 2026
ce9855e
Fix method definition length
Jabbermuggel Jul 5, 2026
6dc67d9
Fix indentation in JuMP macros
Jabbermuggel Jul 5, 2026
ff6b3b2
Add minor formatting fixes
Jabbermuggel Jul 5, 2026
8322eb7
Add nothing return value on all functions that only modify the input
Jabbermuggel Jul 5, 2026
7604fca
Fix issues with documentation
Jabbermuggel Jul 6, 2026
fd827ef
Add return of both solution value and mapping to edit_distance function
Jabbermuggel Jul 7, 2026
2c96fb6
Remove dead leftover code
Jabbermuggel Jul 7, 2026
1dc547d
Add unit tests for uncovered code
Jabbermuggel Jul 7, 2026
2413b34
Replace GenericModel with Model in function argument typing
Jabbermuggel Jul 7, 2026
e229c06
Remove redundant check for graph directedness
Jabbermuggel Jul 7, 2026
c7adef0
Upgrade JuMP dependency for SparseVariable index slicing
Jabbermuggel Jul 8, 2026
5d20f27
Merge branch 'main' into graph_edit_distance
Jabbermuggel Jul 12, 2026
3de0ecb
Fix rounding problem for larger graphs
Jabbermuggel Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Documenter = "0.27"
FillArrays = "0.13, 1.15"
Graphs = "1.7"
HiGHS = "1"
JuMP = "1"
JuMP = "1.3"
JuliaFormatter = "1"
MathOptInterface = "1.18"
OptimalTransport = "0.3"
Expand Down
57 changes: 57 additions & 0 deletions docs/src/algorithms.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,63 @@ graph_matching
GraphsOptim.graph_matching_step_size
```

## Graph edit distance
```@docs
edit_distance
GraphsOptim.edit_distance!
```

### Mathematical Details

The formulations implemented in the code are described in `D'ascenzo, Andrea, et al. "Enhancing Graph Edit Distance Computation: Stronger and Orientation-based ILP Formulations." Proceedings of the VLDB Endowment 18.11 (2025): 4737-4749`. The paper also containts a more detailed description of the graph edit distance problem.

In the graph edit distance problem, we search for a minimum cost *edit path* between
two graphs $G$ and $H$, that is a sequence of edit operations transforming $G$ to $H$. Valid
edit operations are inserting or deleting a node or edge, or relabeling an existing node or
edge.

This formulation of the problem is easy to visualize, but not very suitable for implementing
with integer programming. We thus use another, equivalent definition instead: a *node map*
is a relation $\pi \subset V_{G+ \epsilon} \times V_{H + \epsilon}$ on the vertex sets
augmented by $\epsilon$, in which

* each node $v \in V_G$ is mapped to exactly one element of $V_{H + \epsilon}$
* each node $w \in V_H$ has exactly one preimage in $V_{G + \epsilon}$

Being mapped to $\epsilon$ is equivalent to being deleted or created. We will not give a
proof here, but for metric cost functions this is equivalent to the edit path formulation
(and any cost function can be transformed into an equivalent metric one).

This version of the problem is much better suited for integer programming, and is the
foundation for all formulations implemented here. The formulations all use the same basic
principle, defining binary variables to encode the mapping between nodes and edges,
constraints that ensure the variables encode valid node and edge maps, and finally *topology
constraints* which link node and edge variables based on the topology of the input graphs.
The formulations differ in the exact variable layout and more importantly the topology
constraints used. As seen in the paper mentioned above, the different topology constraints
not only provide massive speedups in practice but their relaxations provide different
bounds.

The best formulation both in theory and practive orients the graphs to provide stricter
topology constraints. The graph $G$ is oriented in a canonical way, while in $H$ there are
forward and backwards edges for each undirected edge in the input. We can then additionally
demand that edges be mapped consistently with their orientation.

### Function documentation for advanced use
```@docs
GraphsOptim.EditCosts
GraphsOptim.get_default_edit_costs
GraphsOptim.validate_cost_function
GraphsOptim.Formulation
GraphsOptim.F1
GraphsOptim.F1prime
GraphsOptim.F1plus
GraphsOptim.F2minus
GraphsOptim.F2
GraphsOptim.F2plus
GraphsOptim.FORI
```

## Coloring

```@docs
Expand Down
5 changes: 5 additions & 0 deletions src/GraphsOptim.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ module GraphsOptim
using Graphs: AbstractGraph, is_directed
using Graphs: vertices, edges, nv, ne, src, dst, inneighbors, outneighbors, has_edge
using Graphs: complement, maximal_cliques
using Graphs: SimpleGraph
using FillArrays: Zeros, Ones, Fill
using HiGHS: HiGHS
using JuMP: Model, AffExpr
using JuMP: objective_function, add_to_expression!
using JuMP: set_silent, optimize!, termination_status, value
using JuMP: set_optimizer, objective_value
using JuMP: @variable, @constraint, @objective
using JuMP: VariableRef
using LinearAlgebra: norm, tr, dot
using MathOptInterface: OPTIMAL
using SparseArrays: sparse
Expand All @@ -29,6 +31,8 @@ export fractional_chromatic_number, fractional_clique_number
export shortest_path
export maximum_weight_clique

export edit_distance, F1, F1prime, F1plus, F2, F2minus, F2plus, FORI

include("utils.jl")
include("flow.jl")
include("assignment.jl")
Expand All @@ -38,5 +42,6 @@ include("fractional_coloring.jl")
include("shortest_path.jl")
include("maximum_clique.jl")
include("independent_set.jl")
include("graph_edit_distance.jl")

end
Loading
Loading