srecord noeq G22MeshMapper_v2(G22Mesh mesh1, G22Mesh mesh2) { // import the important classes delegate Anchor, Curve to G22Mesh. delegate mapAnchor, unmapAnchor to mm. G22MeshMapping mm; // index structures MultiMap anchorsByArity2; // EXCEPTIONS (e.g. meshes don't match in signature) // set to the reason why when a mapping is deemed impossible settable O rejectedBecause; bool rejected() { ret rejectedBecause != null; } // INTERNAL VARS bool prechecksDone; S sig1, sig2; Anchor anchor1; // first anchor to map G22MeshMapping get() { ret mm; } // Do the whole search, but in "random" mode (may fail) void run_random { search_step1(); while (search_step2()); } // random mode void search_step1() { prechecks(); if (rejected()) ret; // make empty mapping mm = new G22MeshMapping(mesh1, mesh2); anchorsByArity2 = multiMapIndex(mesh2.anchors(), a -> a.arity()); // Choose first anchor to map - this is arbitrary // (not a backtracking point) Anchor anchor1 = random(mesh1.anchors()); // Choose which anchor to map it to // (first backtracking point) L options = anchorsByArity2.get(anchor1.arity()); // ret BacktrackingOptions(options, ...); ??? Anchor anchor2 = random(options); print("G22MeshMapper_v2 step1: Connecting " + anchor1 + " to " + anchor2); mapAnchor(anchor1, anchor2); } // random mode bool search_step2() { bool change; for (curve1 : mesh1.curves()) { // skip if curve is already mapped if (mm.isMapped(curve1)) continue with print("Curve is mapped: " + curve1); // check if anchors are mapped Anchor start2 = mm.get(curve1.start); Anchor end2 = mm.get(curve1.end); // If neither anchor is mapped, postpone this curve if (start2 == null && end2 == null) continue with print("Curve is not discovered yet: " + curve1); // Start at the mapped anchor, choose a viable curve in mesh2 to map to bool startAtEnd = end2 != null; Anchor a1other = curve1.anchor(!startAtEnd); Anchor a2 = mm.get(curve1.anchor(startAtEnd)); new L possibleCurves; for (c2 : a2.curves()) { if (mm.isMapped(c2)) continue with print("Curve already mapped: " + c2); // check for arity match Anchor a3 = c2.anchorOpposite(a2); int arity1 = a3.arity(), arity2 = a1other.arity(); if (arity1 != arity2) continue with print("Arity mismatch (" + arity1 + "/" + arity2 + ") for curve " + c2); // This curve is viable as a mapping target possibleCurves.add(c2); } print(l(possibleCurves) + "/" + l(a2.curves()) + " possible curve(s) to map " + curve1 + " to: " + possibleCurves); if (empty(possibleCurves)) ret false with rejectedBecause("Could not map curve " + curve1); // Map the curve Curve c2 = random(possibleCurves); bool flipped = c2.start() != a2; print("Mapping curve " + curve1 + " to " + c2); mm.mapCurve(curve1, c2, flipped); set change; } ret change; } // backtracking version class Search extends VStackComputableWithStep { Anchor anchor2; void step(VStack stack) { cast stack to BStack; if (step == 0) { prechecks(); if (rejected()) stack.ret(); step = 1; } else if (step == 1) { // make empty mapping mm = new G22MeshMapping(mesh1, mesh2); anchorsByArity2 = multiMapIndex(mesh2.anchors(), a -> a.arity()); // Choose first anchor to map - this is arbitrary // (not a backtracking point) anchor1 = random(mesh1.anchors()); // Choose which anchor to map it to (first backtracking point). // List should never be empty because we checked the signatures first. L anchor2options = anchorsByArity2.get(anchor1.arity()); step = 2; stack.options(this, map(anchor2options, anchor2 -> instance.anchor2 = anchor2)); } else if (step == 2) { print("G22MeshMapper_v2 step1: Connecting " + anchor1 + " to " + anchor2); mapAnchor(anchor1, anchor2); step = 3; } else if (step == 3) { stack.call(new Step2); step = 4; } else { if (isTrue(stack.subResult())) step = 3; else stack.return(); } } } class Step2 extends VStackComputableWithStep { bool change; void step(VStack stack) { cast stack to BStack; /* if (step == 0) { for (curve1 : mesh1.curves()) { // skip if curve is already mapped if (mm.isMapped(curve1)) continue with print("Curve is mapped: " + curve1); // check if anchors are mapped Anchor start2 = mm.get(curve1.start); Anchor end2 = mm.get(curve1.end); // If neither anchor is mapped, postpone this curve if (start2 == null && end2 == null) continue with print("Curve is not discovered yet: " + curve1); // Start at the mapped anchor, choose a viable curve in mesh2 to map to bool startAtEnd = end2 != null; Anchor a1other = curve1.anchor(!startAtEnd); Anchor a2 = mm.get(curve1.anchor(startAtEnd)); new L possibleCurves; for (c2 : a2.curves()) { if (mm.isMapped(c2)) continue with print("Curve already mapped: " + c2); // check for arity match Anchor a3 = c2.anchorOpposite(a2); int arity1 = a3.arity(), arity2 = a1other.arity(); if (arity1 != arity2) continue with print("Arity mismatch (" + arity1 + "/" + arity2 + ") for curve " + c2); // This curve is viable as a mapping target possibleCurves.add(c2); } print(l(possibleCurves) + "/" + l(a2.curves()) + " possible curve(s) to map " + curve1 + " to: " + possibleCurves); if (empty(possibleCurves)) ret false with rejectedBecause("Could not map curve " + curve1); // Map the curve Curve c2 = random(possibleCurves); bool flipped = c2.start() != a2; print("Mapping curve " + curve1 + " to " + c2); mm.mapCurve(curve1, c2, flipped); set change; } ret change; */ } } protected void prechecks { set prechecksDone; sig1 = mesh1.signature(); sig2 = mesh1.signature(); if (!eq(sig1, sig2)) ret with rejectedBecause(G22SignatureMismatch(mesh1, mesh2)); } }