15.2 Single character insertion and deletion operations

(26 July 2005)

Abstract

This paper describes a new technique for operational transform of single character insertion and deletion operations on a text document that solves the ERV puzzles and TP2 convergence problems in a far simpler, more efficient and elegant fashion than the SDT [1] or SDTO [2] algorithms.

Like the SDT algorithm, IT and ET are based on the effects relation, which is a total ordering on all characters inserted into the text document. The paper provides an easy way to calculate the effects relation.

Introduction

For state S and operation O, S' = S+O denotes the state obtained after executing O on state S. Operation O may only be executed on state S. Therefore we define statein(O) = S.

Let id(O) denote the site identifier of the site on which O was originally generated. It is assumed there is a total ordering on site identifiers.

Two operations O1, O2 are equivalent (written O1 ~ O2) if statein(O1) = statein(O2) = S and S+O1 = S+O2. Note that this doesn't imply that the operations are equal. For example, it is possible that id(O1)≠id(O2).

[O1 ... On] denotes the list of operations O1,...,On assumed to be contextually serialised - i.e. intended to be performed in the given order on some initial state S. S + [O1...On] denotes the state (((S+O1)+O2)+...+On).

As in [1], by definition characters in text documents have identity. A character is originally inserted by a particular user at a particular site. The character keeps its unique identity even though its index position in the document changes as characters are inserted or deleted. Note that a character doesn't simply relate to its appearance (eg its ASCII code) - for example each appearance of the letter 'A' in a document represents a different character.

We take the convention that strings use zero-based index positions. Given string s, let s[i] be the ith character and let s[i,j) denote the substring corresponding to the half-open interval [i,j).

Definition of IT, ET

Definition:
Let O1 || O2 and statein(O1) = statein(O2) = S. Then we define O1' = IT(O1,O2) as being a transformed version of O1 that maintains the original intention of O1, whilst being executed in the document state following execution of O2. i.e. statein(O1') = S+O2. Therefore [O2, IT(O1,O2)] is contextually serialised.
Definition:
ET is defined to be the inverse of IT. i.e. whenever O1' = IT(O1,O2) is defined, we define ET(O1', O2) = O1. Note that ET is only defined on contextually serialised concurrent operations

It has been shown in [3] that if IT satisfies conditions TP1, TP2 (defined below) then sites are able to execute operations in different orders yet achieve convergence at quiescence.

TP1

∀ O1, O2 where O1 || O2 and statein(O1) = statein(O2) = S, S + [O1 IT(O2, O1)] = S + [ O2 IT(O1, O2) ]

In the following diagram we require S12 = S21.

Transformation property TP1

TP2

∀ O1, O2, O3, IT( IT( O3, O1), IT(O2, O1)) = IT( IT( O3, O2), IT(O1, O2))

System 1: Insert operations

In system 1 we limit ourselves to insert operations that apply to a single text document. Operation O = ins(p,c) inserts character c at position p.

Let each operation contain the following fields.

Field Description
id The site identifier of the site that originally generated the operation
p Zero based insertion position
c Character to be inserted

The following diagram shows two cases of transforming operations Ox, Oy against each other. For each cell the initial state is in the bottom left corner and the final state is in the top right corner. There are two paths from the initial state to the final state - either along the bottom and right edges, or along the left and top edges.

Transformation cells for insert operations

From these two cells we get four cases for IT(O1,O2).

Cell Binding for O1 Binding for O2 Criteria Action
1 Ox Oy O2.p < O1.p ++O1.p
1 Oy Ox O1.p < O2.p -
2 Ox Oy O2.p = O1.p ∧ O2.id < O1.id ++O1.p
2 Oy Ox O2.p = O1.p ∧ O1.id < O2.id -

The criteria for these four cases are mutually exclusive and cover all possible cases. Therefore the above cells lead to the following well-defined algorithm for IT.

// Assumes O1 || O2
IT(Operation& O1, const Operation& O2)
{
    if (O2.p < O1.p || O2.p == O1.p && O2.id < O1.id) ++O1.p;
}

From the two cells we get four cases for ET(O1,O2).

