about inverse_erf

115 views
Skip to first unread message

Buck Golemon

unread,
Dec 27, 2013, 5:40:40 PM12/27/13
to sage-s...@googlegroups.com
1) Sage seems unable to reduce `erf(x) == erf(y)` to `x == y`. How can I help this along?

solve(erf(x) == erf(y), x)[0].simplify_full()

Actual output: x == inverse_erf(erf(y))
Expected output: x == y

I had expected that sage would trivially reduce `inverse_erf(erf(y))` to `y`.

2) This output references 'inverse_erf', which doesn't seem to be importable t from anywhere in sage. Am I correct?

---

My concrete problem is re-deriving the formula for the normal-distribution cdf. I get a good solution from sage, but fail in showing that it's equivalent to a known solution because:

var('x sigma mu')
assume(sigma > 0)
eq3 = (-erf((sqrt(2)*mu - sqrt(2)*x)/(2*sigma)) == -erf((sqrt(2)*(mu - x))/(2*sigma)))
bool(eq3)

Actual output: False
Expected output: True


However this quite similar formula works fine:

eq3 = (-erf(sqrt(2)*mu - sqrt(2)*x) == -erf(sqrt(2)*(mu - x)))
bool(eq3)

Output: True

---
Include:
Platform (CPU) -- x86_64
Operating System -- Ubuntu 13.10
Exact version of Sage (command: "version()") -- 'Sage Version 5.13, Release Date: 2013-12-15'

JamesHDavenport

unread,
Dec 28, 2013, 1:07:41 PM12/28/13
to sage-s...@googlegroups.com
erf, as a function C->C, is not 1:1 (see 7.13(i) of DLMF), so this "simplification" would be incorrect.
I do not know how to tell Sage that you want real-valued functions/variables, when of course it would be correct to do the simplification.

JamesHDavenport

unread,
Dec 28, 2013, 2:00:27 PM12/28/13
to sage-s...@googlegroups.com
Furthermore, DLMF 7.17 only defines the inverse error function on the real line (in fact (-1,1))
I do not recall ever seeing a discussion of the complex inverse error function. Strecok (1968) shows that it satisfies y''=2yy'y',
but this is nonlinear, so the methodology of the paper below doesn't help.

Chyzak,F., Davenport,J.H., Koutschan,C. & Salvy,B.,
On Kahan's Rules for Determining Branch Cuts.
Proc. SYNSAC 2012 (ed. D. Wang et al.), IEEE Computer Society Press, Los Alamitos, CA, pp. 47-51



On Friday, 27 December 2013 22:40:40 UTC, Buck Golemon wrote:

Buck Golemon

unread,
Dec 28, 2013, 2:27:09 PM12/28/13
to sage-s...@googlegroups.com
Thanks. 
If I understand you, the problems lie in the complex domain, where I was only thinking of the real numbers.

Can I not do something to the effect of assume(x, 'real') ?

Buck Golemon

unread,
Dec 28, 2013, 2:32:02 PM12/28/13
to sage-s...@googlegroups.com
Yes, I can, but it doesn't have the intended (or any) effect:

sage: assume(x, 'real')
sage: assume(y, 'real')
sage: assumptions()
[x is real, y is real]
sage: solve(erf(x) == erf(y), x)
[x == inverse_erf(erf(y))]

Buck Golemon

unread,
Dec 28, 2013, 2:46:49 PM12/28/13
to sage-s...@googlegroups.com
I've found here:
http://mathworld.wolfram.com/InverseErf.html

erf^(-1)(erf(x))=x,
(2)

with the identity holding for x in R


Is this a bit of information that can be added (by me?) to sage?

JamesHDavenport

unread,
Dec 29, 2013, 12:32:01 PM12/29/13
to sage-s...@googlegroups.com
In fact you don't really need MathWorld: erf is continuous monotone R->(-1,1), so must have an inverse function (-1,1)->R.
How you tell Sage this needs a Sage expert.

Buck Golemon

unread,
Dec 30, 2013, 12:08:54 PM12/30/13
to sage-s...@googlegroups.com
So I've succeeded in telling maxima how to simplify this, but it doesn't translate through to sage:

