eyedia

Complex numbers

Teaching a reasoner a kind of number it has never heard of.

complex.pl · output · proof · check · try it in the playground


The question

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.

Eyedia has no complex numbers built in. Can we define them with a few rules, and get answers that are both right and explained?


What we tell Eyedia

How to add and multiply pairs, as ordinary rules:

complex_add(complex(A, B), complex(C, D), complex(R, I)) :- R is A+C, I is B+D.
complex_mul(complex(A, B), complex(C, D), complex(R, I)) :- R is A*C-B*D, I is A*D+B*C.

point(z, complex(3, 4)).
point(w, complex(1, 2)).

sum(Sum) :+ point(z, Z), point(w, W), complex_add(Z, W, Sum).
product(Product) :+ point(z, Z), point(w, W), complex_mul(Z, W, Product).
unit_square(Square) :+ complex_mul(complex(0, 1), complex(0, 1), Square).
% …

Division, powers, polar form, logarithms, sine and cosine follow the same way.


What Eyedia concludes

A few of its 23 answers:

sum(complex(4, 6)).
product(complex(-5, 10)).
quotient(complex(3, 4)).
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.


Reading the answers


Why: the proof in plain words

Take product(complex(-5, 10)):

  1. z is 3 + 4i and w is 1 + 2i — facts we gave.
  2. The multiplication rule, with A = 3, B = 4, C = 1, D = 2, says the result is (3·1 − 4·2) + (3·2 + 4·1)i.
  3. 3·1 − 4·2 = −5 and 3·2 + 4·1 = 10 — each a calculation, recorded.

Every one of the 23 answers has a trail like this.


Checked, not just claimed

The checker reads the proof against the program:

Verdict: checked. All 215 steps verified, nothing taken on trust.


Try it

node bin/eyedia.js examples/complex.pl
node bin/eyedia.js --goal "complex_power(complex(1, 1), 16, Result)" examples/complex.pl
node bin/eyedia.js --goal "complex_div(complex(1, 0), complex(0, 1), Inverse)" examples/complex.pl

These give complex(256, 0) and complex(0, -1) (so 1 / i = −i). Change turns(8). to turns(4).: the answer becomes integer_power(4, complex(-4, 0)), half-way round.


Takeaway

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.