First of all: Happy new year to everyone!
This is kind of part 15 of the series about: How to build a Constraint Programming solver?
But it is also interesting for you if you don’t care about constraint programming.
You can learn how to use JuMP.jl as the modelling layer for your own solver.
Anyway these are the other posts so far in the ongoing series:
- Part 1: Setup and backtracking
- Part 2: Pruning
- Part 3: Pruning+Benchmarking
- Part 4: Alldifferent constraint
- Part 5: Better data structure
- Part 6: Sum constraint first part
- Part 7: Sum constraint speed-up
- Part 8: UI Refactoring
- Part 9: Recap video
- Part 10: First part of graph coloring
- Part 11: MIP graph coloring and optimization
- Part 12: Documentation and latest benchmarking
- Part 13: Profiling
- Part 14: Bipartite Matching
All of that can only happen because of the generous support of some people.
I’m very happy that I can cover my server expenses now because of my Patrons.
To keep this going please consider supporting this blog on Patreon. If you do I will create a better/faster blog experience and you will get posts like this earlier! Everything will be free forever but if you have some cash to spare -> This might be an option 😉
Special limited offer… I either just lost your attention or I have it now 😀
I decided to offer a 1:1 (binary) talk where you can ask me about my work and just chat with me if you’re willing to join the Patron 4$ club. 😉 This offer is until the 10th of February.
If you want to just keep reading -> Here you go 😉
Maybe I should have done that from the ground up but wasn’t sure how to and probably it was easier for the blog as well to start without a big code base. Therefore here it is now: Using JuMP.jl as the modelling layer for the constraint solver I’m creating for the past couple of months.
UserInterface change
Before I explain how it’s done I want to show how the user interface changes first:
How it was before
com = CS.init() # creating a constraint solver model
com_grid = Array{CS.Variable, 2}(undef, 9, 9)
for (ind,val) in enumerate(grid)
if val == 0
com_grid[ind] = add_var!(com, 1, 9)
else
com_grid[ind] = add_var!(com, 1, 9; fix=val)
end
end
for rc=1:9
#row
variables = com_grid[CartesianIndices((rc:rc,1:9))]
add_constraint!(com, CS.all_different([variables...]))
#col
variables = com_grid[CartesianIndices((1:9,rc:rc))]
add_constraint!(com, CS.all_different([variables...]))
end
which is a bit of the sudoku part. Now it looks like this:
m = Model(with_optimizer(CS.Optimizer))
@variable(m, 1 <= x[1:9,1:9] <= 9, Int)
# set variables
for r=1:9, c=1:9
if grid[r,c] != 0
@constraint(m, x[r,c] == grid[r,c])
end
end
for rc = 1:9
@constraint(m, x[rc,:] in CS.AllDifferentSet(9))
@constraint(m, x[:,rc] in CS.AllDifferentSet(9))
end
I think it looks a lot cleaner now but more importantly it is the standard interface for mathematical optimization solvers written in Julia.
This also means that if there will exist other constraint solvers in the future one can easily swap the…