Cell Binding for O1 Binding for O2 Criteria Action
1 Ox' Oy O1.p > O2.p + 1 --O1.p
1 Oy' Ox O1.p < O2.p -
2 Ox' Oy O1.p = O2.p+1 ∧ O2.id < O1.id --O1.p
2 Oy' Ox O1.p = O2.p ∧ O1.id < O2.id -

These four criteria are mutually exclusive, but do not cover all cases. The missing cases are

  • O1.p = O2.p ∧ O2.id < O1.id
  • O1.p = O2.p + 1 ∧ O1.id < O2.id

It would seem that these cases can only occur when there is a causal dependence between O1, O2. Therefore we argue that this "incompleteness" is acceptable as long as we only ET concurrent operations. Therefore we have the following algorithm for ET

// Assumes O1 || O2
ET(Operation& O1, const Operation& O2)
{
    if (O2.p < O1.p) --O1.p;
}

We may return to this incompleteness issue in a future paper that addresses the support for selective undo - because that requires transpose of causally dependent operations.

Proof of convergence

TP1: Let the initial document state be S. We want to show that

∀O1,O2, S + [O1 IT(O2, O1)] = S + [ O2 IT(O1, O2) ].

Let |S| = n and Si denote the ith character in S. Let O1 = ins(p1,c1). O2 = ins(p2,c2). O1, O2 both execute on state S. Let O1' = IT(O1,O2) and O2' = IT(O2,O1).

Let S1 = S + [O1] = [S0 S1 ... Sp1-1 c1 Sp1 ... Sn-1] and S2 = S + [O2] = [S0 S1 ... Sp2-1 c2 Sp2 ... Sn-1].

There are four cases to consider

p1 < p2

O1' = ins(p1,c1).

O2' = ins(p2+1,c2)

S + [O1 O2'] = S1 + [O2'] = [S0 S1 ... Sp1-1 c1 Sp1 ... Sp2-1 c2 Sp2 ... Sn-1] = S2 + [O1'] = S + [O2 O1']

p2 < p1 Symmetrical to case of p1 < p2
p1 = p2 & O1.id < O2.id

O1' = ins(p1,c1)

O2' = ins(p2+1,c2)

S + [O1 O2'] = S1 + [O2'] = [S0 S1 ... Sp1-1 c1 c2 Sp1 ... Sn-1] = S2 + [O1'] = S + [O2 O1']

p1 = p2 & O2.id < O1.id Symmetrical to case of p1 = p2 & O1.id < O2.id

Note that the relative order of characters is preserved under IT. This relates to the requirement of user intention preservation.

TP2: Need to show ∀ O1, O2, O3, IT( IT( O3, O1), IT(O2, O1)) = IT( IT( O3, O2), IT(O1, O2))

Continuing the conventions in the proof of TP1, let O3 = ins(p3,c3).

Suppose p1 < p2. Then there are seven cases to consider. The following table shows the shifts (i.e. Δp3) applied to p3 as O3 ITs first past O1 then O2' = ins(p2',c2), or alternatively first past O2 then O1' = ins(p1',c1). Note that p2' = p2+1, and p1' = p1.

O1 O1 O2' O2' O2 O2 O1' O1'
p3 to p1 Δp3 p3' to p2' Δp3 p3 to p2 Δp3 p3'' to p1' Δp3
p3 < p1 < 0 < 0 < 0 < 0
p3 = p1 & O3.id < O1.id = 0 < 0 < 0 = 0
p3 = p1 & O1.id < O3.id = +1 < 0 < 0 = +1
p1 < p3 < p2 > +1 < 0 < 0 > +1
p3 = p2 & O3.id < O2.id > +1 = 0 = 0 > +1
p3 = p2 & O2.id < O3.id > +1 = +1 = +1 > +1
p3 > p2 > +1 > +1 > +1 > +1

There is a consistency in the relationship between p1,p3 (irrespective of whether O3 ITs past O1 first or O2 first): In the first five rows, when O3 ITs first past O2, p3 is not changed (Δp3 = 0). Also p1' = p1 so the relationship between p1,p3 is preserved. In the last two rows, when O3 ITs past O2, p3 is incremented. This still means p3 > p1 so again the relationship between p1,p3 is preserved.

