Q:

Finding vertices in an ordered set of a complete graph

Problem: For an ordered set of edges E of a complete graph Kn, given an edge Ei, find the edge's vertices (v, w)_Ei.
Note: This is likely not a problem specific to graph theory, although it was chosen to express the problem solely because of familiarity. Apologies for any incorrect notation introduced.
Suppose that constructed from a complete graph K5 consisting of vertices 1, 2, 3, 4, 5, we have an ordered set E of the graph's edges, totalling 10 edges. The set E is known to always be ordered as follows:
Ei = (0 < v < n, v < w =< n)
E1 = (1, 2)
E2 = (1, 3)
E3 = (1, 4)
E4 = (1, 5)
E5 = (2, 3)
E6 = (2, 4)
E7 = (2, 5)
E8 = (3, 4)
E9 = (3, 5)
E10 = (4, 5)

For any given Ei, we must now find the vertices (v, w)_Ei using i alone. For example, given 6 we should obtain (2, 4).
Update:
Another, perhaps simpler way of expressing this problem is:
n = 5
i = 0

for v = 1 to n - 1
    for w = v + 1 to n
        i++
        print "E" + i + " = " + v + ", " w 

print "E6 = " + findV(6) + ", " + findW(6)

How is this done?

A:

To solve the problem in closed form, we need the formula for the sum of first k numbers: 1 + 2 + ... + k = (k + 1) * k / 2. This gives us a mapping from edge (i, j) to edge index:
from math import ceil, sqrt

def edge_to_index((i, j)):
    return n * (i - 1) + j - i * (i + 1) / 2

We can derive the inverse mapping:
def index_to_edge(k, n):
    b = 1.0 - 2 * n
    i = int(ceil((-b - sqrt(b**2 - 8 * k)) / 2))
    j = k - n * (i - 1) + i * (i + 1) / 2
    return (i, j)

A test:
n = 5

print "Edge to index and index to edge:"
for i in range(1, n + 1):
    for j in range(i + 1, n + 1):
        k = edge_to_index((i, j))
        print (i, j), "->", k, "->", index_to_edge(k, n)

The output:
Edge to index and index to edge:
(1, 2) -> 1 -> (1, 2)
(1, 3) -> 2 -> (1, 3)
(1, 4) -> 3 -> (1, 4)
(1, 5) -> 4 -> (1, 5)
(2, 3) -> 5 -> (2, 3)
(2, 4) -> 6 -> (2, 4)
(2, 5) -> 7 -> (2, 5)
(3, 4) -> 8 -> (3, 4)
(3, 5) -> 9 -> (3, 5)
(4, 5) -> 10 -> (4, 5)

