Add graph edit distance solver#37
Conversation
there are three kinds of variable structures. We break symmetry by requiring edge indices be ordered from i to j if i < j.
These constraints encode graph structure
This is much cleaner and will prevent use of if statements later
The function checks if the graphs are undirected and defines a slightly nicer call interface
I could not find a way to account for the more general type of the empty variable sets if a graph has no edges, so now we just don't typehint the edge variables.
If the edgeset of one graph is empty, the edge map variables are nonexistent. In this case, the julia compiler doesn't know how it should handle sum() over an empty set of variables. This commit adds a default return value of 0, which fixes the crashes.
They were removed to accomodate for the edge case of empty graphs.
fixup commit
It returns the node matching matrix
These are the most important ones, because they are the public facing entrypoints.
Internal, so only rough description.
Since the functions are internal, only rough documentation on what implication is implemented are added. Technically inferrable from code, but I think it provides value.
To pass the style check
This commit doesn't build, but that is because of preexisting issues with the project that are out of the scope for this commit.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #37 +/- ##
==========================================
- Coverage 98.33% 92.71% -5.63%
==========================================
Files 8 10 +2
Lines 180 343 +163
==========================================
+ Hits 177 318 +141
- Misses 3 25 +22 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Thank you, Jonas, for the PR. Regarding the documentation, I think you are right: it now errors because there is a docstring for a non-exported function. For the downgrade test, the problem seems to be that you are using For Julia 1.6, the issue can be reproduced with this MWE: using JuMP
model = Model()
@variable(model, x[1:2])
@variable(model, y[1:2, 1:2])
# This works on Julia 1.6.7
println(sum(y[1, :]; init=0))
# This works inside JuMP
@constraint(model, [i in 1:2], sum(y[i, :]) <= x[i])
# This also works inside JuMP
@constraint(model, [i in 1:2], sum((y[i, j] for j in 1:2); init=0) <= x[i])
# This fails on Julia 1.6.7
# ERROR: syntax: malformed expression
@constraint(model, [i in 1:2], sum(y[i, :]; init=0) <= x[i])Would it be possible to change the code to avoid this syntax, so that we can keep supporting the same Julia versions currently supported by the library? |
|
I believe I used On the index syntax, I've just now tested a replacement, which works. The issue is that it makes the code much, much more verbose because the # existing syntax
sum(vars.z[i, :, k, l]; init=0)
# version without `:` indexing
sum(vars.z[i, j, k, l] for j in 1:nv(G) if has_edge(G, i,j) && i < j; init=0)It more than doubles the character count and makes it much harder to maintain as well, since we have to explicitly respect the ordering of edges. Is there a reason why the tests run against Julia 1.6? As far as I can tell, that was the LTS version before it was switched to 1.10 already some time ago. The JuMP library itself dropped support for Julia 1.6 a few months ago, and the current version supports Julia 1.10. Based on this, I think it is reasonable to raise the support in this library to the current LTS version 1.10.11, which would allow us to keep the cleaner slicing syntax here. |
This PR implements seven ILP formulations of differing strengths to solve the graph edit distance problem, based on 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.
I have built the docs successfully locally, but I had some issues which are not resolved here because it seemed out of scope for this PR:
make.jlscript is supposed to be used. With the help of ChatGPT, I stumbled on the following working script, to be called from project root:Project.tomlanddocs/Project.tomlcontradict each other on the required Documenter version. After deleting the line inProject.toml, the build works, but as I am inexperienced I don't know if this is the correct fixmakedocscall inmake.jlthrows an error for each of the internal docstrings I wrote because they are not exposed in the documentation. The (again LLM-provided) fix is to addcheckdocs=:exportsas an argument. At least for the current documentation structure, I believe this is the correct fix. It makes little sense to delete internal documentation, but at the same timealgorithms.mdis definitely the wrong place to put all those and in my opinion they shouldn't be exposed to users anyway.