views:

256

answers:

9

I'd like to write a program that lets users draw points, lines, and circles as though with a straightedge and compass. Then I want to be able to answer the question, "are these three points collinear?" To answer correctly, I need to avoid rounding error when calculating the points.

Is this possible? How can I represent the points in memory?

(I looked into some unusual numeric libraries, but I didn't find anything that claimed to offer both exact arithmetic and exact comparisons that are guaranteed to terminate.)

A: 

If the grid axes are integer valued then the answer is fairly straight forward, the points are either exactly colinear or they are not.

Typically however, one works with real numbers (well, floating points) and then draws the rounded values on the screen which does exist in integer space. In this case you have no choice but to pick a tolerance and use it to determine colinearity. Keep it small and the users will never know the difference.

Dr. Tim
They'll know the difference if they ask the question "are these points co-linear", of three points which they can prove using geometry are not co-linear, and the program answers "yes, sure".
Steve Jessop
(...or if the UI lets them just "zoom in" and see that the points don't line up!)
Jason Orendorff
Having written a fair amount of code that displays graphs on grids (pen plotters, screens etc) I think that the point is being missed. You must work with an internal floating point representation that is then displayed at the required resolution. Rounding is never an issue because the precision of the internal model will almost always be much greater than that of the display except in the case of very high zoom levels. Most of the suggestions here will lead to a lot of development time with no payoff.
Dr. Tim
The questioner says he needs a program to do precise geometry. I think it's rather unfair to tell him that he's missing the point, and really he only needs a program to do approximate geometry. I used some software like this when I was 16 or so, can't remember what it was called, designed to help teach geometry. It didn't tell users "these points are co-linear" just because they lay near a straight line at the current display resolution. It only said things were co-linear if it knew by construction that they really are.
Steve Jessop
@Dr. Tim: I appreciate your trying to save me a lot of wasted time, but this is a side project, and Correctness is a large part of the charm of the idea. I expect to spend a month or two reading and learning, then a couple days hacking. It'll be fun.
Jason Orendorff
+8  A: 

I think the only way this would be possible is if you used a symbolic representation, as opposed to trying to represent coordinate values directly -- so you would have to avoid trying to coerce values like sqrt(2) into some numerical format. You will be dealing with irrational numbers that are not finitely representable in binary, decimal, or any other positional notation.

Jim Lewis
Very much this.
Stephen Canon
+1, but I had concluded as much on my own.
Jason Orendorff
A: 

I would recommend no to try to make it perfectly exact.
The first reason for this is what you are questioning here, the rounding error and all that stuff that comes with floating point calculations.
The second one is that you have to round your input as the mouse and screen work with integers. So, initially all user input would be integers, and your output would be integers. Beside, From a usability point of view, its easier to click in the neighborhood of another point (in a line for example) and that the interface consider you are clicking in the point itself.

Limo Wan Kenobi
The idea is for the UI to "snap to" interesting points, exactly as you suggest. Since those points will include the intersection of previously drawn circles and lines, they can have irrational coordinates.
Jason Orendorff
Of course they will have "irrational" coordinates, but (unless you work with a symbolic representation) in the computer those numbers will always be rational. My suggestion was no to fight with the rounding errors but to use them. Even if your UI accept defining points by writing their coordinates you'll never have a "real" irrational number. So, define certain threshold from which you'll round and stop fighting the computer and floating point architecture. They're a [leaky abstraction](http://www.joelonsoftware.com/articles/LeakyAbstractions.html)
Limo Wan Kenobi
+5  A: 

To expand on Jim Lewis's answer slightly, if you want to operate on points that are constructible from the integers with exact arithmetic, you will need to be able to operate on representations of the form:

a + b sqrt(c)

where a, b, and c are either rational numbers, or representations in the form given above. Wikipedia has a pretty decent article on the subject of what points are constructible.

Answering the question of exact equality (as necessary to establish colinearity) with such representations is a rather tricky problem.

Stephen Canon
Thanks Jim, was about to do that edit myself =)
Stephen Canon
"...a rather tricky problem" This was my conclusion as well. I thought of trying to define some kind of canonical form for numbers represented this way, but I don't know if that is possible. Denesting radicals is apparently considered hard.
Jason Orendorff
It's even more tricky than what you say. According to the Wikipedia article, that form wouldn't be enough. Variables a, b, and c can themselves be of the form a' + b' sqrt(c') (and so on down.)
Chip Uni
@Chip: That's exactly what I said, perhaps not clearly enough: "where a, b, and c are either rational numbers, *or representations in the form given above*"
Stephen Canon
+5  A: 

If you try to compare co-ordinates for your points, then you have a problem. Leaving aside co-linearity for a moment, how about just working out whether two points are the same or not?

Supposing that one has given co-ordinates, and the other is a compass-straightedge construction starting from certain other co-ordinates, you want to determine with certainty whether they're the same point or not. Either way is a theorem of Euclidean geometry, it's not something you can just measure. You can prove they aren't the same by spotting some difference in their co-ordinates (for example by computing decimal places of each until you encounter a difference). But in general to prove they are the same cannot be done by approximate methods. Compute as many decimal places as you like of some expansions of 1/sqrt(2) and sqrt(2)/2, and you can prove they're very close together but you won't ever prove they're equal. That takes algebra (or geometry).

Similarly, to show that three points are co-linear you will need theorem-proving software. Represent the points A, B, C by their constructions, and attempt to prove the theorem "A, B and C are colinear". This is very hard - your program will prove some theorems but not others. Much easier is to ask the user for a proof that they are co-linear, and then verify (or refute) that proof, but that's probably not what you want.

Steve Jessop
"This is very hard - your program will prove some theorems but not others." Are you saying that this subset of plane geometry isn't decidable? If so, and you're right, then that's a complete answer to my question.
Jason Orendorff
I mean, not the answer I was hoping for, obviously, but I'd be in no position to complain. :)
Jason Orendorff
I'm not sure whether or not it's incomplete in Goedel's sense. But under practical limits of computing resource and programmer ingenuity, I don't think that even Euclid's elements is a knockover, let alone the whole of geometry.
Steve Jessop
http://en.wikipedia.org/wiki/Tarski%27s_axioms "This fact allowed Tarski to prove that Euclidean geometry is decidable: there exists an algorithm which can determine the truth or falsity of any sentence." So my question is reduced to "What is that algorithm?"
Jason Orendorff
Excellent news. It'd be interesting to know (a) whether Tarski actually produced an algorithm or just proved its existence; (b) whether the proof of its existence is constructive, or by the impossibility of it not existing; (c) whether the algorithm is feasibly computable in hardware...
Steve Jessop
This was the most insightful answer, I thought, so you get the check. :)
Jason Orendorff
For any given 3 points A, B, and C, you should not need a theorem prover to prove collinearity assuming your number representation uniquely represents every representable number, which a proper one should. Now, if you want to prove collinearity for 3 points defined in some way, then you will need a theorem prover. However, plane geometry is invariant to rotations, translations, and scaling, so you should be able to pick particular instances of constructions and general cases down to a finite discrete set, which you can verify using symbolic methods without a theorem prover.
Victor Liu
"if you want to prove collinearity for 3 points defined in some way, then you will need a theorem prover". He does. See for instance his comment about the UI snapping to points of interest, such as the intersection of a line and a circle.
Steve Jessop
A: 

You seem to be asking, in effect, "Can the normal mathematics (integer or floating point) used by computers be made to represent real numbers perfectly, with no rounding errors?" And, of course, the answer to that is "No." If you want theoretical correctness, then you will be stuck with the much harder problem of symbolic manipulation and coding up the equivalent of the inferences that are done in geometry. (In short, I'm agreeing with Steve Jessop, above.)

Joe Mabel
That's not what I'm asking.
Jason Orendorff
+2  A: 

In general, constructable points may have an arbitrarily complex symbolic form, so you must use a symbolic representation to work them exactly. As Stephen Canon noted above, you often need numbers of the form a+b*sqrt(c), where a and b are rational and c is an integer. All numbers of this form form a closed set under arithmetic operations. I have written some C++ classes (see rational_radical1.h) to work with these numbers if that is all you need.

It is also possible to construct numbers which are sums of any number of terms of rational multiples of radicals. When dealing with more than a single radicand, the numbers are no longer closed under multiplication and division, so you will need to store them as variable length rational coefficient arrays. The time complexity of operations will then be quadratic in the number of terms.

To go even further, you can construct the square root of any given number, so you could potentially have nested square roots. Here, the representations must be tree-like structures to deal with root hierarchy. While difficult to implement, there is nothing in principle preventing you from working with these representations. I'm not sure just what additional numbers can be constructed, but beyond a certain point, your symbolic representation will be expressive enough to handle very large classes of numbers.

Addendum

Found this Google Books link.

Victor Liu
Victor, this was a good answer and you got a +1 from me, but "numbers of the form a+b*sqrt(c), where a and b are rational and c is an integer" are not sufficient for this. For example, the sum of two such numbers often is not of that form. (If I were to try it with rational_radical1, it could abort or silently give the wrong answer!)
Jason Orendorff
+6  A: 

Yes.

I highly recommend Introduction to constructions, which is a good basic guide.

Basically you need to be able to compute with constructible numbers - numbers that are either rational, or of the form a + b sqrt(c) where a,b,c were previously created (see page 6 on that PDF). This could be done with algebraic data type (e.g. data C = Rational Integer Integer | Root C C C in Haskell, where Root a b c = a + b sqrt(c)). However, I don't know how to perform tests with that representation.

Two possible approaches are:

  • Constructible numbers are a subset of algebraic numbers, so you can use algebraic numbers. All algebraic numbers can be represented using polynomials of whose they are roots. The operations are computable, so if you represent a number a with polynomial p and b with polynomial q (p(a) = q(b) = 0), then it is possible to find a polynomial r such that r(a+b) = 0. This is done in some CASes like Mathematica, example. See also: Computional algebraic number theory - chapter 4

  • Use Tarski's test and represent numbers. It is slow (doubly exponential or so), but works :) Example: to represent sqrt(2), use the formula x^2 - 2 && x > 0. You can write equations for lines there, check if points are colinear etc. See A suite of logic programs, including Tarski's test

If you turn to computable numbers, then equality, colinearity etc. get undecidable.

sdcvvc
+1! Best answer yet, IMHO....
Jim Lewis
Totally. I wish I could check multiple answers. This was totally unexpected.
Jason Orendorff
That link to "a suite of logic programs" is particularly amazing.
Jason Orendorff
A: 

Some thoughts in the hope that they might help.

The sort of constructions you're talking about will require multiplication and division, which means that to preserve exactness you'll have to use rational numbers, which are generally easy to implement on top of a suitable sort of big integer (i.e., of unbounded magnitude). (Common Lisp has these built-in, and there have to be other languages.)

Now, you need to represent square roots of arbitrary numbers, and these have to be mixed in.

Therefore, a number is one of: a rational number, a rational number multiplied by a square root of a rational number (or, alternately, just the square root of a rational), or a sum of numbers. In order to prove anything, you're going to have to get these numbers into some sort of canonical form, which for all I can figure offhand may be annoying and computationally expensive.

This of course means that the users will be restricted to rational points and cannot use arbitrary rotations, but that's probably not important.

David Thornley