There is a consistency in the relationship between p2,p3 (irrespective of whether O3 ITs past O1 first or O2 first): In the first two rows, when O3 first ITs past O1, p3 is not changed (Δp3 = 0). In these cases p3 < p2 and also p3 < p2' = p2+1, so the relationship between p2, p3 is preserved. In the last five rows, when O3 ITs past O1, p3 is incremented. However O2' also has its position p2 incremented, so the relationship between p2, p3 is preserved.

In all cases the total shift applied to p3 is the same, and therefore condition TP2 is proven. By symmetry we see that TP2 is also proven when p2 < p1.

Let p = p1 = p2, WLOG assume O1.id < O2.id. Therefore O1' = ins(p1,c1) and O2' = ins(p2+1,c2). There are five cases to consider. The following table shows the shifts (i.e. Δp3) applied to p3 as O3 ITs past O1 then O2', or alternatively O2 then O1'. In all cases the total shift is the same, and therefore condition TP2 is proven.

O1 O1 O2' O2' O2 O2 O1' O1'
p3 to p1 Δp3 p3 to p2' Δp3 p3 to p2 Δp3 p3 to p1' Δp3
p3 < p < 0 < 0 < 0 < 0
p3 = p & O3.id < O1.id = 0 < 0 = 0 = 0
p3 = p ∧ O1.id < O3.id ∧ O3.id < O2.id = +1 = 0 = 0 = +1
p3 = p & O2.id < O3.id = +1 > +1 = +1 > +1
p3 > p > +1 > +1 > +1 > +1

Alternative proof of convergence

At quiescence all sites have executed all the insert operations. Therefore all sites agree on the set of characters that have been inserted. Therefore to show convergence, it is sufficient to show that all sites agree on a total ordering of the characters.

Consider that we break up the text document into groups of characters, where characters within a group were tied for insertion position during IT (and therefore site ids were used to break the ties). It is claimed that all the following are true

  1. All sites agree on the assignment of characters to these groups.
  2. There is agreement by all sites on a total ordering of these groups.
  3. Within a group, the characters are ordered according to the total ordering on the site identifiers.

Cell 1 relates to the division of the characters into the groups, and cell 2 to the ordering of operations within a group.

It follows that all sites agree on a total ordering of the inserted characters.

System 2: Insert and track operations

System 2 extends System 1 by allowing for "track" operations, in addition to insert operations. That is, System 2 supports the following two operations:

  • ins(p, c) — insert character c at position p.
  • trk(p) — track the character at position p.

The "track" operation doesn't have any side effects. Its only purpose is to track the location of a character.

The solution is expressed with the following two additional cells

Transformation cells for track operations

Cell 3 says that tracking operations have no effect on each other. Cell 4 says we need to increment the position of a tracked character when there is an insertion at the same position or to the left.

From these additional cells we can derive the IT and ET algorithms as follows.
IT(Operation& O1,const Operation& O2)
{
    if (O2.ins)
    {
        if (O2.p < O1.p || O2.p == O1.p && (O1.trk || O2.id < O1.id))
        {
            ++O1.p;
        }
    }
}

ET(Operation& O1,const Operation& O2)
{
    if (O2.ins && O2.p < O1.p)
    {
        --O1.p;
    }
}

Note that ET assumes O1 || O2, so it never sees the case of t(O1) = trk, t(O2) = ins and O1.p = O2.p.

Lemma:
Under IT, a tracking operation correctly tracks the position of a character.
Proof:

Characters are never deleted, so the location of a given character can always be tracked within the document. Let the tracking operation be O1, with O1.p initially equal to the location of the tracked character.

If O2 is an insert, O1.p is shifted to the right if and only if O2.p ≤ O1.p, preserving the tracked character's position. If O2 is a tracking operation, O1.p is unchanged, which also preserves it.

Proof of convergence: The tracking operations have no effect on the document state; therefore convergence is achieved because we continue to use cells 1,2.

System 3: Insert and delete operations

System 3 extends System 1 by allowing for single character delete operations, in addition to single character insert operations. That is, System 3 supports the following two operations:

  • ins(p, c) — insert character c at position p.
  • del(p) — delete the character at position p.

A correct solution to IT and ET is surprisingly difficult and there have been many attempts in the last 15 years by researchers that have failed to correctly provide both properties TP1 and TP2. Some researchers have avoided the problem by employing a control algorithm that doesn't require TP2 for convergence. However, [1] points out that it is necessary to address ERV puzzles to preserve user intention correctly, and only the solutions in [1] and [2] have addressed the ERV puzzles.

