Revision history [back]

I can answer the "why it does that" question, anyway: Sage follows Maxima's conventions on equality testing. That is, it only returns True if it's convinced the equality holds. "False" here translates as "False or unknown".

I actually couldn't find a good workaround-- I'm not sure what the right way to fake new rewrite rules is. I guess you could confirm that the lhs and rhs agree via something like this:

sage: eq = arcsin(x) == 2*arctan(x/(sqrt(-x*x+1)+1))
sage: bool(eq)
False
sage: # but..
sage: bool(eq.subs(x=0))
True
sage: bool(diff(eq, x))
True

And if you had several cases where the "agree at one point and derivatives equal" trick works, you could put it in a function, maybe with something like this: Warning: untested code!
def tryharder_bool(some_expr):
# hack hack hack
if some_expr:
return True
try:
v = some_expr.variables()
if len(v) == 1:
if bool(some_expr.subs({v[0]:0})) and bool(diff(some_expr, v[0])):
return True
except:
pass
return False

giving
sage: bool(eq)
False
sage: tryharder_bool(eq)
True


I can answer the "why it does that" question, anyway: Sage follows Maxima's conventions on equality testing. That is, it only returns True if it's convinced the equality holds. "False" here translates as "False or unknown".

I actually couldn't find a good workaround-- I'm not sure what the right way to fake new rewrite rules is. I guess you could confirm that the lhs and rhs agree via something like this:

sage: eq = arcsin(x) == 2*arctan(x/(sqrt(-x*x+1)+1))
sage: bool(eq)
False
sage: # but..
sage: bool(eq.subs(x=0))
True
sage: bool(diff(eq, x))
True


And if you had several cases where the "agree at one point and derivatives equal" trick works, you could put it in a function, maybe with something like this: this:

Warning: untested code!

def tryharder_bool(some_expr):
# hack hack hack
if some_expr:
return True
try:
v = some_expr.variables()
if len(v) == 1:
if bool(some_expr.subs({v[0]:0})) and bool(diff(some_expr, v[0])):
return True
except:
pass
return False

giving

giving

sage: bool(eq)
False
sage: tryharder_bool(eq)
True


I can answer the "why it does that" question, anyway: Sage follows Maxima's conventions on equality testing. That is, it only returns True if it's convinced the equality holds. "False" here translates as "False or unknown".

I actually couldn't find a good workaround-- I'm not sure what the right way to fake new rewrite rules is. I guess you could confirm that the lhs and rhs agree via something like this:

sage: eq = arcsin(x) == 2*arctan(x/(sqrt(-x*x+1)+1))
sage: bool(eq)
False
sage: # but..
sage: bool(eq.subs(x=0))
True
sage: bool(diff(eq, x))
True


And if you had several cases where the "agree at one point and derivatives equal" trick works, you could put it in a function, maybe with something like this:

Warning: untested code!code! Will probably break when given unexpected input!

def tryharder_bool(some_expr):
# hack hack hack
if some_expr:
return True
try:
if type(some_expr) == Expression and some_expr.is_relational():
v = some_expr.variables()
if len(v) == 1:
if bool(some_expr.subs({v[0]:0})) and bool(diff(some_expr, v[0])):
return True
except:
pass
return False


giving

sage: bool(eq)
False
sage: tryharder_bool(eq)
True


I can answer the "why it does that" question, anyway: Sage follows Maxima's conventions on equality testing. That is, it only returns True if it's convinced the equality holds. "False" here translates as "False or unknown".

I actually couldn't find a good workaround-- I'm not sure what the right way to fake new rewrite rules is. I guess you could confirm that the lhs and rhs agree via something like this:

sage: eq = arcsin(x) == 2*arctan(x/(sqrt(-x*x+1)+1))
sage: bool(eq)
False
sage: # but..
sage: bool(eq.subs(x=0))
True
sage: bool(diff(eq, x))
True


And if you had several cases where the "agree at one point and derivatives equal" trick works, you could put it in a function, maybe with something like this:

Warning: untested code! Will probably break when given unexpected input!

 def tryharder_bool(some_expr):
# hack hack hack
if some_expr:
return True
try:
if type(some_expr) == Expression and some_expr.is_relational():
v = some_expr.variables()
if len(v) == 1:
if bool(some_expr.subs({v[0]:0})) and bool(diff(some_expr, v[0])):
if some_expr.subs({v[0]:0}) and diff(some_expr, v[0]):
return True
except:
pass
return False


giving

sage: bool(eq)
False
sage: tryharder_bool(eq)
True


I can answer the "why it does that" question, anyway: Sage follows Maxima's conventions on equality testing. That is, it only returns True if it's convinced the equality holds. "False" here translates as "False or unknown".

I actually couldn't find a good workaround-- I'm not sure what the right way to fake new rewrite rules is. I guess you could confirm that the lhs and rhs agree via something like this:

sage: eq = arcsin(x) == 2*arctan(x/(sqrt(-x*x+1)+1))
sage: bool(eq)
False
sage: # but..
sage: bool(eq.subs(x=0))
True
sage: bool(diff(eq, x))
True


And if you had several cases where the "agree at one point and derivatives equal" trick works, you could put it in a function, maybe with something like this:

Warning: untested code! Will probably break when given unexpected input!


def tryharder_bool(some_expr):
# hack hack hack
if some_expr:
return True
if type(some_expr) == Expression and some_expr.is_relational():
v = some_expr.variables()
if len(v) == 1:
if some_expr.subs({v[0]:0}) and diff(some_expr, v[0]):
return True
return False


giving

sage: bool(eq)
False
sage: tryharder_bool(eq)
True


UPDATE:

For some of the other cases mentioned in the comments, playing around with the trig_* functions and/or converting to exponential form works:

sage: eq1 = arcsin(x) == 2*arctan(x/(sqrt(-x*x+1)+1))
sage: eq2 = sin(x) == 2*sin(x/2)*cos(x/2)
sage: eq3 = sin(2*x) == 2*sin(x)*cos(x)
sage: eq4 = tan(x/2) == sin(x)/(1+cos(x))
sage: eqs = eq1, eq2, eq3, eq4
sage: [bool(q) for q in eqs]
[False, False, True, False]
sage: [bool(q.trig_reduce()) for q in eqs]
[False, True, True, False]
sage: [bool(q.trig_expand()) for q in eqs]
[False, False, True, False]
sage: [bool(q.trig_expand(half_angles=True)) for q in eqs]
[False, False, True, True]
sage:
sage:
sage: eq2.maxima_methods().exponentialize()
1/2*I*e^(-I*x) - 1/2*I*e^(I*x) == 1/2*(I*e^(-1/2*I*x) - I*e^(1/2*I*x))*(e^(-1/2*I*x) + e^(1/2*I*x))
sage: eq1.maxima_methods().exponentialize()
arcsin(x) == 2*arctan(x/(sqrt(-x^2 + 1) + 1))
sage: [bool(q.maxima_methods().exponentialize()) for q in eqs]
[False, True, True, True]
sage:
sage: def trig_xeq_check(eq):
....:         return bool(eq) or bool(eq.maxima_methods().exponentialize()) or (bool(eq.subs(x=0)) and bool(diff(eq,x)))
....:
sage:
sage: [trig_xeq_check(q) for q in eqs]
[True, True, True, True]