4
votes

I am trying to automatically prove/disprove some theorems in geometry, related to squares, such as "For every 3 collections of 7 disjoint squares, it is possible to select 1 square from each collection such that the 3 representatives are interior disjoint?".

I tried to use OpenGeoProver and came up with the following description of a square:

    <!-- define a 'free' point - the south-western corner of the square: -->
    <pfree       label="square1southwest"/>

    <!-- define a line that is parallel to the x axis and goes throught that point - the southern boundary: -->
    <lparallel   label="square1south" point="square1southwest" baseline="xaxis" />

    <!-- define a random point on the southern line, which will be the south-eastern corner: -->
    <prandline   label="square1southeast" line="square1south" />

    <!-- rotate the south-eastern corner 90 degrees around the south-western corner, to create the north-western corner: -->
    <protated    label="square1northwest" origpt="square1southeast" center="square1southwest" angmeasure="-90"/>

    <!-- translate the north-western corner by the vector between the two southern corners, to create the north-eastern corner of the square: -->
    <ptranslated label="square1northeast" origpt="square1northwest" point1="square1southwest" point2="square1southeast"/>

This is where I am stuck: how to define the simple statement "square A and square B intersect"?

How can this problem be approached in Z3?

2
I think this is off-topic on SE, because it is a “shopping recommendation”. - Palec
This question appears to be off-topic because it is about mathematics - Rowland Shaw
I " describe the problem and what has been done so far to solve it". Can it be reopened? - Erel Segal-Halevi

2 Answers

2
votes

I have tried to disprove your theorem using MiniZinc:

int: noOfCollections = 3;
int: noOfDisjoints = 7;
int: noOfSquares = noOfCollections * noOfDisjoints;
set of int: Squares = 1..noOfSquares;
int: maxDim = 10000;  %  somewhat arbitrary limit!
int: maxLeft = maxDim;
int: maxRight = maxDim;
int: maxTop = maxDim;
int: maxBottom = maxDim;
int: maxHeight = maxBottom - 1;
int: maxWidth = maxRight - 1;

array[Squares] of var 1..maxLeft: Left;
array[Squares] of var 1..maxTop: Top;
array[Squares] of var 1..maxHeight: Height;
array[Squares] of var 1..maxWidth: Width;
array[Squares] of var bool: Representative;
array[Squares] of 1..noOfCollections: 
      Collection = [1 + (s mod noOfCollections) | s in Squares];

%  Squares must fit in the overall frame
constraint
    forall(s in Squares)(
        (Left[s] + Width[s] - 1 <= maxRight) /\
        (Top[s] + Height[s] - 1 <= maxBottom)
    );

predicate disjoint(var int: s1, var int: s2) =
    (Left[s1] + Width[s1] - 1 < Left[s2]) \/
    (Left[s2] + Width[s2] - 1 < Left[s1]) \/
    (Top[s1] + Height[s1] - 1 < Top[s2]) \/
    (Top[s2] + Height[s2] - 1 < Top[s1]);

%  Squares in a collection must be disjoint
constraint
    forall(s1 in Squares, s2 in Squares 
           where (s1 > s2) /\ (Collection[s1] == Collection[s2]))(
        disjoint(s1, s2)
    );

%   Exactly one Representative per Collection
constraint
    1 == sum(c in 1..noOfCollections, s in Squares 
             where c == 1 + (s mod noOfCollections))
           (bool2int(Representative[s]));

%   Is it possible to select 1 square from each collection such 
%   that the 3 representatives are interior disjoint?
constraint
    forall(s1 in Squares, s2 in Squares, s3 in Squares
           where (Collection[s1] == 1) /\
                 (Collection[s2] == 2) /\
                 (Collection[s3] == 3))(
        disjoint(s1, s2) /\
        disjoint(s1, s3) /\
        disjoint(s2, s3) /\
        Representative[s1] /\
        Representative[s2] /\
        Representative[s3]
    );

solve satisfy;

MiniZinc comes up with "UNSAT" after 45ms.

0
votes

am I the only one that see this as algorithmic problem ?

  • yes the title and start of question is a bit confusing but
  • as I understand the question is (or should be) how to achieve prove of geometry statement.
  • some re-edit/re-tag will be good for it I think

I would do it like this (will not use any language or framework because it is not relevant):

1.dataset definition

  • sum/size/count for geometric entities used for theorem (points,lines,rects,...)
  • sum of all conditions/constrains for input data

2.dataset generation

  • can be random + throw away invalid entities (which do not match 1)
  • or you can generate all valid possibilities within some accuracy for position/size...
  • but that is really nasty because of time and space complexity

  • this is the hard part

  • you must choose between performance/relevance
  • I am afraid that this task cannot be automated with satisfactory performance
  • instead you have to write some generation script for each theorem

3.theorem statement

  • this is the easiest part
  • just check if the theorem is valid for current dataset
  • if not theorem is not valid
  • if the dataset is random use big enough count of tests ...

You got problem with statement "square A and square B intersect"

  • I assume you stated it after dataset is generated
  • this is just another condition for bullet 1
  • so your dataset generator must generate intersecting A,B squares
  • A - generate as is
  • put B - start point inside A (randomly or in the middle or whatever)

  • another option is select only intersecting squares from dataset

  • go through all i=1..N squares (A)
  • then go through i+1..N squares and if the two are intersecting then it is your B square

hope I am not too far away from what you wanted to do ...