sage: print maxima.eval('''                                                               
declare([x, y], real)                                                                     
solve(erf(x) = erf(y), x)                                                                 
''')
done
[x=inverse_erf(erf(y))]

sage: print maxima.eval('''                                                     
matchdeclare (xx, lambda ([e], featurep (e, real)));
tellsimpafter (inverse_erf (erf (xx)), xx);
matchdeclare (yy, lambda ([e], -1 < e and e < 1));
tellsimpafter (erf (inverse_erf (yy)), yy);
''')
done
[inverse_erfrule1,?simp\-inverse\-erf]
done
[erfrule1,?simp\-erf]

sage: print maxima.eval('''
solve(erf(x) = erf(y), x)
''')
[x=y]

sage: var('x y')
(x, y)

sage: assume(x, y, 'real')
sage: assumptions()
[x is real, y is real]

sage: solve(erf(x) == erf(y), x)
[x == inverse_erf(erf(y))]

--
You received this message because you are subscribed to a topic in the Google Groups "sage-support" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sage-support/OlHZAPXeWdQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sage-support...@googlegroups.com.
To post to this group, send email to sage-s...@googlegroups.com.
Visit this group at http://groups.google.com/group/sage-support.
For more options, visit https://groups.google.com/groups/opt_out.

Ivan Andrus

unread,
Dec 30, 2013, 12:36:31 PM12/30/13
to sage-s...@googlegroups.com
I think this might be because "the maxima used by the calculus package is different than the one in the interactive interpreter."  That's from sage.calculus.calculus?

Try the following:

sage: from sage.calculus.calculus import maxima as sm
sage: sm.eval('''matchdeclare (xx, lambda ([e], featurep (e, real)));
tellsimpafter (inverse_erf (erf (xx)), xx);
matchdeclare (yy, lambda ([e], -1 < e and e < 1));
tellsimpafter (erf (inverse_erf (yy)), yy);''');

sage: solve(erf(x) == erf(y), x)
[x == inverse_erf(erf(y))]
sage: assume(x, y, 'real')
sage: solve(erf(x) == erf(y), x)
[x == y]

-Ivan

You received this message because you are subscribed to the Google Groups "sage-support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sage-support...@googlegroups.com.

Buck Golemon

unread,
Dec 31, 2013, 2:39:34 PM12/31/13
to sage-s...@googlegroups.com
Yes, thanks!
That helped.

Sage will now reduce those erf functions, sometimes.

This equation will solve x as `x == r1`:


forget()
var('x mu sigma')
assume(sigma>0)
assume(x, mu, sigma, 'real')

from sage.calculus.calculus import maxima
maxima.eval('''matchdeclare(xx, lambda ([e], featurep (e, real)));\ntellsimpafter (inverse_erf (erf (xx)), xx);\nmatchdeclare (yy, lambda ([e], -1 < e and e < 1));\ntellsimpafter (erf (inverse_erf (yy)), yy);''')

demo = (-erf( sqrt(2)*(mu - x)) == -erf( sqrt(2)*mu - sqrt(2)*x))
show(demo)
show(solve(demo, x))
show(solve(solve(demo, x), x))
show(bool(demo))


1) Is it bad that I need to call solve() twice here?
2) What is r1?

This quite similar equation however refuses to solve and has boolean value False:

eqn = (1/2*erf(-(sqrt(2)*mu - sqrt(2)*x)/(2*sigma)) + 1/2 == 1/2*erf(-sqrt(2)*(mu - x)/(2*sigma)) + 1/2)

show(eqn)
show(solve(eqn, x))
show(solve(solve(eqn, x), x))
show(bool(eqn))


Actual output: False
Expected output: True


3) What prevents sage from knowing these arguments are real and using the above user-defined simpification?

Ivan Andrus

unread,
Dec 31, 2013, 6:36:39 PM12/31/13
to sage-s...@googlegroups.com
I'm afraid I'm in over my head here.  Though I do know that bool(eqn) doesn't necessarily mean what you think it means.

-Ivan
Reply all
Reply to author
Forward
0 new messages