The solutions that appear in [1] (SDT) and [2] (SDTO) appear correct but are quite complex and this paper describes a far simpler solution. Importantly the proposed approach leads to a far more economical implementation, and doesn't require a change to the control algorithm as required by both [1] and [2].

Note firstly that (in System 1 or 2) we have a working solution that satisfies both TP1 and TP2 when we limit ourselves to insertion operations only. It seems that delete operations are the "fly in the ointment". This leads to the following central idea: to imagine that all delete operations on the document have been disabled! The result would be that the document contains all characters that have ever been inserted into the document. The useful thing here is that we get a total ordering on all characters. This forms the basis of correctly determining the effects relation between any two operations.

Definition:
Let the Effects Document refer to the hypothetical document obtained at a given site assuming all delete operations have been disabled so that the document contains all characters that have ever been inserted by operations.

The Effects Document is only a theoretical tool - it is not actually stored. For each operation we keep track of both the position p in the normal document (in which deletes are allowed to take effect) as well as the position q in the Effects Document (in which all delete operations are ignored). The effects relation is then as simple as comparing q positions instead of p positions. The "false ties" according to [1] are precisely the cases where p positions are tied but q positions are not.

So by comparing q positions, we correctly determine when one operation is to the left of another, avoiding the problem of prematurely resorting to site ids to break the tie. This is used to update both the p and q positions as required. Note that because delete operations never occur on the Effects Document, a q position is never shifted to the left.

Let each operation contain the following fields.

Field Description
id The site identifier of the site that originally generated the operation. It is assumed there is a total ordering on site identifiers.
ins Boolean flag where true indicates an insertion operation and false indicates a delete operation
enabled Boolean flag for whether the operation is enabled or disabled. Note that only delete operations can be disabled
p Zero based position in the real document (in which deletes are allowed)
q Zero based position in the Effects document (in which deletes are always disabled)
c Character to be inserted or deleted

Let ins(p,q,c) represent the operation to insert character c at the given p-position and q-position. Let del(p,q) represent the operation to delete the character at the given p-position and q-position. Let ~del(p,q) represent a disabled deletion operation. Insertion operations cannot be disabled.

Analysis using cells

The following sections provide an analysis using our "cells".

Insert with insert
Insert transformed with insert

Cells 5,6 account for transforming insertion operations with insertion operations, and are analogous to cells 1,2 described previously. Note that only the q-position is tested, while both the p-position and q-position are shifted.

Delete with insert
Delete transformed with insert, cells 7 and 8 Disabled delete transformed with insert, cells 9 and 10

In cell 7 we have a delete on the left of an insert, causing the insertion position to be shifted to the left. Note that the p-position is adjusted, but not the q-position.

In cell 8 we have an insert on the left of a delete, causing the deletion position to be shifted to the right. Note that both the p-position and q-position are shifted.

Delete with delete
Delete transformed with delete, cells 11 and 12

In cell 11 we have a delete on the left of another delete, causing the deletion on the right to shift to the left. Note that the p-value is adjusted, but not the q-value.

In cell 12 we have two delete operations that delete the same character. Both of the operations are disabled after transformation.

The Boolean enable flag is sufficient for contextually valid operations. As established by the reachability invariant below, a valid history buffer contains exactly one enabled delete of a given character—the first—and all subsequent deletes of that character are disabled. The transformation functions are defined on these reachable operation states, rather than arbitrary combinations of field values.

Algorithm

The following tables provide the implementations of IT and ET (in C++) based on the types of operations O1 and O2.

O1 O2 IT(O1,O2)
ins ins if (O2.q < O1.q || O2.q == O1.q && O2.id < O1.id) { ++O1.q; ++O1.p; }
del ins if (O2.q <= O1.q) { ++O1.q; ++O1.p; }
ins del if (O2.enabled && O2.q < O1.q) --O1.p;
del del if (O2.enabled && O2.q < O1.q) --O1.p;
if (O2.enabled && O2.q == O1.q) O1.enabled = false;
O1 O2 ET(O1,O2)
ins ins if (O2.q < O1.q) { --O1.q; --O1.p; }
del ins if (O2.q < O1.q) { --O1.q; --O1.p; }
ins del if (O2.enabled && O2.q < O1.q) ++O1.p;
del del if (O2.enabled && O2.q < O1.q) ++O1.p;
if (O2.enabled && O2.q == O1.q) O1.enabled = true;

