Skip to content

Commit

Permalink
Merge pull request #873 from Mathics3/add-ComplexExpand
Browse files Browse the repository at this point in the history
Add complex expand
  • Loading branch information
rocky authored Jul 6, 2023
2 parents ad77ccf + 91683f0 commit 541c281
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ New Builtins
#. ``$PythonImplementation``
#. ``Accuracy``
#. ``ClebschGordan``
#. ``ComplexExpand`` (@yzrun)
#. ``Curl`` (2-D and 3-D vector forms only)
#. ``DiscretePlot``
#. ``Kurtosis``
Expand Down
1 change: 1 addition & 0 deletions SYMBOLS_MANIFEST.txt
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ System`CompiledCodeBox
System`CompiledFunction
System`Complement
System`Complex
System`ComplexExpand
System`ComplexInfinity
System`Complexes
System`CompositeQ
Expand Down
66 changes: 64 additions & 2 deletions mathics/builtin/numbers/hyperbolic.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@
from typing import Optional

from mathics.builtin.arithmetic import _MPMathFunction
from mathics.builtin.base import Builtin
from mathics.builtin.base import Builtin, SympyFunction
from mathics.core.atoms import IntegerM1
from mathics.core.convert.sympy import SympyExpression
from mathics.core.evaluation import Evaluation
from mathics.core.expression import Expression
from mathics.core.list import ListExpression
from mathics.core.symbols import Symbol, SymbolPower
from mathics.eval.hyperbolic import eval_ComplexExpand

SymbolArcCosh = Symbol("ArcCosh")
SymbolArcSinh = Symbol("ArcSinh")
Expand Down Expand Up @@ -246,9 +249,68 @@ class ArcTanh(_MPMathFunction):
sympy_name = "atanh"


class ComplexExpand(SympyFunction):
"""
(<url>
:SymPy:
https://docs.sympy.org/latest/
modules/core.html#sympy.core.expr.Expr.expand</url>, <url>:WMA:
https://reference.wolfram.com/language/ref/ComplexExpand.html
</url>)
<dl>
<dt>'ComplexExpand[$expr$]'
<dd>expands $expr$ assuming that all variables are real.
</dl>
Note: we get equivalent, but different results from WMA:
>> ComplexExpand[3^(I x)]
= 3 ^ (-Im[x]) Re[3 ^ (I Re[x])] + I Im[3 ^ (I Re[x])] 3 ^ (-Im[x])
Assume that both and are real:
>> ComplexExpand[Sin[x + I y]]
= Cosh[y] Sin[x] + I Cos[x] Sinh[y]
Take $x$ to be complex:
>> ComplexExpand[Sin[x], x]
= Cosh[Im[x]] Sin[Re[x]] + I Cos[Re[x]] Sinh[Im[x]]
Polynomials:
>> ComplexExpand[Re[z^5 - 2 z^3 - z + 1], z]
= 1 + Re[z] ^ 5 - 2 Re[z] ^ 3 - Re[z] - 10 Im[z] ^ 2 Re[z] ^ 3 + 5 Im[z] ^ 4 Re[z] + 6 Im[z] ^ 2 Re[z]
Trigonometric and hyperbolic functions
>> ComplexExpand[Cos[x + I y] + Tanh[z], {z}]
= Cos[x] Cosh[y] - I Sin[x] Sinh[y] + Cosh[Re[z]] Sinh[Re[z]] / (Cos[Im[z]] ^ 2 + Sinh[Re[z]] ^ 2) + I Cos[Im[z]] Sin[Im[z]] / (Cos[Im[z]] ^ 2 + Sinh[Re[z]] ^ 2)
Exponential and logarithmic functions:
>> ComplexExpand[Abs[2^z Log[2 z]], z]
= Abs[I Arg[Re[z] + I Im[z]] + Log[4 Im[z] ^ 2 + 4 Re[z] ^ 2] / 2] 2 ^ Re[z]
Specify that a variable is take to be complex:
>> ComplexExpand[Re[2 z^3 - z + 1], z]
= 1 - Re[z] + 2 Re[z] ^ 3 - 6 Im[z] ^ 2 Re[z]
"""

summary_text = "expand a complex expression of real variables"
sympy_name = "expand"

def eval(self, expr, evaluation: Evaluation):
"ComplexExpand[expr_]"
return eval_ComplexExpand(expr, ListExpression())

def eval_with_complex_vars(self, expr, vars, evaluation: Evaluation):
"ComplexExpand[expr_, vars__]"
return eval_ComplexExpand(expr, vars)


class Cosh(_MPMathFunction):
"""
<url>:WMA link:https://reference.wolfram.com/language/ref/Cosh.html</url>
<url>
:WMA link:
https://reference.wolfram.com/language/ref/Cosh.html</url>
<dl>
<dt>'Cosh[$z$]'
Expand Down
22 changes: 22 additions & 0 deletions mathics/eval/hyperbolic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""
Mathics3 builtins from mathics.core.numbers.hyperbolic
"""
from sympy import Symbol as SympySymbol

from mathics.core.convert.sympy import from_sympy


def eval_ComplexExpand(expr, vars):
sympy_expr = expr.to_sympy()
if hasattr(vars, "elements"):
sympy_vars = {v.to_sympy() for v in vars.elements}
else:
sympy_vars = {vars.to_sympy()}
# All vars are assumed to be real
replaces = [
(fs, SympySymbol(fs.name, real=True))
for fs in sympy_expr.free_symbols
if fs not in sympy_vars
]
sympy_expr = sympy_expr.subs(replaces)
return from_sympy(sympy_expr.expand(complex=True))
11 changes: 11 additions & 0 deletions test/builtin/numbers/test_hyperbolic.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,14 @@ def test_gudermannian():
("Gudermannian[z]", "2 ArcTan[Tanh[z / 2]]"),
):
check_evaluation(str_expr, str_expected)


def test_complexexpand():
for str_expr, str_expected in (
("ComplexExpand[Sin[x + I y]]", "Cosh[y]*Sin[x] + I*Cos[x]*Sinh[y]"),
(
"ComplexExpand[3^(I x)]",
"3 ^ (-Im[x]) Re[3 ^ (I Re[x])] + I Im[3 ^ (I Re[x])] 3 ^ (-Im[x])",
),
):
check_evaluation(str_expr, str_expected)

0 comments on commit 541c281

Please sign in to comment.