Last active
January 31, 2026 23:57
-
-
Save LeeeeT/2736ee2b4f3661c0eb1ea4d981dd063c to your computer and use it in GitHub Desktop.
k-SIC + Opportunistic Swap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import itertools | |
| from dataclasses import dataclass | |
| type Name = int | |
| name = itertools.count() | |
| type Label = int | |
| label = itertools.count() | |
| type Pos = Var | Nil | Lam | Sup | Udp | Usl | |
| type Neg = Sub | Era | App | Dup | Usp | Udl | |
| @dataclass(frozen=True) | |
| class Var: | |
| nam: Name | |
| @dataclass(frozen=True) | |
| class Sub: | |
| nam: Name | |
| @dataclass(frozen=True) | |
| class Nil: | |
| pass | |
| @dataclass(frozen=True) | |
| class Era: | |
| pass | |
| @dataclass(frozen=True) | |
| class Lam: | |
| bnd: Name | |
| bod: Name | |
| @dataclass(frozen=True) | |
| class App: | |
| arg: Name | |
| ret: Name | |
| @dataclass(frozen=True) | |
| class Dup: | |
| dpl: Label | |
| dp0: Name | |
| dp1: Name | |
| @dataclass(frozen=True) | |
| class Sup: | |
| spl: Label | |
| sp0: Name | |
| sp1: Name | |
| @dataclass(frozen=True) | |
| class Udp: | |
| udb: Name | |
| @dataclass(frozen=True) | |
| class Usp: | |
| usb: Name | |
| @dataclass(frozen=True) | |
| class Udl: | |
| ud0: Name | |
| ud1: Name | |
| @dataclass(frozen=True) | |
| class Usl: | |
| us0: Name | |
| us1: Name | |
| type Rdx = tuple[Name, Name] | |
| @dataclass(frozen=True) | |
| class Net: | |
| book: set[Rdx] | |
| vars: dict[Name, Pos] | |
| subs: dict[Name, Neg] | |
| def empty_net() -> Net: | |
| return Net(set(), {}, {}) | |
| def var(net: Net, nam: Name) -> Name: | |
| var = next(name) | |
| net.vars[var] = Var(nam) | |
| return var | |
| def sub(net: Net, nam: Name) -> Name: | |
| sub = next(name) | |
| net.subs[sub] = Sub(nam) | |
| return sub | |
| def nil(net: Net) -> Name: | |
| nil = next(name) | |
| net.vars[nil] = Nil() | |
| return nil | |
| def era(net: Net) -> Name: | |
| era = next(name) | |
| net.subs[era] = Era() | |
| return era | |
| def lam(net: Net, bnd: Name, bod: Name) -> Name: | |
| lam = next(name) | |
| net.vars[lam] = Lam(bnd, bod) | |
| return lam | |
| def app(net: Net, arg: Name, ret: Name) -> Name: | |
| app = next(name) | |
| net.subs[app] = App(arg, ret) | |
| return app | |
| def dup(net: Net, dpl: Label, dp0: Name, dp1: Name) -> Name: | |
| dup = next(name) | |
| net.subs[dup] = Dup(dpl, dp0, dp1) | |
| return dup | |
| def sup(net: Net, spl: Label, sp0: Name, sp1: Name) -> Name: | |
| sup = next(name) | |
| net.vars[sup] = Sup(spl, sp0, sp1) | |
| return sup | |
| def udp(net: Net, udb: Name) -> Name: | |
| udp = next(name) | |
| net.vars[udp] = Udp(udb) | |
| return udp | |
| def usp(net: Net, usb: Name) -> Name: | |
| usp = next(name) | |
| net.subs[usp] = Usp(usb) | |
| return usp | |
| def udl(net: Net, ud0: Name, ud1: Name) -> Name: | |
| udl = next(name) | |
| net.subs[udl] = Udl(ud0, ud1) | |
| return udl | |
| def usl(net: Net, us0: Name, us1: Name) -> Name: | |
| usl = next(name) | |
| net.vars[usl] = Usl(us0, us1) | |
| return usl | |
| def wire(net: Net) -> tuple[Name, Name]: | |
| nam = next(name) | |
| return var(net, nam), sub(net, nam) | |
| def show_pos(net: Net, pos: Name) -> str: | |
| match net.vars[pos]: | |
| case Nil(): | |
| return "+_" | |
| case Var(nam) if nam in net.vars: | |
| return show_pos(net, nam) | |
| case Var(nam): | |
| return f"+{nam}" | |
| case Lam(bnd, bod): | |
| return f"+({show_neg(net, bnd)} {show_pos(net, bod)})" | |
| case Sup(spl, sp0, sp1): | |
| return f"+&{spl}{{{show_pos(net, sp0)} {show_pos(net, sp1)}}}" | |
| case Udp(udb): | |
| # return f"+{{{show_pos(net, udb)}}}" | |
| return show_pos(net, udb) | |
| case Usl(us0, us1): | |
| return f"+{{{show_pos(net, us0)} {show_pos(net, us1)}}}" | |
| def show_neg(net: Net, neg: Name) -> str: | |
| match net.subs[neg]: | |
| case Era(): | |
| return "_-" | |
| case Sub(nam) if nam in net.subs: | |
| return show_neg(net, nam) | |
| case Sub(nam): | |
| return f"-{nam}" | |
| case App(arg, ret): | |
| return f"-({show_pos(net, arg)} {show_neg(net, ret)})" | |
| case Dup(dpl, dp0, dp1): | |
| return f"-&{dpl}{{{show_neg(net, dp0)} {show_neg(net, dp1)}}}" | |
| case Usp(usb): | |
| # return f"+{{{show_neg(net, usb)}}}" | |
| return show_neg(net, usb) | |
| case Udl(ud0, ud1): | |
| return f"+{{{show_neg(net, ud0)} {show_neg(net, ud1)}}}" | |
| def reduce(net: Net) -> int: | |
| itrs = 0 | |
| while net.book: | |
| itrs += 1 | |
| lhs, rhs = net.book.pop() | |
| match net.subs.pop(lhs), net.vars.pop(rhs): | |
| case lhsc, Var(nam) if nam in net.vars: | |
| net.subs[lhs] = lhsc | |
| net.book.add((lhs, nam)) | |
| case lhsc, Var(nam): | |
| if isinstance(lhsc, Usp): | |
| net.subs[lhs] = Sub(nam) | |
| net.subs[nam] = lhsc | |
| case Sub(nam), rhsc if nam in net.subs: | |
| net.vars[rhs] = rhsc | |
| net.book.add((nam, rhs)) | |
| case Sub(nam), rhsc: | |
| if isinstance(rhsc, Udp): | |
| net.vars[rhs] = Var(nam) | |
| net.vars[nam] = rhsc | |
| case Usp(usb), Nil(): | |
| net.subs[lhs] = Sub(usb) | |
| case Usp(usb), Usl(us0, us1): | |
| ap, an = wire(net) | |
| net.book.add((usb, usl(net, us0, ap))) | |
| usp0 = usp(net, an) | |
| net.book.add((usp0, us1)) | |
| net.subs[lhs] = Sub(usp0) | |
| case Usp(usb), rhsc: | |
| ap, an = wire(net) | |
| net.vars[rhs] = rhsc | |
| net.book.add((usb, usl(net, rhs, ap))) | |
| net.subs[lhs] = net.subs.pop(an) | |
| case Era(), Udp(udb): | |
| net.vars[rhs] = Var(udb) | |
| case Udl(ud0, ud1), Udp(udb): | |
| ap, an = wire(net) | |
| net.book.add((udl(net, ud0, an), udb)) | |
| udp0 = udp(net, ap) | |
| net.book.add((ud1, udp0)) | |
| net.vars[rhs] = Var(udp0) | |
| case lhsc, Udp(udb): | |
| ap, an = wire(net) | |
| net.subs[lhs] = lhsc | |
| net.book.add((udl(net, lhs, an), udb)) | |
| net.vars[rhs] = net.vars.pop(ap) | |
| case Era(), Nil(): | |
| pass | |
| case Era(), Lam(bnd, bod): | |
| net.book.add((bnd, nil(net))) | |
| net.book.add((era(net), bod)) | |
| case Era(), Sup(spl, sp0, sp1): | |
| net.book.add((era(net), sp0)) | |
| net.book.add((era(net), sp1)) | |
| case Era(), Usl(us0, us1): | |
| net.book.add((era(net), us0)) | |
| net.book.add((era(net), us1)) | |
| case App(arg, ret), Nil(): | |
| net.book.add((era(net), arg)) | |
| net.book.add((ret, nil(net))) | |
| case App(arg, ret), Lam(bnd, bod): | |
| net.book.add((bnd, arg)) | |
| net.book.add((ret, bod)) | |
| case App(arg, ret), Sup(spl, sp0, sp1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| net.book.add((dup(net, spl, an, bn), arg)) | |
| net.book.add((ret, sup(net, spl, cp, dp))) | |
| net.book.add((app(net, ap, cn), sp0)) | |
| net.book.add((app(net, bp, dn), sp1)) | |
| case App(arg, ret), Usl(us0, us1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| udp0 = udp(net, arg) | |
| usp0 = usp(net, ret) | |
| net.book.add((app(net, udp0, usp0), us0)) | |
| net.book.add((app(net, udp0, usp0), us1)) | |
| case Dup(dp0, dp1), Nil(): | |
| net.book.add((dp0, nil(net))) | |
| net.book.add((dp1, nil(net))) | |
| case Dup(dpl, dp0, dp1), Lam(bnd, bod): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| net.book.add((dp0, lam(net, an, bp))) | |
| net.book.add((dp1, lam(net, cn, dp))) | |
| net.book.add((bnd, sup(net, dpl, ap, cp))) | |
| net.book.add((dup(net, dpl, bn, dn), bod)) | |
| case Dup(dpl, dp0, dp1), Sup(spl, sp0, sp1) if dpl == spl: | |
| net.book.add((dp0, sp0)) | |
| net.book.add((dp1, sp1)) | |
| case Dup(dpl, dp0, dp1), Sup(spl, sp0, sp1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| net.book.add((dp0, sup(net, spl, ap, bp))) | |
| net.book.add((dp1, sup(net, spl, cp, dp))) | |
| net.book.add((dup(net, dpl, an, cn), sp0)) | |
| net.book.add((dup(net, dpl, bn, dn), sp1)) | |
| case Dup(dpl, dp0, dp1), Usl(us0, us1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| usp0 = udp(net, dp0) | |
| usp1 = usp(net, dp1) | |
| net.book.add((dup(net, dpl, usp0, usp1), us0)) | |
| net.book.add((dup(net, dpl, usp0, usp1), us1)) | |
| case Udl(ud0, ud1), Nil(): | |
| net.book.add((ud0, nil(net))) | |
| net.book.add((ud1, nil(net))) | |
| case Udl(ud0, ud1), Lam(bnd, bod): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| usp0 = usp(net, bnd) | |
| udp0 = udp(net, bod) | |
| net.book.add((ud0, lam(net, usp0, udp0))) | |
| net.book.add((ud1, lam(net, usp0, udp0))) | |
| case Udl(ud0, ud1), Sup(spl, sp0, sp1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| udp0 = udp(net, sp0) | |
| udp1 = udp(net, sp1) | |
| net.book.add((ud0, sup(net, spl, udp0, udp1))) | |
| net.book.add((ud1, sup(net, spl, udp0, udp1))) | |
| case Udl(ud0, ud1), Usl(us0, us1): | |
| net.book.add((ud0, us0)) | |
| net.book.add((ud1, us1)) | |
| case _: | |
| raise RuntimeError | |
| return itrs | |
| def print_state(net: Net, root: Name, *, heap: bool = False) -> None: | |
| print("ROOT:") | |
| print(f" {show_pos(net, root)}") | |
| print() | |
| print("BOOK:") | |
| for lhs, rhs in net.book: | |
| print(f" {show_neg(net, lhs)} ⋈ {show_pos(net, rhs)}") | |
| if heap: | |
| print() | |
| print("VARS:") | |
| for nam in net.vars: | |
| print(f" {nam} = {show_pos(net, nam)}") | |
| print() | |
| print("SUBS:") | |
| for nam in net.subs: | |
| print(f" {nam} = {show_neg(net, nam)}") | |
| def print_reduction(net: Net, root: Name, *, heap: bool = False) -> None: | |
| print("=" * 30) | |
| print("=", "INITIAL".center(26), "=") | |
| print("=" * 30) | |
| print() | |
| print_state(net, root, heap=heap) | |
| print() | |
| print("=" * 30) | |
| print("=", "NORMALIZED".center(26), "=") | |
| print("=" * 30) | |
| print() | |
| itrs = reduce(net) | |
| print_state(net, root, heap=heap) | |
| print() | |
| print(f"ITRS: {itrs}") | |
| def mk_app(net: Net, fun: Name, arg: Name) -> Name: | |
| rp, rn = wire(net) | |
| net.book.add((app(net, arg, rn), fun)) | |
| return rp | |
| def mk_dup(net: Net, x: Name, lab: Label | None = None) -> tuple[Name, Name]: | |
| if lab is None: | |
| lab = next(label) | |
| x0p, x0n = wire(net) | |
| x1p, x1n = wire(net) | |
| net.book.add((dup(net, lab, x0n, x1n), x)) | |
| return x0p, x1p | |
| def mk_udp(net: Net, x: Name) -> tuple[Name, Name]: | |
| udp0 = udp(net, x) | |
| return udp0, udp0 | |
| def mk_c2(net: Net) -> Name: | |
| f0p, f0n = wire(net) | |
| f1p, f1n = wire(net) | |
| xp, xn = wire(net) | |
| fx = mk_app(net, f1p, xp) | |
| ffx = mk_app(net, f0p, fx) | |
| return lam(net, dup(net, next(label), f0n, f1n), lam(net, xn, ffx)) | |
| def mk_cpow2(net: Net, k: int) -> Name: | |
| # k=1 -> c2, k=2 -> c4, k=3 -> c8, ... | |
| # c_{2^k} = λf. c2 (c_{2^(k-1)} f) | |
| if k < 1: | |
| raise ValueError("k must be >= 1") | |
| if k == 1: | |
| return mk_c2(net) | |
| fp, fn = wire(net) | |
| prev = mk_cpow2(net, k - 1) # c_{2^(k-1)} | |
| prev_f = mk_app(net, prev, fp) # f^(2^(k-1)) | |
| body = mk_app(net, mk_c2(net), prev_f) # square -> f^(2^k) | |
| return lam(net, fn, body) | |
| # λt.λf.t | |
| def mk_true(net: Net) -> Name: | |
| tp, tn = wire(net) | |
| return lam(net, tn, lam(net, era(net), tp)) | |
| # λt.λf.f | |
| def mk_false(net: Net) -> Name: | |
| fp, fn = wire(net) | |
| return lam(net, era(net), lam(net, fn, fp)) | |
| # λb.λt.λf.(b f f) | |
| def mk_clr(net: Net) -> Name: | |
| bp, bn = wire(net) | |
| fp, fn = wire(net) | |
| f0, f1 = mk_udp(net, fp) | |
| return lam(net, bn, lam(net, era(net), lam(net, fn, mk_app(net, mk_app(net, bp, f0), f1)))) | |
| # g = λy.y | |
| # f = λx.(x g g) | |
| # ((f λa.λb.a) (f λc.λd.d)) | |
| def test_jamespayor(net: Net) -> Name: | |
| yp, yn = wire(net) | |
| g0, g1 = mk_udp(net, lam(net, yn, yp)) | |
| xp, xn = wire(net) | |
| f0, f1 = mk_dup(net, lam(net, xn, mk_app(net, mk_app(net, xp, g0), g1))) | |
| ap, an = wire(net) | |
| dp, dn = wire(net) | |
| return mk_app(net, mk_app(net, f0, lam(net, an, lam(net, era(net), ap))), mk_app(net, f1, lam(net, era(net), lam(net, dn, dp)))) | |
| # (clr^N true) | |
| def test_clr_fusion(net: Net, N: int) -> Name: | |
| return mk_app(net, mk_app(net, mk_cpow2(net, N), mk_clr(net)), mk_true(net)) | |
| def main() -> None: | |
| net = empty_net() | |
| # root = test_jamespayor(net) | |
| root = mk_app(net, mk_cpow2(net, 100), mk_clr(net)) | |
| print_reduction(net, root) | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import itertools | |
| from dataclasses import dataclass | |
| type Name = int | |
| name = itertools.count() | |
| type Label = int | |
| label = itertools.count() | |
| type Pos = Var | Lam | Sup | Udp | Usl | |
| type Neg = Sub | App | Dup | Usp | Udl | |
| @dataclass(frozen=True) | |
| class Var: | |
| nam: Name | |
| @dataclass(frozen=True) | |
| class Sub: | |
| nam: Name | |
| @dataclass(frozen=True) | |
| class Lam: | |
| bnd: Name | |
| bod: Name | |
| @dataclass(frozen=True) | |
| class App: | |
| arg: Name | |
| ret: Name | |
| @dataclass(frozen=True) | |
| class Dup: | |
| dpl: Label | |
| dp0: Name | |
| dp1: Name | |
| @dataclass(frozen=True) | |
| class Sup: | |
| spl: Label | |
| sp0: Name | |
| sp1: Name | |
| @dataclass(frozen=True) | |
| class Udp: | |
| udb: Name | |
| @dataclass(frozen=True) | |
| class Usp: | |
| usb: Name | |
| @dataclass(frozen=True) | |
| class Udl: | |
| ud0: Name | |
| ud1: Name | |
| @dataclass(frozen=True) | |
| class Usl: | |
| us0: Name | |
| us1: Name | |
| type Rdx = tuple[Name, Name] | |
| @dataclass(frozen=True) | |
| class Net: | |
| book: set[Rdx] | |
| vars: dict[Name, Pos] | |
| subs: dict[Name, Neg] | |
| def empty_net() -> Net: | |
| return Net(set(), {}, {}) | |
| def var(net: Net, nam: Name) -> Name: | |
| var = next(name) | |
| net.vars[var] = Var(nam) | |
| return var | |
| def sub(net: Net, nam: Name) -> Name: | |
| sub = next(name) | |
| net.subs[sub] = Sub(nam) | |
| return sub | |
| def lam(net: Net, bnd: Name, bod: Name) -> Name: | |
| lam = next(name) | |
| net.vars[lam] = Lam(bnd, bod) | |
| return lam | |
| def app(net: Net, arg: Name, ret: Name) -> Name: | |
| app = next(name) | |
| net.subs[app] = App(arg, ret) | |
| return app | |
| def dup(net: Net, dpl: Label, dp0: Name, dp1: Name) -> Name: | |
| dup = next(name) | |
| net.subs[dup] = Dup(dpl, dp0, dp1) | |
| return dup | |
| def sup(net: Net, spl: Label, sp0: Name, sp1: Name) -> Name: | |
| sup = next(name) | |
| net.vars[sup] = Sup(spl, sp0, sp1) | |
| return sup | |
| def udp(net: Net, udb: Name) -> Name: | |
| udp = next(name) | |
| net.vars[udp] = Udp(udb) | |
| return udp | |
| def usp(net: Net, usb: Name) -> Name: | |
| usp = next(name) | |
| net.subs[usp] = Usp(usb) | |
| return usp | |
| def udl(net: Net, ud0: Name, ud1: Name) -> Name: | |
| udl = next(name) | |
| net.subs[udl] = Udl(ud0, ud1) | |
| return udl | |
| def usl(net: Net, us0: Name, us1: Name) -> Name: | |
| usl = next(name) | |
| net.vars[usl] = Usl(us0, us1) | |
| return usl | |
| def wire(net: Net) -> tuple[Name, Name]: | |
| nam = next(name) | |
| return var(net, nam), sub(net, nam) | |
| def show_pos(net: Net, pos: Name) -> str: | |
| match net.vars.get(pos): | |
| case None: | |
| return "+_" | |
| case Var(nam) if nam in net.vars: | |
| return show_pos(net, nam) | |
| case Var(nam): | |
| return f"+{nam}" | |
| case Lam(bnd, bod): | |
| return f"+({show_neg(net, bnd)} {show_pos(net, bod)})" | |
| case Sup(spl, sp0, sp1): | |
| return f"+&{spl}{{{show_pos(net, sp0)} {show_pos(net, sp1)}}}" | |
| case Udp(udb): | |
| # return f"+{{{show_pos(net, udb)}}}" | |
| return show_pos(net, udb) | |
| case Usl(us0, us1): | |
| return f"+{{{show_pos(net, us0)} {show_pos(net, us1)}}}" | |
| def show_neg(net: Net, neg: Name) -> str: | |
| match net.subs.get(neg): | |
| case None: | |
| return "_-" | |
| case Sub(nam) if nam in net.subs: | |
| return show_neg(net, nam) | |
| case Sub(nam): | |
| return f"-{nam}" | |
| case App(arg, ret): | |
| return f"-({show_pos(net, arg)} {show_neg(net, ret)})" | |
| case Dup(dpl, dp0, dp1): | |
| return f"-&{dpl}{{{show_neg(net, dp0)} {show_neg(net, dp1)}}}" | |
| case Usp(usb): | |
| # return f"+{{{show_neg(net, usb)}}}" | |
| return show_neg(net, usb) | |
| case Udl(ud0, ud1): | |
| return f"+{{{show_neg(net, ud0)} {show_neg(net, ud1)}}}" | |
| def reduce(net: Net) -> int: | |
| itrs = 0 | |
| while net.book: | |
| itrs += 1 | |
| lhs, rhs = net.book.pop() | |
| match net.subs.pop(lhs), net.vars.pop(rhs): | |
| case lhsc, Var(nam) if nam in net.vars: | |
| net.subs[lhs] = lhsc | |
| net.book.add((lhs, nam)) | |
| case lhsc, Var(nam): | |
| if isinstance(lhsc, Usp): | |
| net.subs[lhs] = Sub(nam) | |
| net.subs[nam] = lhsc | |
| case Sub(nam), rhsc if nam in net.subs: | |
| net.vars[rhs] = rhsc | |
| net.book.add((nam, rhs)) | |
| case Sub(nam), rhsc: | |
| if isinstance(rhsc, Udp): | |
| net.vars[rhs] = Var(nam) | |
| net.vars[nam] = rhsc | |
| case Usp(usb), Usl(us0, us1): | |
| ap, an = wire(net) | |
| net.book.add((usb, usl(net, us0, ap))) | |
| usp0 = usp(net, an) | |
| net.book.add((usp0, us1)) | |
| net.subs[lhs] = Sub(usp0) | |
| case Usp(usb), rhsc: | |
| ap, an = wire(net) | |
| net.vars[rhs] = rhsc | |
| net.book.add((usb, usl(net, rhs, ap))) | |
| net.subs[lhs] = net.subs.pop(an) | |
| case Udl(ud0, ud1), Udp(udb): | |
| ap, an = wire(net) | |
| net.book.add((udl(net, ud0, an), udb)) | |
| udp0 = udp(net, ap) | |
| net.book.add((ud1, udp0)) | |
| net.vars[rhs] = Var(udp0) | |
| case lhsc, Udp(udb): | |
| ap, an = wire(net) | |
| net.subs[lhs] = lhsc | |
| net.book.add((udl(net, lhs, an), udb)) | |
| net.vars[rhs] = net.vars.pop(ap) | |
| case App(arg, ret), Lam(bnd, bod): | |
| net.book.add((bnd, arg)) | |
| net.book.add((ret, bod)) | |
| case App(arg, ret), Sup(spl, sp0, sp1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| net.book.add((dup(net, spl, an, bn), arg)) | |
| net.book.add((ret, sup(net, spl, cp, dp))) | |
| net.book.add((app(net, ap, cn), sp0)) | |
| net.book.add((app(net, bp, dn), sp1)) | |
| case App(arg, ret), Usl(us0, us1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| udp0 = udp(net, arg) | |
| usp0 = usp(net, ret) | |
| net.book.add((app(net, udp0, usp0), us0)) | |
| net.book.add((app(net, udp0, usp0), us1)) | |
| case Dup(dpl, dp0, dp1), Lam(bnd, bod): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| net.book.add((dp0, lam(net, an, bp))) | |
| net.book.add((dp1, lam(net, cn, dp))) | |
| net.book.add((bnd, sup(net, dpl, ap, cp))) | |
| net.book.add((dup(net, dpl, bn, dn), bod)) | |
| case Dup(dpl, dp0, dp1), Sup(spl, sp0, sp1) if dpl == spl: | |
| net.book.add((dp0, sp0)) | |
| net.book.add((dp1, sp1)) | |
| case Dup(dpl, dp0, dp1), Sup(spl, sp0, sp1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| net.book.add((dp0, sup(net, spl, ap, bp))) | |
| net.book.add((dp1, sup(net, spl, cp, dp))) | |
| net.book.add((dup(net, dpl, an, cn), sp0)) | |
| net.book.add((dup(net, dpl, bn, dn), sp1)) | |
| case Dup(dpl, dp0, dp1), Usl(us0, us1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| usp0 = udp(net, dp0) | |
| usp1 = usp(net, dp1) | |
| net.book.add((dup(net, dpl, usp0, usp1), us0)) | |
| net.book.add((dup(net, dpl, usp0, usp1), us1)) | |
| case Udl(ud0, ud1), Lam(bnd, bod): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| usp0 = usp(net, bnd) | |
| udp0 = udp(net, bod) | |
| net.book.add((ud0, lam(net, usp0, udp0))) | |
| net.book.add((ud1, lam(net, usp0, udp0))) | |
| case Udl(ud0, ud1), Sup(spl, sp0, sp1): | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| udp0 = udp(net, sp0) | |
| udp1 = udp(net, sp1) | |
| net.book.add((ud0, sup(net, spl, udp0, udp1))) | |
| net.book.add((ud1, sup(net, spl, udp0, udp1))) | |
| case Udl(ud0, ud1), Usl(us0, us1): | |
| net.book.add((ud0, us0)) | |
| net.book.add((ud1, us1)) | |
| return itrs | |
| def print_state(net: Net, root: Name, *, heap: bool = False) -> None: | |
| print("ROOT:") | |
| print(f" {show_pos(net, root)}") | |
| print() | |
| print("BOOK:") | |
| for lhs, rhs in net.book: | |
| print(f" {show_neg(net, lhs)} ⋈ {show_pos(net, rhs)}") | |
| if heap: | |
| print() | |
| print("VARS:") | |
| for nam in net.vars: | |
| print(f" {nam} = {show_pos(net, nam)}") | |
| print() | |
| print("SUBS:") | |
| for nam in net.subs: | |
| print(f" {nam} = {show_neg(net, nam)}") | |
| def print_reduction(net: Net, root: Name, *, heap: bool = False) -> None: | |
| print("=" * 30) | |
| print("=", "INITIAL".center(26), "=") | |
| print("=" * 30) | |
| print() | |
| print_state(net, root, heap=heap) | |
| print() | |
| print("=" * 30) | |
| print("=", "NORMALIZED".center(26), "=") | |
| print("=" * 30) | |
| print() | |
| itrs = reduce(net) | |
| print_state(net, root, heap=heap) | |
| print() | |
| print(f"ITRS: {itrs}") | |
| def mk_app(net: Net, fun: Name, arg: Name) -> Name: | |
| rp, rn = wire(net) | |
| net.book.add((app(net, arg, rn), fun)) | |
| return rp | |
| def mk_dup(net: Net, x: Name, lab: Label | None = None) -> tuple[Name, Name]: | |
| if lab is None: | |
| lab = next(label) | |
| x0p, x0n = wire(net) | |
| x1p, x1n = wire(net) | |
| net.book.add((dup(net, lab, x0n, x1n), x)) | |
| return x0p, x1p | |
| def mk_udp(net: Net, x: Name) -> tuple[Name, Name]: | |
| udp0 = udp(net, x) | |
| return udp0, udp0 | |
| def mk_c2(net: Net) -> Name: | |
| f0p, f0n = wire(net) | |
| f1p, f1n = wire(net) | |
| xp, xn = wire(net) | |
| fx = mk_app(net, f1p, xp) | |
| ffx = mk_app(net, f0p, fx) | |
| return lam(net, dup(net, next(label), f0n, f1n), lam(net, xn, ffx)) | |
| def mk_cpow2(net: Net, k: int) -> Name: | |
| # k=1 -> c2, k=2 -> c4, k=3 -> c8, ... | |
| # c_{2^k} = λf. c2 (c_{2^(k-1)} f) | |
| if k < 1: | |
| raise ValueError("k must be >= 1") | |
| if k == 1: | |
| return mk_c2(net) | |
| fp, fn = wire(net) | |
| prev = mk_cpow2(net, k - 1) # c_{2^(k-1)} | |
| prev_f = mk_app(net, prev, fp) # f^(2^(k-1)) | |
| body = mk_app(net, mk_c2(net), prev_f) # square -> f^(2^k) | |
| return lam(net, fn, body) | |
| # λt.λf.t | |
| def mk_true(net: Net) -> Name: | |
| tp, tn = wire(net) | |
| fp, fn = wire(net) | |
| return lam(net, tn, lam(net, fn, tp)) | |
| # λt.λf.f | |
| def mk_false(net: Net) -> Name: | |
| tp, tn = wire(net) | |
| fp, fn = wire(net) | |
| return lam(net, tn, lam(net, fn, fp)) | |
| # λb.λt.λf.(b f f) | |
| def mk_clr(net: Net) -> Name: | |
| bp, bn = wire(net) | |
| tp, tn = wire(net) | |
| fp, fn = wire(net) | |
| f0, f1 = mk_udp(net, fp) | |
| return lam(net, bn, lam(net, tn, lam(net, fn, mk_app(net, mk_app(net, bp, f0), f1)))) | |
| # g = λy.y | |
| # f = λx.(x g g) | |
| # ((f λa.λb.a) (f λc.λd.d)) | |
| def test_jamespayor(net: Net) -> Name: | |
| yp, yn = wire(net) | |
| g0, g1 = mk_udp(net, lam(net, yn, yp)) | |
| xp, xn = wire(net) | |
| f0, f1 = mk_dup(net, lam(net, xn, mk_app(net, mk_app(net, xp, g0), g1))) | |
| ap, an = wire(net) | |
| bp, bn = wire(net) | |
| cp, cn = wire(net) | |
| dp, dn = wire(net) | |
| return mk_app(net, mk_app(net, f0, lam(net, an, lam(net, bn, ap))), mk_app(net, f1, lam(net, cn, lam(net, dn, dp)))) | |
| # (clr^N true) | |
| def test_clr_fusion(net: Net, N: int) -> Name: | |
| return mk_app(net, mk_app(net, mk_cpow2(net, N), mk_clr(net)), mk_true(net)) | |
| def main() -> None: | |
| net = empty_net() | |
| # root = test_jamespayor(net) | |
| root = test_clr_fusion(net, 100) | |
| print_reduction(net, root) | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment