Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sym(x, 'r') heuristics poor for small x < 1e-17 #1272

Open
ASalahHammad opened this issue Sep 11, 2023 · 4 comments
Open

sym(x, 'r') heuristics poor for small x < 1e-17 #1272

ASalahHammad opened this issue Sep 11, 2023 · 4 comments

Comments

@ASalahHammad
Copy link

Whenever there's an expression that looks exactly like this and with such large numbers as coefficients:

syms x y z
exp = 1.435647686e28 * (1e-19*x + 1e-22*y + z*1e-15)
        [Output]:
                  9223372036854775807⋅z
          x + y + ─────────────────────
                     1000000000000000
vpa(ans)
        [Output]:
        ans = (sym) x + y + 9223.37203686⋅z

Screenshot from 2023-09-11 17-51-29

which is obviously wrong.. and the problem persists whenever an expression is evaluated, for example:

f = @(x,y,z) 1.435647686e28 * (1e-19*x + 1e-22*y + z*1e-15)
        [Output]:
        f =
        @(x, y, z) 1.435647686e28 * (1e-19 * x + 1e-22 * y + z * 1e-15)
syms x y z
f(x,y,z)
        [Output]:
                  9223372036854775807⋅z
          x + y + ─────────────────────
                     1000000000000000

And even when sending the whole expression to the built in function 'eval' and started debugging a little, the expression keeps ok until it is evaluated at the function fh, as appearing in the screenshot attached
Screenshot from 2023-09-11 18-00-42

And.., the same code works on matlab well..

I tried the same thing using octave v:7.1.1 and v:9.0.0 on a PC with Linux Ubuntu

@cbm755
Copy link
Collaborator

cbm755 commented Sep 14, 2023

That does seem poor... But you are ignoring this warning:

warning: passing floating-point values to sym is dangerous, see "help sym"

Compare the difference between these:

1e-23*x
warning: passing floating-point values to sym is dangerous, see "help sym"
warning: called from
    double_to_sym_heuristic at line 50 column 7
    sym at line 379 column 13
    mtimes at line 54 column 5

ans = (sym)
           x         
  ───────────────────
  9223372036854775807


octave:28> sym(1)*sym(10)^(-23)*x
ans = (sym)
             x            
  ────────────────────────
  100000000000000000000000

@cbm755
Copy link
Collaborator

cbm755 commented Sep 14, 2023

I'm not sure if this can be improved but the root of this problem is the following. I've hidden most of the warnings, but I re-iterate that converting doubles to sym is a bad idea, that's what the warning is telling us.

> sym(1e-15)
warning: passing floating-point values to sym is dangerous, see "help sym"
ans = (sym) 1/1000000000000000

> sym(1e-16)
warning: passing floating-point values to sym is dangerous, see "help sym"
ans = (sym) 1/10000000000000000

> sym(1e-17)
warning: passing floating-point values to sym is dangerous, see "help sym"
ans = (sym) 1/100000000000000000

> sym(1e-18)
warning: passing floating-point values to sym is dangerous, see "help sym"
ans = (sym) 1/999999999999999872

> sym(1e-19)
warning: passing floating-point values to sym is dangerous, see "help sym"
ans = (sym) 1/9223372036854775807

> sym(1e-20)
warning: passing floating-point values to sym is dangerous, see "help sym"
ans = (sym) 1/9223372036854775807

@cbm755
Copy link
Collaborator

cbm755 commented Sep 14, 2023

This 9223372036854775807 number is 2^63 - 1: presumably a int64 is being created somewhere along the way... Python int's have no max but int64 or uint64 certainly do...

@cbm755
Copy link
Collaborator

cbm755 commented Sep 14, 2023

Using ratflag as f is working fine:

sym(1e-23, 'f')
ans = (sym)
              6805647338418769           
  ───────────────────────────────────────
  680564733841876926926749214863536422912

So I tracked this to @sym/private/double_to_sym_heuristic.m:

    [N1, D1] = rat (x);
    [N2, D2] = rat (x / pi);
    N3 = round (x^2);
    err1 = abs (N1 / D1 - x);
    err2 = abs ((N2*pi) / D2 - x);
    err3 = abs (sqrt (N3) - x);
    if (err1 <= err3)
      if (err1 <= err2)
        y = pycall_sympy__ ('return Rational(*_ins)', int64 (N1), int64 (D1));
      else
        y = pycall_sympy__ ('return Rational(*_ins)*S.Pi', int64 (N2), int64 (D2));
      end
    else
      y = pycall_sympy__ ('return sqrt(Integer(*_ins))', int64 (N3));
    end

observations

  • Lots of double precision calculations being done there
  • none of those err calculations are accurate at these scales
  • values being passed are limited to int64

decisions to be made

  • since its a heuristic function, perhaps there should be a hardcoded range where the heuristics are applied...
  • outside of that range, either an error or better yet fall back on ratflag 'f'
  • and/or go back to rats: IIRC it was worse, but it would give a string.

@cbm755 cbm755 changed the title [Octave SourceForge] A problem with evaluating symbolic expression sym(x, 'r') heuristics poor for small x < 1e-17 Sep 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants