JuliaSymbolics / SymbolicUtils.jl

Symbolic expressions, rewriting and simplification
https://docs.sciml.ai/SymbolicUtils/stable/
Other
524 stars 99 forks source link

Regression: infinite loop during simplification on v1 #500

Closed MilesCranmer closed 1 year ago

MilesCranmer commented 1 year ago

The following code hits an infinite loop:

using SymbolicUtils
@syms x1::LiteralReal x2::LiteralReal
s = cos(x1*3.2) - (x2*5.8) + x2*1.2
simplify(s)

On v1, this code hangs on the simplify(s) and hasn't completed in 30 minutes. This works on v0.19.

Defining @syms x1 x2 works (auto-simplifies).

When I interrupt the simplification, this is the stacktrace (it changes every time I interrupt it):

Failed to apply rule cot(~x) ^ 2 + 1 => csc(~x) ^ 2 on expression 1.2x2 + cos(3.2x1) - 5.8x2
Stacktrace:
  [1] (::SymbolicUtils.Rule{SymbolicUtils.BasicSymbolic{Any}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#192#273"})(term::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/rule.jl:145
  [2] (::SymbolicUtils.ACRule{typeof(Combinatorics.permutations), SymbolicUtils.Rule{SymbolicUtils.BasicSymbolic{Any}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#192#273"}})(term::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/rule.jl:407
  [3] macro expansion
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/utils.jl:11 [inlined]
  [4] (::SymbolicUtils.Rewriters.Chain)(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:69
  [5] macro expansion
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/utils.jl:11 [inlined]
  [6] (::SymbolicUtils.Rewriters.Chain)(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:69
  [7] (::SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:58
  [8] (::SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}}, typeof(similarterm), false})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:200
  [9] (::SymbolicUtils.Rewriters.IfElse{typeof(SymbolicUtils.has_trig_exp), SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}}, typeof(similarterm), false}, SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.Chain, typeof(similarterm), false}})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:58
 [10] macro expansion
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/utils.jl:11 [inlined]
 [11] (::SymbolicUtils.Rewriters.Fixpoint{SymbolicUtils.Rewriters.IfElse{typeof(SymbolicUtils.has_trig_exp), SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}}, typeof(similarterm), false}, SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.Chain, typeof(similarterm), false}}})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:122
 [12] IfElse
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:58 [inlined]
 [13] (::SymbolicUtils.Rewriters.PassThrough{SymbolicUtils.Rewriters.IfElse{typeof(istree), SymbolicUtils.Rewriters.Fixpoint{SymbolicUtils.Rewriters.IfElse{typeof(SymbolicUtils.has_trig_exp), SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}}, typeof(similarterm), false}, SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.Chain, typeof(similarterm), false}}}, SymbolicUtils.Rewriters.Empty}})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:188
 [14] simplify(x::SymbolicUtils.BasicSymbolic{LiteralReal}; expand::Bool, polynorm::Nothing, threaded::Bool, simplify_fractions::Bool, thread_subtree_cutoff::Int64, rewriter::Nothing)
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/simplify.jl:41
 [15] simplify(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/simplify.jl:16
 [16] top-level scope
    @ REPL[5]:1

caused by: InterruptException:
Stacktrace:
  [1] getindex
    @ ./tuple.jl:29 [inlined]
  [2] car
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/utils.jl:179 [inlined]
  [3] (::SymbolicUtils.var"#loop#99"{SymbolicUtils.var"#success#85"{SymbolicUtils.var"#192#273"}})(term::SymbolicUtils.LL{SubArray{Any, 1, Vector{Any}, Tuple{Vector{Int64}}, false}}, bindings′::Base.ImmutableDict{Symbol, Any}, matchers′::SymbolicUtils.LL{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/matchers.jl:101
  [4] (::SymbolicUtils.var"#97#100"{SymbolicUtils.BasicSymbolic{LiteralReal}, Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}})(b::Base.ImmutableDict{Symbol, Any}, n::Int64)
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/matchers.jl:102
  [5] (::SymbolicUtils.var"#literal_matcher#94"{typeof(+)})(next::SymbolicUtils.var"#97#100"{SymbolicUtils.BasicSymbolic{LiteralReal}, Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, data::SymbolicUtils.BasicSymbolic{LiteralReal}, bindings::Base.ImmutableDict{Symbol, Any})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/matchers.jl:11
  [6] (::SymbolicUtils.var"#loop#99"{SymbolicUtils.var"#success#85"{SymbolicUtils.var"#192#273"}})(term::SymbolicUtils.BasicSymbolic{LiteralReal}, bindings′::Base.ImmutableDict{Symbol, Any}, matchers′::Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/matchers.jl:101
  [7] (::SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}})(success::SymbolicUtils.var"#success#85"{SymbolicUtils.var"#192#273"}, data::Tuple{SymbolicUtils.BasicSymbolic{LiteralReal}}, bindings::Base.ImmutableDict{Symbol, Any})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/matchers.jl:106
  [8] (::SymbolicUtils.Rule{SymbolicUtils.BasicSymbolic{Any}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#192#273"})(term::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/rule.jl:143
  [9] (::SymbolicUtils.ACRule{typeof(Combinatorics.permutations), SymbolicUtils.Rule{SymbolicUtils.BasicSymbolic{Any}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(+)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(^)}, SymbolicUtils.var"#term_matcher#98"{Tuple{SymbolicUtils.var"#literal_matcher#94"{typeof(cot)}, SymbolicUtils.var"#slot_matcher#95"{SymbolicUtils.Slot{typeof(SymbolicUtils.alwaystrue)}}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#literal_matcher#94"{Int64}}}, SymbolicUtils.var"#192#273"}})(term::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/rule.jl:407
 [10] macro expansion
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/utils.jl:11 [inlined]
 [11] (::SymbolicUtils.Rewriters.Chain)(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:69
 [12] macro expansion
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/utils.jl:11 [inlined]
 [13] (::SymbolicUtils.Rewriters.Chain)(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:69
 [14] (::SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:58
 [15] (::SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}}, typeof(similarterm), false})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:200
 [16] (::SymbolicUtils.Rewriters.IfElse{typeof(SymbolicUtils.has_trig_exp), SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}}, typeof(similarterm), false}, SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.Chain, typeof(similarterm), false}})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:58
 [17] macro expansion
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/utils.jl:11 [inlined]
 [18] (::SymbolicUtils.Rewriters.Fixpoint{SymbolicUtils.Rewriters.IfElse{typeof(SymbolicUtils.has_trig_exp), SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}}, typeof(similarterm), false}, SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.Chain, typeof(similarterm), false}}})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:122
 [19] IfElse
    @ ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:58 [inlined]
 [20] (::SymbolicUtils.Rewriters.PassThrough{SymbolicUtils.Rewriters.IfElse{typeof(istree), SymbolicUtils.Rewriters.Fixpoint{SymbolicUtils.Rewriters.IfElse{typeof(SymbolicUtils.has_trig_exp), SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#218#302", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.IfElse{SymbolicUtils.var"#219#303", SymbolicUtils.Rewriters.Chain, SymbolicUtils.Rewriters.Empty}}, typeof(similarterm), false}, SymbolicUtils.Rewriters.Walk{:post, SymbolicUtils.Rewriters.Chain, typeof(similarterm), false}}}, SymbolicUtils.Rewriters.Empty}})(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/pO4d6/src/rewriters.jl:188
 [21] simplify(x::SymbolicUtils.BasicSymbolic{LiteralReal}; expand::Bool, polynorm::Nothing, threaded::Bool, simplify_fractions::Bool, thread_subtree_cutoff::Int64, rewriter::Nothing)
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/simplify.jl:41
 [22] simplify(x::SymbolicUtils.BasicSymbolic{LiteralReal})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/pO4d6/src/simplify.jl:16
MilesCranmer commented 1 year ago

Could it be that some of the default simplification rules assume that an expression is already in simplified polynomial form?

MilesCranmer commented 1 year ago

@YingboMa @shashi would one of you be willing to look into this? This issue is preventing me from upgrading my SymbolicUtils.jl version for SymbolicRegression.jl

MilesCranmer commented 1 year ago

@YingboMa @shashi sorry for the spam but just wanted to ping this as it is still blocking me from upgrading. Please let me know if there's anything at all I can do to help debug this. Thanks! - Miles

shashi commented 1 year ago

Hey sorry, yes I will look at this now.

MilesCranmer commented 1 year ago

Thanks!!

MilesCranmer commented 1 year ago

Pinging this. Anything I can help with?

MilesCranmer commented 1 year ago

Hm, still some infinite loops somewhere @shashi. I would leave this issue open if that's okay?

I don't have an MWE I can show you yet, but something in the following expression is freezing up the simplification, whereas with version < 1.0.0, it works fine (this expression is in the DynamicExpressions.jl test)

pow_abs(x, y) = abs(x)^y
custom_cos(x) = cos(x)^2
tree = (
    ((x2 + x2) * ((-0.5982493 / pow_abs(x1, x2)) / -0.54734415)) + (
        sin(
            custom_cos(
                sin(1.2926733 - 1.6606787) /
                sin(((0.14577048 * x1) + ((0.111149654 + x1) - -0.8298334)) - -1.2071426),
            ) * (custom_cos(x3 - 2.3201916) + ((x1 - (x1 * x2)) / x2)),
        ) / (0.14854191 - ((custom_cos(x2) * -1.6047639) - 0.023943262))
    )
)

This also simplifies fine with normal symbols; it's just LiteralReal that breaks.

Maybe there should be a unit test that does a brute force search over expression trees, and sees if they hit an infinite loop or not?

MilesCranmer commented 1 year ago

Okay, here is a MWE:

@syms x1::LiteralReal

simplify(sin((0.14577048 * x1) + ((0.111149654 + x1) - -0.8298334)))

this hangs indefinitely. If you point out where I could debug this I'd be happy to help, so I can merge the update faster

shashi commented 1 year ago

That does not hang for me on v1.0.3...

MilesCranmer commented 1 year ago

It's hanging for me on that version. Here's a video of what I am seeing: https://asciinema.org/a/576406 (I manually stop it after 2 minutes).

Maybe I'm just not waiting long enough?

Here's my versioninfo in case that is relevant:

Julia Version 1.9.0-rc2
Commit 72aec423c2a (2023-04-01 10:41 UTC)
Platform Info:
  OS: macOS (arm64-apple-darwin21.3.0)
  CPU: 8 × Apple M1 Pro
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, apple-m1)
  Threads: 6 on 6 virtual cores
Environment:
  JULIA_NUM_THREADS = auto
shashi commented 1 year ago

Thanks! I might have been on a branch and it was showing me v1.0.3, did you try it on master of SymbolicUtils?

MilesCranmer commented 1 year ago

Sweet!! v1.0.4 worked. Thanks!!

MilesCranmer commented 1 year ago

*master worked; I think the v1.0.4 on the registry still has the issue

shashi commented 1 year ago

Yes, that's right. I see a CI failure from an unrelated PR, will fix and release.