MAT3253 Complex Variables

2.1. Complex conjugate🔗

Definition 1.3.1. The complex conjugate of a complex number z = a + bi is defined as z^* = a - bi.

Define the notation conj as the star operator in complex numbers. This is already defined in Mathlib as starRingEnd ℂ.

notation "conj" => (starRingEnd )

Proposition 1.3.2. For complex numbers z\in \mathbb{C}:

(a)

(z^*)^* = z.

(b)

z^* = z if and only if z is real.

(c)

z^* = -z if and only if z is purely imaginary.

/-- Prop. 1.3.2 part (a) Complex conjugate is an involution -/ example {z : } : conj (conj z) = z := z:(starRingEnd ) ((starRingEnd ) z) = z -- Use extensionality on real and imaginary parts z:((starRingEnd ) ((starRingEnd ) z)).re = z.rez:((starRingEnd ) ((starRingEnd ) z)).im = z.im z:((starRingEnd ) ((starRingEnd ) z)).re = z.re -- real parts are equal All goals completed! 🐙 z:((starRingEnd ) ((starRingEnd ) z)).im = z.im -- imaginary parts are equal All goals completed! 🐙 example {z : } : conj (conj z) = z := z:(starRingEnd ) ((starRingEnd ) z) = z -- prove using an existing theorem in Mathlib All goals completed! 🐙 /-- Prop. 1.3.2 part (b) z* = z if and only if imag(z) = 0 -/ example (z : ) : conj z = z z.im = 0 := z:(starRingEnd ) z = z z.im = 0 z:(starRingEnd ) z = z z.im = 0z:z.im = 0 (starRingEnd ) z = z z:(starRingEnd ) z = z z.im = 0 -- conj z = z → z.im = 0 z:h:(starRingEnd ) z = zz.im = 0 -- Two complex numbers are equal -- iff their corresponding components are equal z:h:((starRingEnd ) z).re = z.re ((starRingEnd ) z).im = z.imz.im = 0 -- Break h into real (h_re) and imaginary (h_im) parts z:h_re:((starRingEnd ) z).re = z.reh_im:((starRingEnd ) z).im = z.imz.im = 0 -- Simplify (conj z).im to -z.im z:h_re:((starRingEnd ) z).re = z.reh_im:-z.im = z.imz.im = 0 -- We now have -z.im = z.im. Arithmetic solves this. All goals completed! 🐙 z:z.im = 0 (starRingEnd ) z = z -- z.im = 0 → conj z = z z:h:z.im = 0(starRingEnd ) z = z -- To prove two complex numbers are equal, -- check components and use the hypothesis that Im(z)=0 All goals completed! 🐙 Complex.conj_eq_iff_im {z : } : (starRingEnd ) z = z z.im = 0#check conj_eq_iff_im -- This is the same as the second part of Prop. 1.3.2

Compare with Mathlib's conj_eq_iff_im

/-- Prop. 1.3.2. part (c) z* = -z if and only if real(z) = 0 -/ example (z : ) : conj z = -z z.re = 0 := z:(starRingEnd ) z = -z z.re = 0 z:(starRingEnd ) z = -z z.re = 0z:z.re = 0 (starRingEnd ) z = -z z:(starRingEnd ) z = -z z.re = 0 -- conj z = -z → z.re = 0 z:h:(starRingEnd ) z = -zz.re = 0 -- Two complex numbers are equal -- iff their components are equal z:h:((starRingEnd ) z).re = (-z).re ((starRingEnd ) z).im = (-z).imz.re = 0 -- Break h into real (h_re) and imaginary (h_im) parts z:h_re:((starRingEnd ) z).re = (-z).reh_im:((starRingEnd ) z).im = (-z).imz.re = 0 -- Simplify (conj z).re to -z.re z:h_re:z.re = -z.reh_im:((starRingEnd ) z).im = (-z).imz.re = 0 -- We now have z.re = -z.re All goals completed! 🐙 z:z.re = 0 (starRingEnd ) z = -z -- z.re = 0 → conj z = -z z:h:z.re = 0(starRingEnd ) z = -z -- To prove two complex numbers are equal, -- we check the real and imaginary parts, -- and use the hypothesis that real(z)=0 All goals completed! 🐙

Complex conjugate is an automorphism of the complex field. Addition, multiplication, and inversion are preserved by complex conjugation.

Theorem 1.3.3.

(a)

(z_1 + z_2)^* = z_1^* + z_2^*, for z_1, z_2\in\mathbb{C},

(b)

(z_1 z_2)^* = z_1^* z_2^*,  for z_1, z_2\in\mathbb{C},

(c)

(1/z)^* = 1/(z^*) for z\neq 0.

/-- Theorem 1.3.3 part (a) (z_1 + z_2)^* = z_1^* + z_2^* -/ theorem conj_add_conj (z₁ z₂ : ) : conj z₁ + conj z₂ = conj (z₁ + z₂) := z₁:z₂:(starRingEnd ) z₁ + (starRingEnd ) z₂ = (starRingEnd ) (z₁ + z₂) -- define a, b, c, d z₁:z₂:a: := z₁.re(starRingEnd ) z₁ + (starRingEnd ) z₂ = (starRingEnd ) (z₁ + z₂); z₁:z₂:a: := z₁.reb: := z₁.im(starRingEnd ) z₁ + (starRingEnd ) z₂ = (starRingEnd ) (z₁ + z₂) z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.re(starRingEnd ) z₁ + (starRingEnd ) z₂ = (starRingEnd ) (z₁ + z₂); z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im(starRingEnd ) z₁ + (starRingEnd ) z₂ = (starRingEnd ) (z₁ + z₂) calc -- repalce z₁ and z₂ by their definitions -- (a + bi) and (c + di) conj z₁ + conj z₂ -- Apply conjugate definition: (a - bi) + (c - di) _ = Complex.mk a (-b) + Complex.mk c (-d) := z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im(starRingEnd ) z₁ + (starRingEnd ) z₂ = { re := a, im := -b } + { re := c, im := -d } All goals completed! 🐙 -- Group real and imaginary parts: (a + c) - i(b + d) _ = Complex.mk (a + c) (-(b + d)) := z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im{ re := a, im := -b } + { re := c, im := -d } = { re := a + c, im := -(b + d) } z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im{ re := a, im := -b } + { re := c, im := -d } = { re := a + c, im := -b - d } All goals completed! 🐙 -- By definition, it equals conj (z₁+z₂) _ = conj (z₁ + z₂) := z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im{ re := a + c, im := -(b + d) } = (starRingEnd ) (z₁ + z₂) All goals completed! 🐙 /-- Theorem 1.3.3 part (b) (z_1 z_2)^* = z_1^* z_2^* -/ theorem conj_mul_conj (z₁ z₂ : ) : conj z₁ * conj z₂ = conj (z₁ * z₂) := z₁:z₂:(starRingEnd ) z₁ * (starRingEnd ) z₂ = (starRingEnd ) (z₁ * z₂) -- define a,b,c,d z₁:z₂:a: := z₁.re(starRingEnd ) z₁ * (starRingEnd ) z₂ = (starRingEnd ) (z₁ * z₂); z₁:z₂:a: := z₁.reb: := z₁.im(starRingEnd ) z₁ * (starRingEnd ) z₂ = (starRingEnd ) (z₁ * z₂) z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.re(starRingEnd ) z₁ * (starRingEnd ) z₂ = (starRingEnd ) (z₁ * z₂); z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im(starRingEnd ) z₁ * (starRingEnd ) z₂ = (starRingEnd ) (z₁ * z₂) calc -- Expand z₁ and z₂ conj z₁ * conj z₂ -- Apply conjugate definition _ = Complex.mk a (-b) * Complex.mk c (-d) := z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im(starRingEnd ) z₁ * (starRingEnd ) z₂ = { re := a, im := -b } * { re := c, im := -d } All goals completed! 🐙 -- Perform complex multiplication. Use extensionality -- to split into real and imaginary goals _ = Complex.mk (a * c - b * d) (-(a * d + b * c)) := z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im{ re := a, im := -b } * { re := c, im := -d } = { re := a * c - b * d, im := -(a * d + b * c) } z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im({ re := a, im := -b } * { re := c, im := -d }).re = { re := a * c - b * d, im := -(a * d + b * c) }.rez₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im({ re := a, im := -b } * { re := c, im := -d }).im = { re := a * c - b * d, im := -(a * d + b * c) }.im z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im({ re := a, im := -b } * { re := c, im := -d }).re = { re := a * c - b * d, im := -(a * d + b * c) }.re All goals completed! 🐙 z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im({ re := a, im := -b } * { re := c, im := -d }).im = { re := a * c - b * d, im := -(a * d + b * c) }.im z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im-(a * d) + -(b * c) = -(b * c) + -(a * d) All goals completed! 🐙 -- The rest is true by definition _ = conj (z₁ * z₂) := z₁:z₂:a: := z₁.reb: := z₁.imc: := z₂.red: := z₂.im{ re := a * c - b * d, im := -(a * d + b * c) } = (starRingEnd ) (z₁ * z₂) All goals completed! 🐙 /-- Theorem 1.3.3 part (c) conj z⁻¹ = (conj z)⁻¹ -/ example (z : ) (hz : z 0) : conj z⁻¹ = (conj z)⁻¹ := z:hz:z 0(starRingEnd ) z⁻¹ = ((starRingEnd ) z)⁻¹ z:hz:z 0((starRingEnd ) z)⁻¹ = (starRingEnd ) z⁻¹ z:hz:z 0(starRingEnd ) z * (starRingEnd ) z⁻¹ = 1 -- Now we perform the calculation: z*(1/z) = ... = 1 calc conj z * conj z⁻¹ -- Combine conjugates: (1/z)* z* = ((1/z)z)* _ = conj (z*z⁻¹) := z:hz:z 0(starRingEnd ) z * (starRingEnd ) z⁻¹ = (starRingEnd ) (z * z⁻¹) All goals completed! 🐙 -- Simplify z(1/z) to 1 _ = conj 1 := z:hz:z 0(starRingEnd ) (z * z⁻¹) = (starRingEnd ) 1 All goals completed! 🐙 -- Conjugate of 1 is 1 _ = 1 := z:hz:z 0(starRingEnd ) 1 = 1 All goals completed! 🐙

Existing Mathlib theorems proving complex conjugate is an automorphism of the complex field. We can use these to give a more concise proof of the above theorems.

/-- Prove by applying existing theorems in Mathlib -/ example (z₁ z₂ : ) : conj z₁ + conj z₂ = conj (z₁ + z₂) := z₁:z₂:(starRingEnd ) z₁ + (starRingEnd ) z₂ = (starRingEnd ) (z₁ + z₂) All goals completed! 🐙 example (z₁ z₂ : ) : conj z₁ * conj z₂ = conj (z₁ * z₂) := z₁:z₂:(starRingEnd ) z₁ * (starRingEnd ) z₂ = (starRingEnd ) (z₁ * z₂) All goals completed! 🐙 example (z : ) : conj z⁻¹ = (conj z)⁻¹ := z:(starRingEnd ) z⁻¹ = ((starRingEnd ) z)⁻¹ All goals completed! 🐙

The next proposition justifies that the product of a complex number and its complex conjugate is a real number. (This is the notion of norm in from algebraic number theory.) It also illustrates how to recover the real and imaginary parts of a complex number using the complex conjugate.

Theorem 1.3.4. If z=a+bi for a,b\in\mathbb{R}, then

(a)

z z^* = a^2+b^2.

(b)

a = \frac{z + z^*}{2} and b = \frac{z - z^*}{2i}.

/-- Theorem 1.3.4, Part (a) z z^* = a^2 + b^2 -/ -- a detailed proof by calculation example (z : ) : z * conj z = (z.re)^2 + (z.im)^2 := z:z * (starRingEnd ) z = z.re ^ 2 + z.im ^ 2 z:a: := z.rez * (starRingEnd ) z = z.re ^ 2 + z.im ^ 2; z:a: := z.reb: := z.imz * (starRingEnd ) z = z.re ^ 2 + z.im ^ 2 calc z * conj z -- Apply conjugate: (a + bi)(a - bi) _ = (Complex.mk a b) * (Complex.mk a (-b)) := z:a: := z.reb: := z.imz * (starRingEnd ) z = { re := a, im := b } * { re := a, im := -b } All goals completed! 🐙 -- Def. of multiplication: (aa - b(-b)) + i(a(-b) + ba) _ = Complex.mk (a * a - b * (-b)) (a * (-b) + b * a) := z:a: := z.reb: := z.im{ re := a, im := b } * { re := a, im := -b } = { re := a * a - b * -b, im := a * -b + b * a } All goals completed! 🐙 -- Simplify Algebra: a^2 + b^2 + i(0) _ = Complex.mk (a ^ 2 + b ^ 2) 0 := z:a: := z.reb: := z.im{ re := a * a - b * -b, im := a * -b + b * a } = { re := a ^ 2 + b ^ 2, im := 0 } z:a: := z.reb: := z.ima * a - b * -b = a ^ 2 + b ^ 2z:a: := z.reb: := z.ima * -b + b * a = 0 z:a: := z.reb: := z.ima * a - b * -b = a ^ 2 + b ^ 2 All goals completed! 🐙 -- Real part: a*a - (-b^2) = a^2 + b^2 z:a: := z.reb: := z.ima * -b + b * a = 0 All goals completed! 🐙 -- Imaginary part: -ab + ab = 0 _ = (a ^ 2 + b ^ 2 : ) := z:a: := z.reb: := z.im{ re := a ^ 2 + b ^ 2, im := 0 } = a ^ 2 + b ^ 2 z:a: := z.reb: := z.im{ re := a ^ 2 + b ^ 2, im := 0 }.re = (a ^ 2 + b ^ 2).rez:a: := z.reb: := z.im{ re := a ^ 2 + b ^ 2, im := 0 }.im = (a ^ 2 + b ^ 2).im z:a: := z.reb: := z.im{ re := a ^ 2 + b ^ 2, im := 0 }.re = (a ^ 2 + b ^ 2).re z:a: := z.reb: := z.ima ^ 2 + b ^ 2 = (a ^ 2).re + (b ^ 2).re z:a: := z.reb: := z.ima ^ 2 + b ^ 2 = (↑(a ^ 2)).re + (b ^ 2).re z:a: := z.reb: := z.ima ^ 2 + b ^ 2 = (↑(a ^ 2)).re + (↑(b ^ 2)).re repeat All goals completed! 🐙 z:a: := z.reb: := z.im{ re := a ^ 2 + b ^ 2, im := 0 }.im = (a ^ 2 + b ^ 2).im z:a: := z.reb: := z.im0 = (a ^ 2).im + (b ^ 2).im z:a: := z.reb: := z.im0 = (↑(a ^ 2)).im + (b ^ 2).im z:a: := z.reb: := z.im0 = (↑(a ^ 2)).im + (↑(b ^ 2)).im repeat z:a: := z.reb: := z.im0 = 0 + 0 All goals completed! 🐙

We can also prove the same result using the existing theorem mul_conj in Mathlib.

Complex.mul_conj (z : ) : z * (starRingEnd ) z = (normSq z)#check mul_conj -- This states that z * conj z = normSq z, -- where normSq z = z.re^2 + z.im^2 example (z : ) : z * conj z = (z.re)^2 + (z.im)^2 := z:z * (starRingEnd ) z = z.re ^ 2 + z.im ^ 2 -- proof using `mul_conj` z:(normSq z) = z.re ^ 2 + z.im ^ 2 z:({ toFun := fun z => z.re * z.re + z.im * z.im, map_zero' := normSq._proof_1, map_one' := normSq._proof_2, map_mul' := } z) = z.re ^ 2 + z.im ^ 2 ; z:z.re * z.re + z.im * z.im = z.re ^ 2 + z.im ^ 2 ; All goals completed! 🐙 /-- Theorem 1.3.4, Part (b) z.re = (z + conj z) / 2 -/ example (z : ) : z.re = (z + conj z) / 2 := z:z.re = (z + (starRingEnd ) z) / 2 -- detailed proof by calculation, -- using the definition of conjugate z:a: := z.rez.re = (z + (starRingEnd ) z) / 2 z:a: := z.reb: := z.imz.re = (z + (starRingEnd ) z) / 2 z:a: := z.reb: := z.im(z + (starRingEnd ) z) / 2 = z.re calc (z + conj z) / 2 -- Expand z to Complex.mk a b _ = (Complex.mk a b + conj (Complex.mk a b)) / 2 := z:a: := z.reb: := z.im(z + (starRingEnd ) z) / 2 = ({ re := a, im := b } + (starRingEnd ) { re := a, im := b }) / 2 All goals completed! 🐙 -- Apply definition of conjugate _ = (Complex.mk a b + Complex.mk a (-b)) / 2 := z:a: := z.reb: := z.im({ re := a, im := b } + (starRingEnd ) { re := a, im := b }) / 2 = ({ re := a, im := b } + { re := a, im := -b }) / 2 All goals completed! 🐙 -- Perform the addition: (a+a) + i(b-b) _ = (Complex.mk (a + a) (b + -b)) / 2 := z:a: := z.reb: := z.im({ re := a, im := b } + { re := a, im := -b }) / 2 = { re := a + a, im := b + -b } / 2 All goals completed! 🐙 -- Simplify the numerator: 2a + i0 _ = (Complex.mk (2 * a) 0) / 2 := z:a: := z.reb: := z.im{ re := a + a, im := b + -b } / 2 = { re := 2 * a, im := 0 } / 2 z:a: := z.reb: := z.ima + a = 2 * az:a: := z.reb: := z.imb + -b = 0 -- Focus inside the 'mk' z:a: := z.reb: := z.ima + a = 2 * a All goals completed! 🐙 -- Real part: a + a = 2 * a z:a: := z.reb: := z.imb + -b = 0 All goals completed! 🐙 -- Imaginary part: b + -b = 0 -- Convert 'mk (2a) 0' to real number '(2a : ℂ)' _ = (2 * a : ) / 2 := z:a: := z.reb: := z.im{ re := 2 * a, im := 0 } / 2 = 2 * a / 2 z:a: := z.reb: := z.im({ re := 2 * a, im := 0 } / 2).re = (2 * a / 2).rez:a: := z.reb: := z.im({ re := 2 * a, im := 0 } / 2).im = (2 * a / 2).im z:a: := z.reb: := z.im({ re := 2 * a, im := 0 } / 2).re = (2 * a / 2).re All goals completed! 🐙 z:a: := z.reb: := z.im({ re := 2 * a, im := 0 } / 2).im = (2 * a / 2).im All goals completed! 🐙 _ = a := z:a: := z.reb: := z.im2 * a / 2 = a All goals completed! 🐙

An alternate proof using by matching the real and imaginary parts

example (z : ) : z.re = (z + conj z) / 2 := z:z.re = (z + (starRingEnd ) z) / 2 -- prove by considering real and imaginary parts z:(↑z.re).re = ((z + (starRingEnd ) z) / 2).rez:(↑z.re).im = ((z + (starRingEnd ) z) / 2).im -- Goal 1: Real parts match -- LHS: z.re -- RHS: ((z + conj z) / 2).re z:(↑z.re).re = ((z + (starRingEnd ) z) / 2).re All goals completed! 🐙 -- Goal 2: Imaginary parts match -- LHS: 0 (since z.re is real) -- RHS: ((z + conj z) / 2).im z:(↑z.re).im = ((z + (starRingEnd ) z) / 2).im All goals completed! 🐙 /-- Theorem 1.3.4, Part (b) z.im = (z - conj z) / (2i) -/ example (z : ) : z.im = (z - conj z) / (2*I) := z:z.im = (z - (starRingEnd ) z) / (2 * I) z:(z - (starRingEnd ) z) / (2 * I) = z.im -- Multiply both sides by 2*I to avoid fraction headaches z:z - (starRingEnd ) z = z.im * (2 * I)z:2 * I 0 -- Use Extensionality to check Real/Imaginary parts z:z - (starRingEnd ) z = z.im * (2 * I) z:(z - (starRingEnd ) z).re = (z.im * (2 * I)).rez:(z - (starRingEnd ) z).im = (z.im * (2 * I)).im z:(z - (starRingEnd ) z).re = (z.im * (2 * I)).re All goals completed! 🐙 -- Real parts match (0 = 0) z:(z - (starRingEnd ) z).im = (z.im * (2 * I)).im z:z.im + z.im = z.im * 2 All goals completed! 🐙 -- Imaginary parts match (2b = 2b) -- Prove denominator non-zero z:2 * I 0 All goals completed! 🐙

We can also prove the same result using the existing theorems from Mathlib.

example (z : ) : z.re = (z + conj z) / 2 := z:z.re = (z + (starRingEnd ) z) / 2 -- prove using and existing theorem in Mathlib All goals completed! 🐙 example (z : ) : z.im = (z - conj z) / (2*I) := z:z.im = (z - (starRingEnd ) z) / (2 * I) -- prove using and existing theorem in Mathlib All goals completed! 🐙