Try it

Enter a starting PD and moves in JSON, or choose an example.

Move Names and Arguments

Moves use the current diagram's labels. Commands, prefixes and over/under are case insensitive. X3 and 3 both mean crossing 3; S1 and 1 both mean strand 1. Crossings and faces start at zero. Strand numbers are the actual PD labels.

Command (alias)MeaningJSON object
DoR1 S1 over + (r1)Add a curl on S1; choose over/under and +/− sign.{"move":"DoR1","strand":1,"level":"over","sign":"+"}
UndoR1 X3 (u1)Remove a curl at X3.{"move":"UndoR1","crossing":3}
DoR2 F4 S1 over S2 (r2)Add two crossings in F4, S1 over S2.{"move":"DoR2","face":4,"over":1,"under":2}
UndoR2 F4 (u2)Remove the cancelling pair bounding F4.{"move":"UndoR2","face":4}
DoR3 S1 X3 (r3)Slide S1 over or under the opposite crossing X3 in a triangular face.{"move":"DoR3","strand":1,"crossing":3}

DoR2 F4 S2 under S1 and DoR2 4 1 2 mean the same as DoR2 F4 S1 over S2. Omit the face (DoR2 1 over 2, or omit the object's face) only when the two strands have exactly one common face. An ambiguous request returns the candidate face IDs.

PD labels and face numbering

A crossing is [under-in, over-90, under-out, over-270], in counterclockwise cyclic order. Crossings X0, X1, … follow the order in the PD array. Strand labels are preserved; new labels start above the current maximum. Removing crossings closes the gaps in crossing indices.

Faces are recomputed after every move using KnotSharp's deterministic rule:

  1. Visit crossings in PD order and their four slots in the order above. From each slot, cross the strand and turn left at the next crossing, following the boundary until the starting strand is reached again.
  2. Rotate each boundary list so that its first occurrence of the smallest numerical strand label comes first. Preserve the direction of the boundary walk.
  3. Deduplicate boundaries by their set of strand labels, keeping the first encountered boundary.
  4. Sort the remaining boundary lists lexicographically by integer values (a shorter prefix comes first), and number them F0, F1, ….

There is no special exterior-face number. For example, the trefoil PD [[1,5,2,4],[3,1,4,6],[5,3,6,2]] has boundaries F0 = [1,3,5], F1 = [1,4], F2 = [2,5], F3 = [2,6,4], F4 = [3,6]. Replay output gives these boundaries at every step.

These tools currently accept single oriented knots. [] represents the crossingless unknot, with an implicit strand S0 on which R1 can add a curl. It has no PD-derived face IDs. The implementation uses KnotSharp's Reidmeister move definitions.

Certificate checker

Enter a starting PD and moves in JSON, with an ending PD, or choose an example.

API

POST JSON to /api/reidemeister-certificate/replay to return {"end_pd":[...]}. Add ?output=steps to include every state (including step 0), its faces and strands, and a completed certificate. The try-it box always requests every step.

POST JSON to /api/reidemeister-certificate/ to check a certificate. /api/reidemeister-certificate/check is equivalent. Both accept start_pd, moves, and end_pd; the last is required for checking and optional for replay. Moves may mix command strings and objects. An object's optional result_pd asserts the exact state immediately after that move. Every supplied intermediate state and endpoint must match, including crossing order and strand labels. No relabelling is performed for comparison.

{"start_pd": [], "moves": [
  {"move": "DoR1", "strand": 0, "level": "over", "sign": "+",
   "result_pd": [[1,1,0,0]]}
], "end_pd": [[1,1,0,0]]}

Success: {"valid":true}. Malformed input: {"valid":false,"error":"syntax error"} (HTTP 400). A rejected move or assertion returns valid:false, step (1-based move number; 0 for the start), phase (start/move/end), code, and reason. An ambiguous face also includes candidate_faces. These verdicts return HTTP 200.

Limits: 256 KB of UTF-8 input, 100 moves, 100 starting crossings, 200 crossings during replay, and five seconds per computation. Timeouts (HTTP 504) and unavailable or failed engines (HTTP 503) return error and code, with no validity verdict.

Error codes (defined in F#)
CodeReason
syntax_errorsyntax error
input_limitUse at most 256,000 input characters.
crossing_limitUse at most 100 starting crossings for certificates and 200 crossings during replay or in the interactive tool.
move_limitUse at most 100 moves.
invalid_pdEach strand label must occur exactly twice.
nonplanar_pdThe PD rotation system is not a planar knot diagram.
not_a_knotThe PD code must describe exactly one knot component.
inconsistent_orientationThe PD under-strand directions are inconsistent.
crossing_not_foundThe crossing does not exist in the current diagram.
strand_not_foundThe strand does not exist in the current diagram.
face_not_foundThe face does not exist in the current diagram.
not_r1_loopThe crossing does not bound a removable R1 loop.
not_r2_digonThe face is not a removable R2 digon with opposite consistent crossing levels.
same_r2_strandR2 requires two distinct strands.
strand_not_on_faceBoth R2 strands must lie on the specified face.
no_common_faceNo face contains both R2 strands.
ambiguous_faceMore than one face contains both R2 strands; specify a face ID.
invalid_r3_triangleThe strand and opposite crossing must bound a three-crossing triangular face.
r3_level_mismatchThe sliding strand must be over at both ends or under at both ends.
result_pd_mismatchresult_pd does not match replay.
end_pd_mismatchend_pd does not match replay.
engine_failureKnotSharp could not safely perform this move.
layout_failureCould not construct a grid drawing for this diagram.
timeoutThe calculation exceeded the five-second time limit.
unavailableThe Reidemeister engine is unavailable.