My father introduced me to a famous algebra problem involving an electrical delta resistance. A delta configuration has three terminals, A, B and C and three resistors, x, y and z. x goes between B and C, y between C and A, z between A and B.
The effective resistance between A and B is Z = 1/(1/z + 1/(x + y)).
The effective resistance between B and C is X = 1/(1/x + 1/(y + z)).
The effective resistance between C and A is Y = 1/(1/y + 1/(z + x)).
These effective resistances are the easy ones to measure as it is forbidden to break the connections for the purposes of measuring. When I learned of the algebra problem of solving for x, y and z in terms of X, Y and Z, I indeed failed to find an algebraic solution. Some years later I did find it but just now I have misplaced that solution. A clue is to exploit symmetry. See solution below snatched from the web.
My father told me that a technician would not make these measurements but would do it the easy way. I thought about that for a while and could not figure out an easy way. When he told me it was indeed easy. Can you see how to learn x, y and z using only elementary cheap stuff, and, of course, what ever it takes to measure resistance? This would not have occurred to me! You need only a bit of high school electricity theory and algebra. See the answer.
; Hypothetical resistances on sides of delta (define x 3.23) (define y 2.15) (define z 4.32) ; Measured resistances (define Z (/ (+ (/ z) (/ (+ x y))))) (define X (/ (+ (/ x) (/ (+ y z))))) (define Y (/ (+ (/ y) (/ (+ z x))))) ; Equivalent Y resistances (define R1 (* 0.5 (+ (- X) Y Z))) ; => (3.23 2.15 4.32) (define R2 (* 0.5 (+ X (- Y) Z))) (define R3 (* 0.5 (+ X Y (- Z)))) ; Deduced original resistances. (define RA (+ (/ (* R2 R3) R1) R3 R2)) (define RB (+ (/ (* R3 R1) R2) R1 R3)) (define RC (+ (/ (* R1 R2) R3) R2 R1)) (list RA RB RC)thanks
We have a peculiar pattern above that I want to capture in code.
We have three cases of three similar functions, each of three variables.
In each case the 6 permutations of input yields the same permutation in output.
Each case has the group of 6 as its symmetry group.
Wanted a function that takes a function of three reals and returns a function of a list of three reals returning a list of three reals.
The above presumes Scheme.
For OCaml substitute ‘triple’ for ‘list’.
The OCaml signature would be
(a function of three reals) -> (a function of a list of three reals returning a list of three reals)
type r = float;;
(r * r * r -> r) -> (r * r * r -> r * r * r)
let sp f (a, b, c) = f (a, b, c), f(b, c, a), f(c, b, a);;
Indeed for the above OCaml understands:
val sp : ('a * 'a * 'a -> 'b) -> 'a * 'a * 'a -> 'b * 'b * 'b = <fun>
which is slightly more general than we want—it will do.
We can now write our transform irredundantly as:
let r x = 1. /. x;;
let del = sp (fun (a, b, c) -> r ((r a) +. (r (b +. c))));;
and indeed del (3.23, 2.15, 4.32);; => (2.15444…, 1.67345…, 2.39604…)
just as (list X Y Z) yields (2.15444… 1.67345… 2.39604…) in the scheme program.
The inverse of del is
let l1 = sp (fun (ra, rb, rc) -> rb *. rc /. ra +. rb +. rc);;
let l2 = sp (fun (x, y, z) -> (y +. z -. x) /. 2.);;
let led x = l1 (l2 x);;
led (del (3.23, 2.15, 4.32));; => (3.23, 2.14999…, 4.32)
Alternatively we define function composition:
let comp f g = fun x -> g (f x);;
let led = comp (sp (fun (x, y, z) -> (y +. z -. x) /. 2.)) (sp (fun (ra, rb, rc) -> rb *. rc /. ra +. rb +. rc));;
Alltogether:
let sp f (a, b, c) = f(a, b, c), f(b, c, a), f(c, b, a) and r x = 1. /. x in let del = sp (fun (a, b, c) -> r ((r a) +. (r (b +. c)))) and comp f g x = g (f x) in let led = comp (sp (fun (x, y, z) -> (y +. z -. x) /. 2.)) (sp (fun (a, b, c) -> b *. c /. a +. b +. c)) in led (del (3.1, 4.3, 5.2));; => (3.10…, 4.3, 5.20…)We transcribe this to Scheme for comparison:
(define ((sp f) l) (apply (lambda (a b c) (list (f (list a b c)) (f (list b c a)) (f (list c a b)))) l)) (define (d l) (apply (lambda (a b c) (/ (+ (/ a) (/ (+ b c))))) l)) (define (comp f g) (lambda (x) (g (f x)))) (define led (comp (sp (lambda (l) (apply (lambda (x y z) (/ (+ y z (- x)) 2)) l))) (sp (lambda (l) (apply (lambda (a b c) (+ (/ (* b c) a) b c)) l))))) (led ((sp d) '(2 4 3))) ; => (2 4 3)OCaml’s slick syntax wins here.