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) | Meaning | JSON 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:
- 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.
- Rotate each boundary list so that its first occurrence of the smallest numerical strand label comes first. Preserve the direction of the boundary walk.
- Deduplicate boundaries by their set of strand labels, keeping the first encountered boundary.
- 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#)
| Code | Reason |
|---|---|
syntax_error | syntax error |
input_limit | Use at most 256,000 input characters. |
crossing_limit | Use at most 100 starting crossings for certificates and 200 crossings during replay or in the interactive tool. |
move_limit | Use at most 100 moves. |
invalid_pd | Each strand label must occur exactly twice. |
nonplanar_pd | The PD rotation system is not a planar knot diagram. |
not_a_knot | The PD code must describe exactly one knot component. |
inconsistent_orientation | The PD under-strand directions are inconsistent. |
crossing_not_found | The crossing does not exist in the current diagram. |
strand_not_found | The strand does not exist in the current diagram. |
face_not_found | The face does not exist in the current diagram. |
not_r1_loop | The crossing does not bound a removable R1 loop. |
not_r2_digon | The face is not a removable R2 digon with opposite consistent crossing levels. |
same_r2_strand | R2 requires two distinct strands. |
strand_not_on_face | Both R2 strands must lie on the specified face. |
no_common_face | No face contains both R2 strands. |
ambiguous_face | More than one face contains both R2 strands; specify a face ID. |
invalid_r3_triangle | The strand and opposite crossing must bound a three-crossing triangular face. |
r3_level_mismatch | The sliding strand must be over at both ends or under at both ends. |
result_pd_mismatch | result_pd does not match replay. |
end_pd_mismatch | end_pd does not match replay. |
engine_failure | KnotSharp could not safely perform this move. |
layout_failure | Could not construct a grid drawing for this diagram. |
timeout | The calculation exceeded the five-second time limit. |
unavailable | The Reidemeister engine is unavailable. |