Teaching a reasoner a kind of number it has never heard of.
complex.py · output · proof · check · try it in the playground
A complex number is a pair of ordinary numbers, a real part and an
imaginary part, written here as complex(3, 4) for 3 + 4i. The special
number i has the property that i × i = −1. Engineers use these for waves,
circuits and rotations.
peye has no complex numbers built in. Can we define them with a few rules, and get answers that are both right and explained?
How to add and multiply pairs, as ordinary rules:
implied_by(complex_add(complex(A, B), complex(C, D), complex(R, I)), is_(R, A + C) & is_(I, B + D))
implied_by(
complex_mul(complex(A, B), complex(C, D), complex(R, I)),
is_(R, A * C - B * D)
& is_(I, A * D + B * C),
)
fact(point('z', complex(3, 4)))
fact(point('w', complex(1, 2)))
implies(point('z', Z) & point('w', W) & complex_add(Z, W, Sum), sum(Sum))
implies(point('z', Z) & point('w', W) & complex_mul(Z, W, Product), product(Product))
implies(complex_mul(complex(0, 1), complex(0, 1), Square), unit_square(Square))
# …
Division, powers, polar form, logarithms, sine and cosine follow the same way.
A few of its 23 answers:
sum(complex(4, 6))
product(complex(-5, 10))
quotient(complex(3.0, 4.0))
ratio(complex(2.2, -0.4))
unit_square(complex(-1, 0))
integer_power(8, complex(16, 0))
power('self_power', complex(0.20787957635076193, 0.0))
sine(complex(1.9999999999999998, 1.0605752387249067e-16))
…and 15 more.
unit_square) is derived from the multiplication rule,
not assumed./
always gives decimals, so it reads complex(3.0, 4.0); dividing z by w
does not divide evenly, so it becomes 2.2 and −0.4.Take product(complex(-5, 10)):
Every one of the 23 answers has a trail like this.
The checker reads the proof against the program:
Verdict: checked. All 215 steps verified, nothing taken on trust.
python -m peye examples/complex.py
python -m peye --goal "complex_power(complex(1, 1), 16, Result)" examples/complex.py
python -m peye --goal "complex_div(complex(1, 0), complex(0, 1), Inverse)" examples/complex.py
These give complex(256, 0) and complex(0.0, -1.0) (so 1 / i = −i).
Change fact(turns(8)) to fact(turns(4)): the answer becomes
integer_power(4, complex(-4, 0)), half-way round.
A new kind of number is just a handful of rules. Because every calculation is recorded and redone by the checker, you can see exactly where results stay exact and where decimals creep in.