Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

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
click to hide/show revision 5
added more trig simplifications

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]