Question related to Desargues' Theorem

255 Views Asked by At

The diagram below is one way of drawing two triangles ($\Delta PQR,\ \Delta P'Q'R'$) perspective from a point ($O$), with pairs of corresponding sides meeting at $D, E, F$ as in Desargues' Theorem ("If two triangles are perspective from a point, and if their pairs of corresponding sides meet, then the three points of intersection are collinear").

I am working a problem related to counting the number of mutually inscribed pentagons (the vertices of each lie on the sides of the other) that can be listed using the diagram. For example two pairs of such pentagons are $DFP'OR, \ EPQQ'R'$ and $RPP'Q'D, \ EFQOR'.$

The count of such pairs is 6, but I am having trouble proving it. My initial thought was that since any initial choice of 5 vertices yielding an end-to-end arrangement of segments completely determines the dual set of vertices (using the only arrangement of the "free" vertex on each segment from the initial choice that yields an end-to-end arrangement of the segments in the dual), you only have to count the number of different initial choices. But I am having trouble doing this. Please help!

enter image description here

1

There are 1 best solutions below

0
On BEST ANSWER

One way is complete enumeration: have the computer check all possible combinations. I've written a program to do this, and after your comment below, I think I even got it right. Its output now looks like this:

\begin{align*} 123,124,145,345,235 &\quad 135,134,234,245,125 & PQDR'P' &\quad EROQ'F \\ 123,124,245,345,135 &\quad 235,234,134,145,125 & PQQ'R'E &\quad P'ORDF \tag{1} \\ 123,134,145,245,235 &\quad 125,124,234,345,135 & PRDQ'P' &\quad FQOR'E \tag{2} \\ 123,134,345,245,125 &\quad 235,234,124,145,135 & PRR'Q'F &\quad P'OQDE \\ 123,234,245,145,135 &\quad 125,124,134,345,235 & POQ'DE &\quad FQRR'P' \\ 123,234,345,145,125 &\quad 135,134,124,245,235 & POR'DF &\quad ERQQ'P' \\ \end{align*}

Desargues' configuration can be seen as the projection of five planes in three-dimensional space. Each line of the configuration corresponds to the intersection of two such planes, each point to the intersection of three. In the notation above, this is the format used in the left part: every point of each pentagon is given as three digits, corresponding to the planes involved. The notation to the right translates this into the labels used in your question. The two examples you gave are marked using numbered equations.

Here is the Python script I used to do this enumeration. The planes are represented as individual bits, so a point is a number with three bits set, and a line is one with two bits set. The recursion alternates between iterating over incident lines and incident points, always making sure to not reuse either. Some precautions were taken to not count the same things twice: The first point of the first pentagon is always $123$, and the first point of the second is the only remaining point on the fourth line of the first pentagon. Of the two possible orientations, only one is taken, by comparing the second and the last point. Here is the code:

def nicestr(v):
    if isinstance(v, int):
        return ''.join(str(i+1) for i in range(5) if v & (1 << i))
    else:
        return [nicestr(i) for i in v]

lines = [(1 << i)|(1 << j) for i in range(4) for j in range(i + 1, 5)]
points = [i ^ 0x1f for i in lines]
labels  = {
    '123': "P",
    '124': "Q",
    '125': "F",
    '134': "R",
    '135': "E",
    '145': "D",
    '234': "O",
    '235': "P'",
    '245': "Q'",
    '345': "R'",
}

def incident(p, l):
    assert p in points and l in lines
    return (p & l) == l

def pentaLine(seq):
    p = seq[-1]
    for l in lines:
        if incident(p, l) and l not in seq:
            pentaPoint(seq + [l])

def pentaPoint(seq):
    l = seq[-1]
    if len(seq) == 10:
        if incident(seq[0], l) and seq[2] < seq[-2]:
            firstDone(seq)
    elif len(seq) == 20:
        if incident(seq[10], l) and seq[12] < seq[-2]:
            assert len(set(seq)) == 20
            printResult(seq)
    else:
        for p in points:
            if incident(p, l) and p not in seq:
                pentaLine(seq + [p])

def firstDone(seq):
    p1 = seq[-2]
    for p2 in [seq[i] for i in range(0, 10, 2)]:
        p3 = 0x1f ^ p1 ^ p2
        if p3 in seq:
            return
        p1 = p2
    pentaLine(seq + [p3])

def printResult(seq):
    a = nicestr(seq[i] for i in range(0, 10, 2))
    b = nicestr(seq[i] for i in range(10, 20, 2))
    al = ''.join(labels[i] for i in a)
    bl = ''.join(labels[i] for i in b)
    print('{} &\quad {} & {} &\quad {} \\\\'
          .format(','.join(a), ','.join(b), al, bl))

pentaLine([7])

The script is not written for performance, or maintainable code, but instead for speedy coding and a rather dumb KISS approach to the problem. This is not the nicest of proofs, but I'd still consider it a possible proof, and it has the benefit of letting the machine do most of the work.