Skip to content

Rules behave differently for some trigonometric functions #748

@pmc4

Description

@pmc4

Hello. As described in this Julia Discourse post, when defining custom rules for some trigonometric identities, the behaviour is not consistent. It looks like some rules are missing or that they are not being applied. Let me show two MWE with two different trigonometric identities:

Problem 1

Here we define a custom rule for the sine of the double angle:

using SymbolicUtils

@syms a
r = @acrule(sin(2*~x) => 2*sin(~x)*cos(~x))

# This works and returns 2cos(a)*sin(a)
simplify(sin(2a), r)

# This doesn't work and returns (1//4)*sin(2a)
simplify(sin(2a) / 4, r)

The last call should return cos(a)*sin(a)//2, but instead does nothing. We can add an extra rule to solve this issue:

using SymbolicUtils

@syms a

rules = [
    @acrule(sin(2*~x) => 2 * sin(~x) * cos(~x))
    @acrule(~a * sin(2*~x) => ~a * 2 * sin(~x) * cos(~x))
]

r = RestartedChain(rules)

# Now it works and returns (1//2)*cos(a)*sin(a)
simplify(sin(2a) / 4, r)

However this is not efficient, I would like to simplify sin(2a) independently of whatever is being multiplied or whichever place the sine appears. For example, sin(2a) / sin(2b) does not get simplified. I've tried adding something like

@acrule(sin(~~x) / sin(~~y) => sin((~~x)...) / sin((~~y)...))

but it doesn't work either.

Problem 2

Now we define a custom rule for the product of two sine functions and perform the same naïve computation as we did with sin(2a) / 4 in Problem 1.

using SymbolicUtils

@syms λ a₁ a₂ a₃ a₄

r = @acrule cos(~x) * cos(~y) => (cos(~x - ~y) + cos(~x + ~y)) / 2

# Returns the correct result
# (1//32)*(cos(a₁*λ + a₂*λ) + cos(a₁*λ - a₂*λ))*(cos(a₃*λ + a₄*λ) + cos(-a₃*λ + a₄*λ))
simplify(cos(a₁ * λ) * cos(a₂ * λ) * cos(a₃ * λ) * cos(a₄ * λ) / 8, r)

In this case it is giving the correct result when we divide the expression by a number. It even detects that there are two pairs of cosines being multiplied. Nonetheless, if we now divide by λ instead of by 8, it no longer works:

# Returns again (cos(a₂*λ)*cos(a₃*λ)*cos(a₄*λ)*cos(a₁*λ)) / (λ^2)
simplify(cos(a₁ * λ) * cos(a₂ * λ) * cos(a₃ * λ) * cos(a₄ * λ) / λ^2, r)

I don't exactly know which kind of rules are missing or if this is a bug. I'd expect bot examples to fail the same way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions