<jupyter_start><jupyter_text>Complex Arithmetic Tutorial Workbook**What is this workbook?**A workbook is a collection of problems, accompanied by solutions to them. The explanations focus on the logical steps required to solve a problem; they illustrate the concepts that need to be applied to come up with a solution to the problem, explaining the mathematical steps required. Note that a workbook should not be the primary source of knowledge on the subject matter; it assumes that you've already read a tutorial or a textbook and that you are now seeking to improve your problem-solving skills. You should attempt solving the tasks of the respective kata first, and turn to the workbook only if stuck. While a textbook emphasizes knowledge acquisition, a workbook emphasizes skill acquisition.This workbook describes the solutions to the problems offered in the [Complex Arithmetic tutorial](./ComplexArithmetic.ipynb). Since the tasks are offered as programming problems, the explanations also cover some elements of Python that might be non-obvious for a first-time user.**What you should know for this workbook**1. Basic math.2. Basic Python knowledge is helpful but not necessary. Click the cell with code below this block of text and press `Ctrl+Enter` (`⌘+Enter` on Mac). **Do not skip this step**.<jupyter_code># Run this cell using Ctrl+Enter (⌘+Enter on Mac).
from testing import exercise
from typing import Tuple

import math

Complex = Tuple[float, float]
Polar = Tuple[float, float]<jupyter_output><empty_output><jupyter_text>Exercise 1: Powers of $i$.**Input:** An even integer $n$.**Goal:** Return the $n$th power of $i$, or $i^n$.  Solution When raising $i$ to an integer power, the answer will vary according to a certain pattern. To figure it out, notice that raising $i$ to the power of 4 gives: $i^4 = i^2 \cdot i^2 = (-1) \cdot (-1) = 1$. Thus, when the power $n$ is divisible by 4, $i^n$ will always be 1. When the power $n$ is not divisible by 4, you can use the previous observation to see that $i^n = i^{n \mod 4}$. For an even power $n$ that is not divisible by 4 you'll have $i^n = i^2 = -1.$Here is the complete pattern that arises when raising $i$ to non-negative powers. Note that it is periodic with period 4.|Power of $i$ | $i^0$ | $i^1$ | $i^2$ | $i^3$ | $i^4$ | $i^5$ | $i^6$ | $i^7$ | $i^8$ | $\dots$ ||----|----|----|----|----|----|----|----|----|----|----||Result | $1$ | $i$ | $-1$ | $-i$ | $1$ | $i$ | $-1$ | $-i$ | $1$ | $\dots$ |> *Python note*:  `%` is the Python modulo operator which returns the remainder of a division. For example, `7%2` gives 1, because 1 is the remainder of dividing 7 by 2.  > We can use this operator to figure out whether the power $n$ is divisible by 4.<jupyter_code>@exercise
def imaginary_power(n : int) -> int:
    # If n is divisible by 4
    if n % 4 == 0:
        return 1
    else:
        return -1<jupyter_output><empty_output><jupyter_text>[Return to task 1 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-1:-Powers-of-$i$.)  Exercise 2: Complex addition.**Inputs:**1. A complex number $x = a + bi$, represented as a tuple `(a, b)`.2. A complex number $y = c + di$, represented as a tuple `(c, d)`.**Goal:** Return the sum of these two numbers $x + y = z = g + hi$, represented as a tuple `(g, h)`.  SolutionAdding two complex numbers can be done by separately adding the real parts of the numbers and the imaginary parts:  $$ z = x + y = (a + bi) + (c + di) = \underset{real}{\underbrace{(a + c)}} + \underset{imaginary}{\underbrace{(b + d)}}i $$<jupyter_code>@exercise
def complex_add(x : Complex, y : Complex) -> Complex:
    # You can extract elements from a tuple like this
    a = x[0]
    b = x[1]
    
    c = y[0]
    d = y[1]
    
    # This creates a new variable and stores the real component into it
    real = a + c
    # Replace the ... with code to calculate the imaginary component
    imaginary = b + d
    
    # You can create a tuple like this, with the real and imaginary part of the number
    ans = (real, imaginary)
    
    return ans<jupyter_output><empty_output><jupyter_text>[Return to task 2 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-2:-Complex-addition.)  Exercise 3: Complex multiplication.**Inputs:**1. A complex number $x = a + bi$, represented as a tuple `(a, b)`.2. A complex number $y = c + di$, represented as a tuple `(c, d)`.**Goal:** Return the product of these two numbers $x \cdot y = z = g + hi$, represented as a tuple `(g, h)`.  SolutionMultiplying complex numbers is like multiplying polynomials, therefore the same rules apply. **Remember** $i^2 =-1$.  $$z = x \cdot y = (a + bi)(c + di) = a \cdot c + a \cdot di + c \cdot bi + bi \cdot di = \underset{real}{\underbrace{a \cdot c - b \cdot d}} + \underset{imaginary}{\underbrace{(a \cdot d + c \cdot b)}}i $$<jupyter_code>@exercise
def complex_mult(x : Complex, y : Complex) -> Complex:
    
    # Here is another, more compact way of extracting the parts of the complex number:
    (a, b) = x
    (c, d) = y
    
    real = (a * c) - (b * d)
    imaginary = (a * d) + (c * b)
    
    # Instead of creating a separate tuple with the result, we return the tuple directly
    return (real, imaginary)<jupyter_output><empty_output><jupyter_text>[Return to task 3 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-3:-Complex-multiplication.)  Exercise 4: Complex conjugate.**Input:** A complex number $x = a + bi$, represented as a tuple `(a, b)`.**Goal:** Return $\overline{x} = g + hi$, the complex conjugate of $x$, represented as a tuple `(g, h)`.  SolutionTo get the complex conjugate of a complex number you change the sign of the imaginary part of the complex number:  $$\overline{x} = a - bi$$<jupyter_code>@exercise
def conjugate(x : Complex) -> Complex:
    
    real = x[0]

    # The sign can be easily flipped with the unary minus operator
    imaginary = - x[1]
    
    return (real, imaginary)<jupyter_output><empty_output><jupyter_text>[Return to task 4 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-4:-Complex-conjugate.)  Exercise 5: Complex division.**Inputs:**1. A complex number $x = a + bi$, represented as a tuple `(a, b)`.2. A complex number $y = c + di \neq 0$, represented as a tuple `(c, d)`.**Goal:** Return the result of the division $\frac{x}{y} = \frac{a + bi}{c + di} = g + hi$, represented as a tuple `(g, h)`.  Solution $$z = \frac{x}{y} = \frac{x}{y} \cdot 1 = \frac{x}{y} \cdot \frac{\overline{y}}{\overline{y}} = \frac{x\overline{y}}{y\overline{y}} = \frac{(a + bi)(c - di)}{(c + di)(c - di)} = \frac{a \cdot c + bi \cdot c - a \cdot di - bi \cdot di}{c \cdot c + di \cdot c - c \cdot di - di \cdot di} = \frac{a \cdot c + b \cdot d + (a \cdot (-d) + c \cdot b)i}{c^2 + d^2}$$> *Python note*:  In Python you can use an operator `**` to raise a number to the given power; $2^3$ can be written as `x = 2 ** 3`.<jupyter_code>@exercise
def complex_div(x : Complex, y : Complex) -> Complex:
    
    (a, b) = x
    (c, d) = y
    
    # We will use the denominator multiple times, so we'll store the value in a separate variable, 
    # to make the code easier to use and less error prone.
    # Here we use ** to raise c and d to the second power.
    denominator = (c ** 2) + (d ** 2)
    
    real = ((a * c) + (b * d)) / denominator
    imaginary = ((a * (-d) ) + (c * b)) / denominator
    
    return (real, imaginary)<jupyter_output><empty_output><jupyter_text>[Return to task 5 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-5:-Complex-division.)  Exercise 6: Modulus.**Input:** A complex number $x = a + bi$, represented as a tuple `(a, b)`.**Goal:** Return the modulus of this number, $|x|$.  SolutionThe modulus of the complex number can be seen as the distance from the origin 0 to the $z$ point in the complex plane. This can be calculated using the Pythagorean theorem: $c^2 = a^2 + b^2$, which means $ c = \sqrt{a^2 + b^2} $. > *Python note*: In the `math` library of Python you can use the `sqrt` function to calculate the square root of a number. > To use `math` library, we'd need to first call `import math`, but this is already done for us in the first cell of the notebook.> After that, to use a function from that library, you can simply use `math.(functionName)`.<jupyter_code>@exercise
def modulus(x : Complex) -> float:
    return math.sqrt(x[0] ** 2 + x[1] ** 2)<jupyter_output><empty_output><jupyter_text>[Return to task 6 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-6:-Modulus.)  Exercise 7: Complex exponents.**Input:** A complex number $x = a + bi$, represented as a tuple `(a, b)`.**Goal:** Return the complex number $e^x = e^{a + bi} = g + hi$, represented as a tuple `(g, h)`.  SolutionTo start, we will rewrite the expression $e^{a + bi}$ as a product of two simpler expressions: $ e^a \cdot\ e^{bi} $.The first part is a real number. The second part can be expressed using the formula $e^{i\theta} = \cos \theta + i\sin \theta$.  Substituting this into our expression gives:$$ e^a(\cos b + i\sin b) = \underset{real}{\underbrace{e^a \cos b}} + \underset{imaginary}{\underbrace{e^a \sin b}}i  $$> *Python note:* Python `math` library offers multiple trigonometric functions, including `cos` and `sin`, and constants, including Euler's constant $e$ (accessed as `math.e`).<jupyter_code>@exercise
def complex_exp(x : Complex) -> Complex:
    
    (a, b) = x
    
    expa = math.e ** a
    
    real = expa * math.cos(b)
    imaginary = expa * math.sin(b)
    
    return (real, imaginary)<jupyter_output><empty_output><jupyter_text>[Return to task 7 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-7:-Complex-exponents.)  Exercise 8*: Complex powers of real numbers.**Inputs:**1. A non-negative real number $r$.2. A complex number $x = a + bi$, represented as a tuple `(a, b)`.**Goal:** Return the complex number $r^x = r^{a + bi} = g + hi$, represented as a tuple `(g, h)`.  SolutionLet's rewrite the expression $r^x$ to use Euler's constant, which will allow us to use an approach similar to the solution to the previous exercise.First, we rewrite $r^x$ into a product of two powers: $$ r^{a+bi} = r^a \cdot r^{bi} $$Given that $r = e^{\ln r} $ ($\ln$ is the natural logarithm), we can rewrite the second part of the product as follows: $$ r^{bi} =  e^{bi\ln r} $$Now, given $e^{i\theta} = \cos \theta + i\sin \theta$, we can rewrite it further as follows: $$ e^{bi\ln r} = \cos( b \cdot \ln r) + i \sin(b \cdot \ln r) $$When substituting this into our original expression, we get:  $$ \underset{real}{\underbrace{r^a \cos(b \cdot \ln r)}} + \underset{imaginary}{\underbrace{r^a \sin(b \cdot \ln r)}} i $$ > *Python note*: To get the natural logarithm in Python, you can use the `log` function from the `math` library.  > You can perform basic conditional operations based on Boolean conditions with the `if` statement. > The syntax can be seen in the code below, you can also add `else` or `elif` statements which are described [here](https://www.w3schools.com/python/python_conditions.asp).<jupyter_code>@exercise
def complex_exp_real(r : float, x : Complex) -> Complex:
    
    # Since ln(r) is only defined for positive numbers, we check for this special case.
    # If r = 0, raising it to any power will give 0.
    # Calling return before the end of the function will not execute the rest of the function.
    if (r == 0):
        return (0,0)
    
    (a, b) = x
    
    # Raise r to the power of a
    ra = r ** a
    
    # Natural logarithm of r
    lnr = math.log(r)
    
    real = ra * math.cos(b * lnr)
    imaginary = ra * math.sin(b * lnr)
    
    return (real, imaginary)<jupyter_output><empty_output><jupyter_text>[Return to task 8 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-8*:-Complex-powers-of-real-numbers.)  Exercise 9: Cartesian to polar conversion.**Input:** A complex number $x = a + bi$, represented as a tuple `(a, b)`.**Goal:** Return the polar representation of $x = re^{i\theta}$, i.e., the distance from origin $r$ and phase $\theta$ as a tuple `(r, θ)`.* $r$ should be non-negative: $r \geq 0$* $\theta$ should be between $-\pi$ and $\pi$: $-\pi < \theta \leq \pi$  SolutionWe need to calculate the $r$ and $\theta$ values as seen in the complex plane. $r$ should be familiar to you already, since it is the modulus of a number (exercise 6):$$ r = \sqrt{a^2 + b^2} $$$\theta$ can be calculated using trigonometry: since we know that the polar and the Cartesian forms of the number represent the same value, we can write$$ re^{i \theta} = a + bi $$Euler's formula allows us to express the left part of the equation as $$ re^{i \theta} = r \cos \theta + i r \sin \theta $$For two complex numbers to be equal, their real and imaginary parts have to be equal. This gives us the following system of equations:$$ \begin{cases} a = r \cos \theta \\ b = r \sin \theta \end{cases} $$To calculate $\theta$, we can divide the second equation by the first one to get$$ \tan \theta = \frac{b}{a} $$$$ \theta = \arctan \left(\frac{b}{a}\right) $$> *Python note:* The `arctan2(b, a)` function from the `math` library returns `atan(b / a)` in radians. It will also handle the special case of $a = 0$ gracefully.<jupyter_code>@exercise
def polar_convert(x : Complex) -> Polar:
    
    (a, b) = x
    
    r = math.sqrt(a**2 + b **2)
    theta = math.atan2(b, a)
    
    return (r, theta)<jupyter_output><empty_output><jupyter_text>[Return to task 9 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-9:-Cartesian-to-polar-conversion.)  Exercise 10: Polar to Cartesian conversion.**Input:** A complex number $x = re^{i\theta}$, represented in polar form as a tuple `(r, θ)`.**Goal:** Return the Cartesian representation of $x = a + bi$, represented as a tuple `(a, b)`. Using the trigonometric functions of the right triangle, you can get the following expressions (which you've obtained algebraically in the previous exercise):$$ \begin{cases} a = r \cos \theta \\ b = r \sin \theta \end{cases} $$<jupyter_code>@exercise
def cartesian_convert(x : Polar) -> Complex:
    
    (r, theta) = x
    
    real = r * math.cos(theta)
    imaginary = r * math.sin(theta)
    
    return (real, imaginary)<jupyter_output><empty_output><jupyter_text>[Return to task 10 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-10:-Polar-to-Cartesian-conversion.)  Exercise 11: Polar multiplication.**Inputs:**1. A complex number $x = r_{1}e^{i\theta_1}$ represented in polar form as a tuple `(r1, θ1)`.2. A complex number $y = r_{2}e^{i\theta_2}$ represented in polar form as a tuple `(r2, θ2)`.**Goal:** Return the result of the multiplication $x \cdot y = z = r_3e^{i\theta_3}$, represented in polar form as a tuple `(r3, θ3)`.* $r_3$ should be non-negative: $r_3 \geq 0$* $\theta_3$ should be between $-\pi$ and $\pi$: $-\pi < \theta_3 \leq \pi$* Try to avoid converting the numbers into Cartesian form.  SolutionMultiplying two complex numbers in polar form can be done efficiently in the following way:$$ z = x \cdot y = r_{1}e^{\theta_1 i} \cdot r_{2}e^{\theta_2 i} = r_{1}r_{2} \cdot e^{(\theta_1 + \theta_2)i} $$  > Here is the longer approach of converting the numbers to the Cartesian from and doing multiplication in it:  > $$ x = r_{1}e^{i\theta_1} = r_{1}(\cos \theta_1 + i \sin \theta_1) $$> $$ y = r_{2}e^{i\theta_2} = r_{2}(\cos \theta_2 + i \sin \theta_2) $$> $$ z = x \cdot y = r_1r_2 \cdot \left( \cos \theta_1 \cos \theta_2 − \sin \theta_1 \sin \theta_2 + i (\sin \theta_1 \cos \theta_2 + \sin \theta_2 \cos \theta_1 ) \right) $$>> We can simplify this using the following trigonometric identities:> * $\cos a \cos b  \mp \sin a \sin b = \cos(a \pm b)$> * $\sin a \cos b  \pm \sin a \cos b = \sin(a \pm b)$>> Finally, this solution gives the same answer as the short solution above:>$$z = r_{1}r_{2}(\cos(\theta_1 + \theta_2) + i \sin(\theta_1 + \theta_2)) = r_{1}r_{2} \cdot e^{(\theta_1 + \theta_2)i} $$<jupyter_code>@exercise
def polar_mult(x : Polar, y : Polar) -> Polar:
    
    (r1, theta1) = x
    (r2, theta2) = y
    
    radius = r1 * r2
    
    angle = theta1 + theta2
    
    # If the calculated angle is larger then pi, we will subtract 2pi
    if (angle > math.pi):
        # Reassign the value for angle
        angle = angle - 2.0 * math.pi
        
    # If the calculated angle is smaller then -pi, we will add 2 pi
    elif (angle <= -math.pi):
        angle = angle + 2.0 * math.pi
    
    return (radius, angle)<jupyter_output><empty_output><jupyter_text>[Return to task 11 of the Complex Arithmetic tutorial.](./ComplexArithmetic.ipynbExercise-11:-Polar-multiplication.)  Exercise 12**: Arbitrary complex exponents.**Inputs:**1. A complex number $x = a + bi$, represented as a tuple `(a, b)`.2. A complex number $y = c + di$, represented as a tuple `(c, d)`.**Goal:** Return the result of raising $x$ to the power of $y$: $x^y = (a + bi)^{c + di} = z = g + hi$, represented as a tuple `(g, h)`.  Solution Let's convert the number $x$ to polar form $x = re^{i\theta}$ and rewrite the complex exponent as follows:$$ x^y = \left( re^{i\theta} \right)^{c + di} = e^{(\ln(r) + i\theta)(c + di)} = $$$$ = e^{\ln(r) \cdot c \, + \, \ln(r) \cdot di \, + \, i\theta \cdot c \, + \, (d\theta)i^2} = e^{\left(\ln(r) \cdot c \, - \, d\theta \right) \, + \, \left(\ln(r) \cdot d \, + \, \theta c\right)i} $$Finally, this needs to be converted back to Cartesian form using Euler's formula:$$ e^{\ln(r) \cdot c - d\theta} \cdot (\cos (\ln(r) \cdot d + \theta c) + i\sin (\ln(r) \cdot d + \theta c)) $$<jupyter_code>@exercise
def complex_exp_arbitrary(x : Complex, y : Complex) -> Complex:
    
    (a, b) = x
    (c, d) = y

    # Convert x to polar form
    r = math.sqrt(a ** 2 + b ** 2)
    theta = math.atan2(b, a)
    
    # Special case for r = 0
    if (r == 0):
        return (0, 0)

    lnr = math.log(r)
    
    exponent = math.exp(lnr * c - d * theta)
    
    real = exponent * (math.cos(lnr * d + theta * c ))
    imaginary = exponent * (math.sin(lnr * d + theta * c))
    
    return (real, imaginary)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14439061983926016, 'fraction_numerical': 0.011890344599801827, 'mean_word_length': 3.449424442811658, 'pattern_counts': {'":': 0, '<': 56, '<?xml version=': 0, '>': 88, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '70006', 'license': 'MIT', 'n_tokens_mistral': 6083, 'n_tokens_neox': 5811, 'n_words': 2430, 'path': 'tutorials/ComplexArithmetic/Workbook_ComplexArithmetic.ipynb', 'repo_name': 'bzu13/QuantumKatas', 'size': '18166'}