Oscar, Yes, this is what I want to check. Thanks for taking the time to write this code. I'll give it a try.
In the meantime I did get my code to run. I think Python was actually being "Killed" by trying to lambdify an expression with thousands of operations. I then switched to expr.evalf(subs=<a bunch of floats>) and it wouldn't complete either. Finally, expr.xreplace(<a bunch of floats>) completes. I also reduced the number of symbolic arguments for the lambdify call by ensuring only the ones that were needed were used. def compare_cse(expr, args=None): def find_args(expr): args = list(expr.free_symbols) # get constants and time try: # time not explicit, so remove if there args.remove(TIME) except ValueError: # time not present pass args += me.find_dynamicsymbols(expr) # get the functions of time return list(sm.ordered(args)) if args is None: args = find_args(expr) vals = list(np.random.random(len(args))) value_dict = {s: v for s, v in zip(args, vals)} # This is where it is getting killed! Can't lambdify M it seems. #print('lambdifying the whole expression') #eval_expr = sm.lambdify(args, expr) #print('Evaluate the whole expression') #res = eval_expr(*vals) # this also doesn't complete (haven't waited for it to complete) #res = sm.matrix2numpy(expr.evalf(subs=value_dict), dtype=float) print('xreplace whole expr') res = sm.matrix2numpy(expr.xreplace(value_dict), dtype=float) print('Find common sub expressions') replacements, reduced_expr = sm.cse(expr) print('Evaluate each subexpression') for (var, sub_expr) in replacements: print('Sub expression {}'.format(var)) sub_expr_args = find_args(sub_expr) sub_expr_vals = [value_dict[s] for s in sub_expr_args] eval_sub_expr = sm.lambdify(sub_expr_args, sub_expr) value_dict[var] = eval_sub_expr(*sub_expr_vals) red_expr_args = find_args(reduced_expr[0]) red_expr_vals = [value_dict[s] for s in red_expr_args] eval_reduced_expr = sm.lambdify(red_expr_args, reduced_expr[0]) cse_res = eval_reduced_expr(*red_expr_vals) np.testing.assert_allclose(res, cse_res) The good thing is that I am getting matching results from an xreplaced large expression and the cse'd version of that expression evaluated using lambdify. I'm think the bug is now in PyDy's c-code generation (that use's cse). Maybe I can adapt your code to evaluating the c code in some way. Jason moorepants.info +01 530-601-9791 On Fri, Oct 23, 2020 at 1:00 PM Oscar Benjamin <oscar.j.benja...@gmail.com> wrote: > Hi Jason, > > I'm approaching this from the perspective that this is a bug in > cse/lambdify and that you want to identify which part of a large > expression tree triggers the bug. Since evaluating the whole > expression is slow I would start by testing smaller subexpressions and > work up from there. You can get something like that with: > > from sympy.utilities.iterables import postorder_traversal > > def cse_compare(expr, syms, vals): > result = lambdify(syms, expr)(*vals) > > syms_all, vals_all = list(syms), list(vals) > reps, [reduced_expr] = cse(expr) > for csesym, cseexpr in reps: > val = lambdify(syms_all, cseexpr)(*vals_all) > syms_all.append(csesym) > vals_all.append(val) > result_cse = lambdify(syms_all, reduced_expr)(*vals_all) > > return abs(result - result_cse) / abs(result) > > def cse_compare_bottom_up(expr): > syms = list(expr.free_symbols) > vals = list(np.random.random(len(syms))) > > def subexprs(): > seen = set() > for e in postorder_traversal(expr): > if e not in seen: > yield e > seen.add(e) > > # possibly better: > #exprs = sorted(set(postorder_traversal(expr)), key=lambda e: > e.count_ops()) > exprs = subexprs() > > for subexpr in exprs: > print() > print(subexpr) > print(cse_compare(expr, syms, vals)) > > test_expr = (sin(x+1) + 2*cos(x-3)).expand(trig=True) > cse_compare_bottom_up(test_expr) > > > Oscar > > On Fri, 23 Oct 2020 at 07:59, Jason Moore <moorepa...@gmail.com> wrote: > > > > Oscar, > > > > Yes I can try evaluating in different orders. That's an interesting idea. > > > > I also may be breaking lambdify with too many arguments. I can store the > numerical results of each subexpression in a dictionary, then identify the > minimal set of variables in each subsequent subexpression, and only > lambdify with that very much smaller set of arguments. Maybe that will fix > it. > > > > I'll try both. > > > > Jason > > moorepants.info > > +01 530-601-9791 > > > > > > On Fri, Oct 23, 2020 at 8:56 AM Oscar Gustafsson < > oscar.gustafs...@gmail.com> wrote: > >> > >> Yes, you are right that the email is about a different topic. However, > it can be worth noting that evaluating floating-point expressions in > different order, which is basically what you do using cse:s, can give > different results due to the floating-point quantization/rounding happening > at different places. Hence, it is not always obvious to tell if the results > are "identical". If you are unlucky, the error propagation can be quite > disastrous at times, but you are probably correct in that there is > something else that is the primary issue here. > >> > >> BR Oscar > >> > >> Den tors 22 okt. 2020 kl 18:57 skrev Jason Moore <moorepa...@gmail.com > >: > >>> > >>> As far as I understand the results should match to machine precision. > >>> > >>> We are able to match these kinds of models executed on different > platforms using different formulation techniques to machine precision (e-14 > or more). In fact, we use this to be able to verify that two independent > modelers have created the same model. > >>> > >>> The fact that my model can't get the same results with two numerical > evaluations of sympy code is concerning. > >>> > >>> My question in this email though, is how to improve the comparison > code so that it doesn't crash for large expressions. > >>> > >>> Jason > >>> moorepants.info > >>> +01 530-601-9791 > >>> > >>> > >>> On Thu, Oct 22, 2020 at 6:49 PM Oscar Gustafsson < > oscar.gustafs...@gmail.com> wrote: > >>>> > >>>> How much do they differ? I checked the issue and the latest result > wasn't that bad, although probably too much to blame floating-point errors. > However, if you push the numerical range into e.g. denormalized numbers I > guess it can simply be that. Not very likely though. Is it still that type > of numerical errors? > >>>> > >>>> BR Oscar > >>>> > >>>> Den tors 22 okt. 2020 09:37Jason Moore <moorepa...@gmail.com> skrev: > >>>>> > >>>>> Howdy, > >>>>> > >>>>> I'm trying to track down a bug in this PR: > >>>>> > >>>>> https://github.com/pydy/pydy/pull/122 > >>>>> > >>>>> I have quite large SymPy expressions which I evaluate with floating > point numbers. I also cse those expressions and evaluate those with the > same floating point numbers. I'm getting discrepancies in the results. I'd > like to eliminate the possibility that the cse'd expressions are different > from the original expression. I wrote this naive function to make the > comparison: > >>>>> > >>>>> def compare_cse(expr): > >>>>> > >>>>> args = list(expr.free_symbols) > >>>>> args.remove(TIME) > >>>>> args += me.find_dynamicsymbols(expr) > >>>>> args = list(sm.ordered(args)) > >>>>> vals = list(np.random.random(len(args))) > >>>>> > >>>>> eval_expr = sm.lambdify(args, expr) > >>>>> res = eval_expr(*vals) > >>>>> > >>>>> replacements, reduced_expr = sm.cse(expr) > >>>>> for repl in replacements: > >>>>> var = repl[0] > >>>>> sub_expr = repl[1] > >>>>> eval_sub_expr = sm.lambdify(args, sub_expr) > >>>>> vals.append(eval_sub_expr(*vals)) > >>>>> args.append(var) > >>>>> eval_reduced_expr = sm.lambdify(args, reduced_expr[0]) > >>>>> cse_res = eval_reduced_expr(*vals) > >>>>> > >>>>> np.testing.assert_allclose(res, cse_res) > >>>>> > >>>>> This seems to work for small expressions, but for the large > expressions run this actually kills my Python interpreter after some > minutes. > >>>>> > >>>>> Is there a better way to write this? I need some way to verify that > numerical evaluation of a cse'd expression gives the same result as > numerical evaluation of the expression that can actually complete in a > reasonable amount of time. > >>>>> > >>>>> Jason > >>>>> moorepants.info > >>>>> +01 530-601-9791 > >>>>> > >>>>> -- > >>>>> You received this message because you are subscribed to the Google > Groups "sympy" group. > >>>>> To unsubscribe from this group and stop receiving emails from it, > send an email to sympy+unsubscr...@googlegroups.com. > >>>>> To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/CAP7f1Aivs53AcwyaoyO5%2Bzkn%2BPrX3TfoJJ5X85qQNZ6JRbo5JQ%40mail.gmail.com > . > >>>> > >>>> -- > >>>> You received this message because you are subscribed to the Google > Groups "sympy" group. > >>>> To unsubscribe from this group and stop receiving emails from it, > send an email to sympy+unsubscr...@googlegroups.com. > >>>> To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/CAFjzj-LQNBFoF7Q4Rb%2BZG3J35-Et9b__SED-DMJvwUYqyKYADQ%40mail.gmail.com > . > >>> > >>> -- > >>> You received this message because you are subscribed to the Google > Groups "sympy" group. > >>> To unsubscribe from this group and stop receiving emails from it, send > an email to sympy+unsubscr...@googlegroups.com. > >>> To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/CAP7f1AgdkaC0D69s_ohka_AjDFvKCD%2BMoVKyFhs0Vn2b_DtFkw%40mail.gmail.com > . > >> > >> -- > >> You received this message because you are subscribed to the Google > Groups "sympy" group. > >> To unsubscribe from this group and stop receiving emails from it, send > an email to sympy+unsubscr...@googlegroups.com. > >> To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/CAFjzj-LFUSgmQ90Uok2LxKSTZ-bJKysCy%2BGqvs1wYtDErUAZNA%40mail.gmail.com > . > > > > -- > > You received this message because you are subscribed to the Google > Groups "sympy" group. > > To unsubscribe from this group and stop receiving emails from it, send > an email to sympy+unsubscr...@googlegroups.com. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/CAP7f1Ai1UbiR6vLZs7_PTmY2WOk-VpsqYTSsTm4KUi6e9Y78qQ%40mail.gmail.com > . > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sympy+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/CAHVvXxRPevyn7SOROy04jSTe2hMkQbhkQafYBTTDMDYo18dTRQ%40mail.gmail.com > . > -- You received this message because you are subscribed to the Google Groups "sympy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sympy+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAP7f1AgfuhpZDJpwoeYVA0yr8VVEUOArPhX6e%3D43tcVS9F6Vtg%40mail.gmail.com.