I’m trying to implement the Rhea C++ constraint solving algorithm in Julia as a learning project. I’m simply translating the original source as far as I’m able into something that makes sense in Julia.
I have implemented part of the unit tests and at the current state they fail with a StackOverflowError, but not every time. As the inputs are completely deterministic, I don’t know how that can happen.
As the code is already a couple hundred lines long and I’m not sure where the problem might be, I know it will be complicated to get help here, because I can’t post a non-working minimal example.
So first of all here’s the stacktrace:
(Rhea) pkg> test Rhea
Testing Rhea
Resolving package versions...
Test Summary: | Pass Total
strength test | 11 11
Test Summary: | Pass Total
variable test | 16 16
Test Summary: | Pass Total
linear expressions 1 | 13 13
Test Summary: | Pass Total
linear expressions 3 | 5 5
linear equation test: Error During Test at /Users/juliuskrumbiegel/dev/julia/Rhea/test/runtests.jl:116
Test threw exception
Expression: is_satisfied(x == y - 1)
StackOverflowError:
Stacktrace:
[1] Dict(::Pair{variable{Float64},Float64}) at ./dict.jl:124
[2] expression{variable{Float64}}(::variable{Float64}, ::Float64, ::Float64) at /Users/juliuskrumbiegel/dev/julia/Rhea/src/expression.jl:14
[3] expression{variable{Float64}}(::variable{Float64}) at /Users/juliuskrumbiegel/dev/julia/Rhea/src/expression.jl:12
[4] ==(::variable{Float64}, ::variable{Float64}) at /Users/juliuskrumbiegel/dev/julia/Rhea/src/constraint.jl:52
[5] isequal(::variable{Float64}, ::variable{Float64}) at ./operators.jl:123
[6] ht_keyindex(::Dict{variable{Float64},Float64}, ::variable{Float64}) at ./dict.jl:290
[7] haskey(::Dict{variable{Float64},Float64}, ::variable{Float64}) at ./dict.jl:546
[8] sub!(::expression{variable{Float64}}, ::Rhea.term{variable{Float64}}) at /Users/juliuskrumbiegel/dev/julia/Rhea/src/expression.jl:153
[9] sub!(::expression{variable{Float64}}, ::expression{variable{Float64}}) at /Users/juliuskrumbiegel/dev/julia/Rhea/src/expression.jl:147
[10] -(::expression{variable{Float64}}, ::expression{variable{Float64}}) at /Users/juliuskrumbiegel/dev/julia/Rhea/src/linear_expression.jl:43
[11] ==(::expression{variable{Float64}}, ::expression{variable{Float64}}) at /Users/juliuskrumbiegel/dev/julia/Rhea/src/constraint.jl:45
... (the last 8 lines are repeated 9998 more times)
[79996] ==(::variable{Float64}, ::variable{Float64}) at /Users/juliuskrumbiegel/dev/julia/Rhea/src/constraint.jl:52
ERROR: Package Rhea errored during testing
So there seems to be a loop between the ==(::variable{Float64}, ::variable{Float64})
statements at [4] and [11]. That line from [4] looks like this:
==(v::variable, v2::variable) = linear_expression(v) == linear_expression(v2)
which should then lead to another function that I defined
==(first::linear_expression, second::linear_expression) = constraint(first - second, eq)
but this doesn’t appear next in the stack trace, which I don’t understand.
variable
is defined like this:
mutable struct variable{T}
p::T
end
expression
like this:
mutable struct expression{T}
constant::Float64
terms::Dict{T, Float64}
end
and linear_expression
like this:
const linear_expression = expression{variable{Float64}}
The code has basically lots of redefinitions of operators, so that something like
x = variable(3.0)
y = variable(4.0)
x == y
should not compare x and y but create a linear expression.
I’ll leave it at that for now because it is a lot already, I would be grateful for input how to understand what might be going on here if it’s impossible to do something with the code snippets. Thank you!