Comments on use of enable flag

This algorithm makes use of an enable flag to avoid deleting a character twice. Note that the first operation in a linear history buffer to delete the character is enabled, and all subsequent delete operations are disabled. Therefore, sites may disagree about which operation actually deleted the character! This is reasonable because we are only interested in convergence of the final document state.

Reachability invariant (editorial note)

The following invariant supplies a condition that was implicit in the original account but is needed to justify the Boolean enable flag precisely:

For each character identity, if a valid linear history buffer contains one or more delete operations targeting that character, exactly the first such delete is enabled and every subsequent such delete is disabled.

The invariant holds for an empty history buffer. A locally generated delete targets a visible character and is initially enabled, so its causal context contains no effective delete of that character. When an enabled incoming delete is IT'd through the concurrent suffix, it remains enabled if the suffix has no same-target delete. Otherwise the first same-target delete in the suffix is enabled and disables the incoming delete; later same-target deletes are disabled and have no further effect. If an already-disabled delete is forwarded, its enabled predecessor occurs earlier in the sender's valid serialisation and is included in the operation's context, so it occurs in the receiver's prefix. Appending the received delete therefore preserves the invariant.

It remains to check history-buffer transposition. For adjacent same-target deletes the only reachable enable states are [enabled, disabled], when they are the first two such deletes, and [disabled, disabled], when an enabled predecessor occurs earlier. In the first case, ET re-enables the second delete and IT disables the first, after which swapping them again gives [enabled, disabled]. In the second case neither ET nor IT changes an enable flag and the pair remains [disabled, disabled]. A pair [disabled, enabled] is unreachable. Transpositions involving an insertion or deletes of different characters do not change how many deletes target a character. Thus local generation, remote integration, and every adjacent transposition preserve the invariant, and induction establishes it for every reachable history buffer.

Alternative exposition

Definition 1:
For operation O, let shiftp(O) and shiftq(O) be defined as follows:
Definitions of shiftp and shiftq
Definition 2:
For operations O1, O2, let O1 < O2 (meaning O1 is on the left of O2) be defined as follows

O1 < O2 = (O1.q < O2.q) ∨ (O1.q = O2.q ∧ O1.ins ∧ (O2.del ∨ O1.id < O2.id))

Algorithm

IT(O1,O2)
{
    if (O2.enabled && !O1.ins && !O2.ins && O1.q == O2.q && O1.enabled)
    {
        O1.enabled = false;
    }
    else if (O2 < O1)
    {
        O1.q += shiftq(O2);
        O1.p += shiftp(O2);
    }
}

ET(O1,O2)
{
    if (O2.enabled && !O1.ins && !O2.ins && O1.q == O2.q && !O1.enabled)
    {
        O1.enabled = true;
    }
    else if (O2 < O1)
    {
        O1.q -= shiftq(O2);
        O1.p -= shiftp(O2);
    }
}

Proof of correctness

There is a useful mapping from system 3 to system 2, where delete operations are mapped to tracking operations, and the effects document is mapped to a document in which delete operations are never performed. This immediately gives us two useful results - that convergence of the effects document is achieved, and delete operations correctly track the location of the character within the effects document.

Lemma 1:
For contextually valid operations, ET(IT(O1,O2), O2) = O1.
Proof:

There are three cases to consider:

  1. If O1,O2 are both enabled delete operations at the same q-position, O1 is disabled by IT and then re-enabled by ET. If the operations occur in a reachable history-buffer transposition, the reachability invariant above gives the equivalent adjacent-pair analysis: [enabled, disabled] transposes to [enabled, disabled] with the enabled representative exchanged, while [disabled, disabled] remains unchanged. The invalid state [disabled, enabled] need not be inverted.
  2. Otherwise, suppose O2 < O1. Shifts are applied to O1.p and O1.q. Now shiftq(O2) ≥ 0, so O1.q can only be shifted further to the right. Therefore O2 < O1 continues to hold after IT, and ET reverses the shifts applied to O1.p and O1.q.
  3. Otherwise, O2 is not less than O1. IT does not modify O1, and ET likewise applies no change.

