"""rwr² — Translate k-OA to k-ORE (Algorithm 3, arXiv 1004.2372). rwr²(G): 1: compute a marking H of G 2: return strip(rwr²₁(H)) """ from .marking import mark_koa from .rwr0 import rwr0 from .grammar import ( Concat, Alt, Plus, Optional, Star, Symbol, Epsilon, Empty, ) def strip(node): """Remove k-ORE markers: Symbol('a_i') → Symbol('a').""" if isinstance(node, Symbol): value = node.value if '_' in value: base = value.rsplit('_', 1)[0] return Symbol(base) return node if isinstance(node, (Epsilon, Empty)): return node if isinstance(node, (Plus, Optional, Star)): return type(node)(strip(node.child)) if isinstance(node, (Concat, Alt)): return type(node)([strip(child) for child in node.parts]) return node def rwr_sq(G): """ |———— Algorithm 3: rwr² ————| Require: k-OA G Ensure: k-ORE r with L(G) ⊆ L(r) 1: H ← marking of G 2: return strip(rwr²₁(H)) """ H = mark_koa(G) result = rwr0(H) if result is None or isinstance(result, Empty): return None return strip(result)