This is kinda part of the constraint solver series => Building a constraint solver in Julia but is useful for more than this and might be its own package (yeah I say that often :D)
There were some changes to the constraint solver which still need a post and I’m not satisfied yet to write a post about it but I should…
What is this topic about?
When I started with Julia and Juniper.jl I needed to write a table logger to display the current status of the solver.
By status I mean information like best solution found so far (incumbent) and best bound as well as how long did it run so far.
Basically the table from this:
Now I of course also need this for the constraint solver project but I didn’t like the code that much and spoiler alert: I’m not completely satisfied with the current implementation now but I think I should put it out here and maybe some others have ideas on how to improve it.
What I want
I want to easily define the table by giving the header information which includes the type, the width and some other information.
In the solver I want to push something to the table and given some criteria the table should decide whether this is a new row or whether there it’s not worth it i.e in the constraint solver there can be a lot of backtracking steps but they can be quite fast for example in the case of solving sudokus. I don’t want a line for each step in the backtrack!
function. Normally the user wants to get updates to see that it’s running or if a new solution was found. Therefore I use the rule that a new line should be added every five seconds or if there is a new solution.
Additionally the type of the column should define some formatting rules which the developer should be able to change.
Some problems
Not too sure how to make it as extensible as possible so this is my try of doing it and I welcome your comments/issues/PRs.
Current implementation
TableLogger.jl
mutable struct TableCol
id :: Symbol
name :: String
type :: DataType
width :: Int
alignment :: Symbol # :left, :center, :right
b_format :: Bool
end
mutable struct TableEntry{T}
col_id :: Symbol
value :: T
end
mutable struct TableSetup
cols :: Vector{TableCol}
col_idx :: Dict{Symbol,Int}
new_row_criteria :: Bool
diff_criteria :: Dict{Symbol, Any}
last_row :: Vector{TableEntry}
end
The table is defined by the columns cols
might have some criteria to check if a new row should be added or now which depends on last_row
and diff_criteria
will be passed to the function of deciding whether a new row will be added.
I need the col_idx
to know which column is at which position. Maybe that can be done in a different fashion.
TableCol
has a type which defines whether some formatting should be used.
Each row is a vector of TableEntry
which defines the column…