In all cases we have established the result.

ET preserves the comparison used during IT. If IT shifts O1 because O2 < O1, then shiftq(O2) ≥ 0 and the comparison remains true until ET reverses that shift. If IT does not shift O1, ET applies no shift either. The special equal-q delete/delete case changes only the enable flag and leaves the ordering fields unchanged.

Lemma 2:
Assuming operations on a single text document, the < relation on operations is asymmetric: O1 < O2 ⇒ ¬(O2 < O1).
Proof:

Suppose both O1 < O2 and O2 < O1. Neither q-position can be strictly smaller than the other, so O1.q = O2.q. The definition would then require both operations to be insertions and would require both O1.id < O2.id and O2.id < O1.id. This contradicts the strict total ordering of site identifiers.

Lemma 3:
For operations on a single text document, excluding a pair of delete operations that target the same character, the < relation defines a strict total order. For insertions tied at the same q-position, the relevant concurrent operations are assumed to have distinct site identifiers.
Proof:

Operations are ordered first by q-position. At equal q-position, all insertions precede deletions and insertions are ordered by site identifier. Two deletes at the same q-position are the excluded case because they target the same character. Thus any two operations in the stated domain are comparable in exactly one direction. Asymmetry follows from Lemma 2. Transitivity follows from the lexicographic construction: a strict increase in q-position remains strict, while at one q-position the strict site-identifier order on insertions is transitive and every insertion precedes every deletion. Therefore < is a strict total order on the stated domain.

Lemma 4:
Under IT, the q-position of a delete operation tracks the position of the deleted character as it appears in the effects document.
Proof:

Characters are never deleted from the effects document, so their locations remain trackable. Let O1 be a delete whose q-position is initially the location of its target character in that document. Because O1 is a delete, the ordering test simplifies to:

O2 < O1 = (O2.q < O1.q) ∨ (O2.q = O1.q ∧ O2.ins).

Consequently, an insertion O2 shifts O1.q to the right if and only if O2.q ≤ O1.q, preserving the target character's location. A delete O2, enabled or not, does not change O1.q because shiftq(O2) = 0; this is correct because deletes do not remove characters from the effects document.

Lemma 5:
At quiescence, convergence of the effects document is achieved.
Proof:

Only insert operations cause changes to the effects document. Furthermore, when an insert operation O1 is transformed against a delete operation O2, O1.q is not adjusted. Therefore the presence of delete operations has no effect on the q-positions of the insert operations.

This shows that the solution can be mapped to the simpler system where the document state is related to the effects document, document positions are related to q-positions, and there are only insert operations.

So assuming the simpler system (with only insert operations) achieves convergence, we demonstrate convergence of the effects document as required.

Lemma 6:
At quiescence, convergence of the document is achieved.
Proof:

By Lemma 5, every site has the same effects document at quiescence. Every site has also received the same set of delete operations. By Lemma 4, each delete continues to identify the same character in that effects document. For several deletes of one character, the enable rule permits exactly the first such delete in a local serialisation to affect the visible document and disables the others. Sites may enable different delete operations, but they exclude the same character identity exactly once. Consequently every site obtains the visible document by removing the same set of character identities from the same effects document, and the visible documents converge.

Lemma 7:
Characters in the document appear in the same relative order as in the effects document.
Proof:

The visible document is obtained from the effects document only by omitting characters targeted by enabled deletes. Deletion does not reorder the remaining characters. Therefore any two characters that remain visible occur in the same relative order as they do in the effects document.

Completion of the convergence proof (editorial note)

The preceding lemmas can be strengthened into a direct argument that transformation through a valid set of concurrent operations is independent of the order in which that set is serialised. Give every inserted character its operation identity. The insertion rules place these identities in one total effects order: q-position is primary, and the total order on site identifiers breaks a genuine tie between concurrent insertions. Deletes do not alter that order.

For an operation O transformed through a context A, its resulting fields have the following interpretation:

  1. O.q is its boundary or target position after inserting the members of A that precede O in the total effects order.
  2. O.p is the corresponding visible rank after omitting the distinct character identities deleted to its left by A.
  3. If O is a delete, O.enabled is true exactly when A contains no earlier delete of O's target identity; once the first same-target delete has been encountered, O is disabled and later disabled representatives have no further effect.

The first item follows from the insertion-only result for System 1. The second follows because an enabled delete shifts precisely the operations whose visible positions lie to its right, while the reachability invariant ensures that several deletes of one identity contribute only one such shift. The third is exactly the enable invariant. Each item is therefore a function of the context's inserted identities and distinct deleted identities, rather than of the chosen valid serialisation of that context.

Consequently, for three concurrent operations O1, O2, O3, transforming O3 through O1 followed by IT(O2,O1) gives the same q-position, visible p-position and enable state as transforming it through O2 followed by IT(O1,O2). Its type, identity and character are never changed. The resulting operations are equal, establishing TP2 on the contextually valid domain. TP1 follows from the same canonical interpretation for a context containing two operations: both execution paths construct the same effects order and omit the same set of deleted identities.

At quiescence every site has received the same insert operations and hence, by Lemma 5, has the same effects document. Every site has also received the same delete operations. By Lemma 4 they target the same character identities, and by the reachability invariant each identity targeted one or more times is omitted exactly once. The visible document at every site is therefore the common effects document filtered by the same set of deleted identities. Lemma 7 preserves the order of the remaining characters, so all sites have the same visible document. This completes the convergence proof for System 3.

Intention preservation (editorial note)

“Intention” cannot mean an unrecorded subjective purpose of the user. In the CSM model of [1] it has an operational meaning: preserve the effect of each operation and the effects relation between operations. For the operations in this paper, the effect of an insertion is to introduce its fresh character identity at a particular boundary in the effects order; the effect of a deletion is to make the character identity selected at generation invisible. The effects relation is the relative order of the character identities. Concurrent insertions at the same boundary did not previously have a relative order, so ordering them by site identifier completes, rather than contradicts, the recorded intention.

Lemma 8 (completed editorially):
IT and ET preserve intention, in this operational sense, for contextually valid operations in System 3.
Proof:

Consider first an insertion O. Transformation never changes its identity or character. Its q-position is shifted exactly when another insertion is placed before it in the effects order; a delete never changes q. Thus O remains at the same boundary relative to every character that existed in its generation context, while concurrent insertions at that boundary are put into the one deterministic site-identifier order. Its p-position is the visible projection of that q-position: it is shifted by an enabled deletion exactly when a distinct visible character to its left disappears. Multiple deletions of one character contribute only one shift, by the enable invariant. Executing the transformed insertion therefore has the same individual effect and preserves all previously defined effects relations.

Now consider a deletion O. By Lemma 4, transformation preserves the identity of its target: insertions adjust q precisely when they add a character before that target, and deletions do not adjust q because they do not remove identities from the effects document. The p-position remains the visible rank of the target. If a concurrent deletion has already made the same identity invisible, O is disabled. This is not a loss of its intended effect: that effect has already been achieved, and a second deletion of the same identity must be idempotent. Deleting a character changes visibility but not the effects order, so it cannot reverse an effects relation between surviving or tombstoned identities.

It follows that IT preserves both parts of the CSM criterion: each operation has the same effect as at generation, modulo an effect already achieved by an equivalent concurrent deletion, and every pre-existing effects relation is retained. ET is the inverse of IT on its stated domain. Removing a context operation reverses exactly the corresponding p- and q-adjustments and the same-target enable transition, without changing identity, character, target or effects order. ET therefore preserves the same two properties. This completes the proof obligation left as “Proof: TODO” in the 2005 text.

Correctness status (editorial note): Systems 1 and 2 have the convergence arguments given above. For System 3, the reachability invariant and canonical-context argument complete the TP1, TP2 and quiescent-convergence argument for contextually valid operations processed by the stated history-buffer control algorithm. This does not define IT or ET on arbitrary combinations of field values that cannot arise in a valid history. Lemma 8 completes intention preservation for the CSM effects-and-effects-relation meaning applicable to these primitive operations; it does not claim to formalise arbitrary subjective user intention or provide a general selective-undo theory.

Generation of operations

When generating an operation it is necessary to correctly initialise both the p-position and q-position stored in the operation. To support this it is necessary to be able to map from p-position to q-position. Therefore a document needs to maintain information about where characters have been deleted. An efficient implementation can store run-length encoded information. However, for the purposes of easily understanding the requirements, consider that an array B[] of booleans flags is stored, indexed by q-position. Let B[q] be false to indicate that the qth character has been deleted, otherwise B[q] = true.

To generate an operation to delete the pth character, we calculate the q-position as follows

int Getq(int p)
{
    int n = B.size();
    int pi = 0;
    for (int i=0 ; i < n ; ++i)
    {
        if (B[i])
        {
            if (pi == p)
            {
                return i;
            }
            ++pi;
        }
    }
    return n;
}

When operation O = del(p,q) is executed, B[] is updated as follows

void UpdateBForDelete(int p,int q)
{
    B[q] = false;
}

When operation O = ins(p,q,c) is executed, B[] is updated as follows

void UpdateBForInsert(int p,int q)
{
    B.insert(B.begin() + q, true);
}

Note that the q-positions (not the p-positions) stored within the operation are used to update B.

Tests

The algorithm was tested by simulating between two and nine sites making randomly generated single-character insertions and deletions and exchanging them in arbitrary causally valid orders. Convergence was checked repeatedly between sites during each simulation and across all sites after every operation had been exchanged. Sites were required to agree on the complete effects document, including character identities and visibility.

A total of 10,000 simulations of 1,000 events each completed without a convergence failure. The number and variety of operations, sites and exchange orders covered by this testing provide very high confidence in the correctness of the algorithm.

Browse the test files.

Related work (editorial note)

During 2004, David Barrett-Lennard was studying the TP2 puzzles, including examples like the one described in Operational Transformation On Text. He observed that there were no such puzzles when all sites performed only insertions, and none when all sites performed only deletions: the puzzles arose when insertions and deletions were both present.

In early 2005 he read Du Li and Rui Li's work on the operation effects relation. Their idea led directly to the realisation that positions could be tracked as though deletions had not taken place. This preserves the correctness of the insertion ordering by preventing deletions from destroying the positional information on which that ordering depends. Li and Li's effects relation was therefore the key inspiration for the Effects Document introduced in this paper, and their contribution to the idea deserves explicit credit. Their work identifies preservation of the effects relation between concurrent operations as a consistency requirement for group editors; see Preserving Operation Effects Relation in Group Editors, published in November 2004.

The Effects Document is a hypothetical document containing every inserted character while treating all delete operations as disabled. It provides a simple way to calculate the effects relation while retaining the ordering information needed by insertion operations.

This line of work was subsequently examined by Gérald Oster, Pascal Urso, Pascal Molli and Abdessamad Imine in the INRIA research report Proving Correctness of Transformation Functions in Collaborative Editing Systems, published in December 2005. They used the SPIKE automated theorem prover to find counterexamples in several existing operational transformation algorithms, including Li and Li's SDT and SDTO algorithms. The counterexamples helped them develop Tombstone Transformation Functions (TTF), which retain deleted characters as invisible tombstones and were formally checked against TP1 and TP2.

TTF preserves the operation effects relation. Conceptually, it shares the central insight of the Effects Document: deleted characters remain available as stable ordering landmarks. The INRIA authors also explicitly describe their use of tombstones as an adaptation of the WOOT approach, developed in Real Time Group Editors Without Operational Transformation. TTF should therefore be understood as connecting Li and Li's effects relation with the tombstone representation used by WOOT, rather than as deriving solely from either one.

References

  1. Du Li and Rui Li, Ensuring Consistency in Real-Time Group Editors, ACM Transactions on Computer-Human Interaction, April 2004. Under review at the time of writing.
  2. Du Li and Rui Li, An Operational Transformation Algorithm and Performance Evaluation, Journal of CSCW, July 2005. Under review at the time of writing.
  3. Matthias Ressel, Doris Nitsche-Ruhland and Rul Gunzenhäuser, An Integrating, Transformation-Oriented Approach to Concurrency Control and Undo in Group Editors, Proceedings of CSCW 1996, pages 288–297, 1996.

Source code

The historical C++ implementation is retained as a documentation resource. It implements the Boolean enable-flag algorithm described above. Its transformation functions assume the contextually valid operation states characterised by the reachability invariant in the editorial completion of the proof. Browse the source files.