Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add peephole optimization #45

Merged
merged 28 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1565d3d
Add assoc counting script
adrianleh Apr 2, 2024
7d32890
First pass circuit proof from diagrammatic proof
caldwellb Jul 8, 2024
a872c15
Add uc_WT automation
adrianleh Jul 8, 2024
3279ad9
Add uc_WT automation
adrianleh Jul 8, 2024
90501b1
Added notation to make writing lemmas straightforward
caldwellb Jul 9, 2024
eb810e2
Added to automation for converting diagrams, swap flipping
caldwellb Jul 9, 2024
29cb23c
Generalize pi copy
adrianleh Jul 9, 2024
8cf2725
Generalize 2_PI spider rule to ints instead of nats
adrianleh Jul 9, 2024
6b3c364
fig 4 nam
adrianleh Jul 9, 2024
993d80d
fig 5 nam 1,3
adrianleh Jul 9, 2024
5694980
Merge POPL submission
adrianleh Jul 10, 2024
16602ed
Save my sanity by commenting out slow solve_props
adrianleh Jul 10, 2024
eeb540b
Merge remote-tracking branch 'origin/assoc-automation' into circuit-p…
adrianleh Jul 10, 2024
4ff9104
Improve assoc_count.py for paper number generation]
adrianleh Jul 10, 2024
66773f5
Improve assoc_count.py to consider do n (tac) a repeat app
adrianleh Jul 10, 2024
a60b9fa
Improve assoc_count.py to not use ANSI on windows
adrianleh Jul 10, 2024
edb0095
Add basic proofs for peephole
adrianleh Jul 10, 2024
56bc148
Fix h_reduction_{4,5}
adrianleh Jul 10, 2024
12af1f5
Pass at cnot commutation via top_to_bottom_big_yank_l
caldwellb Jul 11, 2024
96c04e4
Add missing changes
adrianleh Jul 11, 2024
fffcd86
Peephole progress
adrianleh Jul 11, 2024
04fabc5
Clean up Nam H proofs by adding `conj_diagrams`
adrianleh Jul 11, 2024
b651411
Add comm_4
adrianleh Jul 11, 2024
23fc883
Add comm_5
adrianleh Jul 11, 2024
658c655
Add comm_6
adrianleh Jul 12, 2024
a0201ce
Refactor: Extract basic rules from peephole, solve cnot admitteds, re…
adrianleh Jul 12, 2024
b66eaff
Force quantumlib to not be 1.5.0
adrianleh Jul 12, 2024
ca2383d
try to pin to qlib 1.3.0
caldwellb Jul 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions .meta/assoc_count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/env python3

import re
import os
import sys
import functools


MIN_PYTHON = (3, 10)
if sys.version_info < MIN_PYTHON:
print(f"Your python version is {sys.version_info.major}.{sys.version_info.minor}. {MIN_PYTHON[0]}.{MIN_PYTHON[1]} is required")
exit(3)


b_color_yellow = '\033[93m'
b_color_cyan = '\033[96m'
b_color_reset = '\033[0m'
b_color_green = '\033[92m'
b_color_red = '\033[91m'

is_windows = sys.platform.startswith('win')
if is_windows: # Disable colors on windows
b_color_yellow = ''
b_color_cyan = ''
b_color_reset = ''
b_color_green = ''
b_color_red = ''
print("Warning: Windows detected. Disabling colored output")

curr_dir = os.path.dirname(os.path.realpath(__file__))
src_dir = f"{curr_dir}/../src"

regex_assoc : list[re.Pattern] = list(map(re.compile, [
r".*rewrite.*assoc",
r".*rewrite.*dist",
r".*rewrite.*mixed_product",
r".*rewrite.*cast",
r".*cleanup_zx",
r".*cast_id",
r".*simpl_cast",
r".*bundle_wires",
r".*restore_dims",
r".*cast_irrelevance",
r".*apply .*_simplify",
r".*rewrite.*stack_empty_.",
r".*rewrite.*n_stack1_",
r".*rewrite.*n_wire_stack",
r".*rewrite.*wire_to_n_wire",
r".*rewrite.*wire_removal_",
r".*rewrite.*(n_wire|nstack1)_split",
]))
proof_regex = re.compile(r'Proof\.((?:(?!Proof\.|Qed\.|Defined\.|Admitted\.|Abort\.)(?!\b(?:Proof|Qed|Defined|Admitted|Abort)\b)[\s\S])*?)(Qed\.|Defined\.|Admitted\.|Abort\.)')
stmt_regex = re.compile(r'(([a-z|A-Z|0-9])+(\t| |[a-z|A-Z|0-9]|.)*)(\t| )*(\n|;|$)')

class Result:
non_assoc : int
assoc : int
repeat_assoc : int

def __init__(self, non_assoc : int = 0, assoc : int = 0, repeat_assoc : int = 0) -> None:
self.non_assoc = non_assoc
self.assoc = assoc
self.repeat_assoc = repeat_assoc


def __add__(self, other):
return Result(self.non_assoc + other.non_assoc, self.assoc + other.assoc, self.repeat_assoc + other.repeat_assoc)

def __iadd__(self, other):
self.assoc += other.assoc
self.non_assoc += other.non_assoc
self.repeat_assoc += other.repeat_assoc
return self

def total_assoc(self) -> int:
return self.assoc + self.repeat_assoc

def total(self) -> int:
return self.total_assoc() + self.non_assoc

def __str__(self) -> str:
return \
f"""{b_color_red}Number of repeated assoc lines:{b_color_reset} {self.repeat_assoc} ({self.repeat_assoc / self.total():.2%}) ({self.repeat_assoc / self.total_assoc():.2%} of all assoc lines)
{b_color_yellow}Number of assoc lines:{b_color_reset} {self.assoc} ({self.assoc / self.total():.2%}) ({self.assoc / self.total_assoc():.2%} of all assoc lines)
{b_color_cyan}Total of any assoc lines:{b_color_reset} {self.total_assoc()} ({self.total_assoc() / self.total():.2%})
{b_color_green}Number of other proof lines:{b_color_reset} {self.non_assoc} ({self.non_assoc / self.total():.2%})
Total lines: {self.total()}
"""

do_regex = re.compile(r'do \d+')


def count_assoc_non_assoc(proof : str, proof_completion : str) -> Result:
if proof_completion != "Qed." and proof_completion != "Defined.":
return Result()
result = Result()
for stmt in stmt_regex.findall(proof):
if any(map(lambda pattern : pattern.match(stmt[0]), regex_assoc)):
if 'repeat' in stmt[0] or do_regex.match(stmt[0]):
result.repeat_assoc += 1
else:
result.assoc += 1
else:
result.non_assoc += 1
return result


def count_assoc_file(file : str) -> tuple[int, int]:
with open(file) as f:
data = f.read()
proofs = proof_regex.findall(data)
result = functools.reduce(lambda curr, proof : count_assoc_non_assoc(proof[0], proof[-1]) + curr , proofs, Result())
return result

result = Result()
for dir, _, files in os.walk(src_dir):
for file in files:
print(f"Checking {dir}/{file}...")
if not file.endswith(".v"): # Make sure we only look at Coq files
continue
result += count_assoc_file(f"{dir}/{file}")

print(result)



2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 INQWIRE
Copyright (c) 2021 REDACTED

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

Verifying the ZX Calculus

[Check out the paper on arxiv](https://arxiv.org/abs/2205.05781)

## Building VyZX

Works with Coq 8.16-8.18.
Expand Down
12 changes: 4 additions & 8 deletions coq-vyzx.opam
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@ opam-version: "2.0"
version: "0.1.0"
synopsis: "Coq library for reasoning about ZX diagrams"
description: """
inQWIRE's QuantumLib is a Coq library for reasoning
about ZX diagrams.
A Coq library for reasoning about ZX diagrams.
"""
maintainer: ["inQWIRE Developers"]
authors: ["inQWIRE"]
maintainer: ["Anonymous"]
authors: ["Anonymous"]
license: "MIT"
homepage: "https://github.com/inQWIRE/VyZX"
bug-reports: "https://github.com/inQWIRE/VyZX/issues"
depends: [
"dune" {>= "2.8"}
"coq-quantumlib" {>= "1.3.0"}
"coq-quantumlib" {= "1.3.0"}
"coq-sqir" {>= "1.3.0"}
"coq-voqc" {>= "1.3.0"}
"coq" {>= "8.16"}
Expand All @@ -33,4 +30,3 @@ build: [
"@doc" {with-doc}
]
]
dev-repo: "git+https://github.com/inQWIRE/VyZX.git"
10 changes: 4 additions & 6 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@
(generate_opam_files true)

(license MIT)
(authors "inQWIRE")
(maintainers "inQWIRE Developers")
(source (github inQWIRE/VyZX))
(authors "Anonymous")
(maintainers "Anonymous")

(package
(name coq-vyzx)
(synopsis "Coq library for reasoning about ZX diagrams")
(description "\| inQWIRE's QuantumLib is a Coq library for reasoning
"\| about ZX diagrams.
(description "\| A Coq library for reasoning about ZX diagrams.
)

(depends
(coq-quantumlib (>= 1.3.0))
(coq-quantumlib (= 1.3.0))
(coq-sqir (>= 1.3.0))
(coq-voqc (>= 1.3.0))
(coq (>= 8.16))))
18 changes: 10 additions & 8 deletions src/CoreData/Proportional.v
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,16 @@ Proof.
assumption.
Qed.

Lemma conjugate_diagrams : forall n m (zx0 zx1 : ZX n m),
zx0 ⊼ ∝ zx1 ⊼ -> zx0 ∝ zx1.
Proof.
intros.
apply adjoint_diagrams.
unfold adjoint.
rewrite H.
easy.
Qed.

Lemma colorswap_adjoint_commute : forall n m (zx : ZX n m),
⊙ (zx †) ∝ (⊙ zx) †.
Proof.
Expand Down Expand Up @@ -395,11 +405,3 @@ Proof.
apply Z_spider_1_1_fusion.
Qed.

Lemma proportional_sound : forall {nIn nOut} (zx0 zx1 : ZX nIn nOut),
zx0 ∝ zx1 -> exists (zxConst : ZX 0 0), ⟦ zx0 ⟧ = ⟦ zxConst ↕ zx1 ⟧.
Proof.
intros.
simpl; unfold proportional, proportional_general in H.
destruct H as [c [H cneq0]].
rewrite H.
Abort.
79 changes: 69 additions & 10 deletions src/CoreRules/CapCupRules.v
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,6 @@ Unshelve.
all: lia.
Qed.

Lemma n_cup_inv_n_swap_n_wire : forall n, n_cup n ∝ n_wire n ↕ n_swap n ⟷ n_cup_unswapped n.
Proof.
intros.
strong induction n.
destruct n; [ | destruct n].
- simpl. rewrite n_cup_0_empty. cleanup_zx. simpl_casts. easy.
- simpl. rewrite n_cup_1_cup. cleanup_zx. simpl_casts. bundle_wires. cleanup_zx. easy.
Admitted. (*TODO*)

Lemma n_cup_unswapped_colorswap : forall n, ⊙ (n_cup_unswapped n) ∝ n_cup_unswapped n.
Proof.
intros.
Expand Down Expand Up @@ -207,4 +198,72 @@ Qed.
(fun n => @n_cap_unswapped_transpose n)
(fun n => @n_cup_transpose n)
(fun n => @n_cap_transpose n)
: transpose_db.
: transpose_db.
Local Open Scope ZX_scope.

Lemma bigyank_cap : forall (zx1 : ZX 1 1),
⊂ ↕ zx1 ∝ — ↕ ⊂ ⟷ top_to_bottom 3 ⟷ (— ↕ — ↕ zx1).
Proof.
intros.
rewrite top_to_bottom_grow_r.
simpl_casts.
rewrite top_to_bottom_2.
repeat rewrite compose_assoc.
rewrite (stack_assoc — —).
zx_simpl.
repeat rewrite ComposeRules.compose_assoc.
rewrite <- (stack_wire_distribute_l ⨉ (— ↕ zx1)).
rewrite <- swap_comm.
rewrite stack_wire_distribute_l.
rewrite <- (ComposeRules.compose_assoc (⨉ ↕ —)).
rewrite (stack_assoc_back — (zx1)).
zx_simpl.
rewrite <- (stack_wire_distribute_r ⨉ (— ↕ zx1)).
rewrite <- swap_comm.
solve_prop 1.
Unshelve.
all: lia.
Qed.

Lemma bigyank_cup : forall (zx1 : ZX 1 1),
top_to_bottom 3 ⟷ (⊃ ↕ zx1) ∝ — ↕ ⊃ ⟷ zx1.
Proof.
intros.
rewrite (stack_empty_r_rev zx1) at 2.
simpl_casts.
rewrite <- (stack_compose_distr — zx1).
cleanup_zx.
rewrite top_to_bottom_grow_l.
cleanup_zx.
rewrite top_to_bottom_2.
rewrite ComposeRules.compose_assoc.
rewrite <- (nwire_removal_l ⊃).
rewrite <- (wire_removal_r zx1).
rewrite (stack_compose_distr).
zx_simpl.
rewrite <- (ComposeRules.compose_assoc (— ↕ ⨉)).
rewrite stack_assoc.
simpl_casts.
rewrite <- stack_wire_distribute_l.
rewrite <- swap_comm.
rewrite stack_wire_distribute_l.
rewrite <- 2 (ComposeRules.compose_assoc (⨉ ↕ —)).
rewrite (stack_assoc_back — zx1 —).
simpl_casts.
rewrite <- (stack_wire_distribute_r (⨉) (— ↕ zx1)).
rewrite <- swap_comm.
zx_simpl.
rewrite stack_wire_distribute_r.
repeat rewrite ComposeRules.compose_assoc.
assert ((⨉ ↕ — ⟷ (— ↕ ⨉ ⟷ (⊃ ↕ —))) ∝ (— ↕ ⊃)) as Hrw. { shelve. }
rewrite Hrw; clear Hrw.
rewrite (stack_assoc zx1).
zx_simpl.
bundle_wires.
rewrite <- (stack_compose_distr zx1 —).
zx_simpl.
easy.
Unshelve.
all: try lia.
solve_prop 1.
Qed.
14 changes: 13 additions & 1 deletion src/CoreRules/CastRules.v
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Proof.
Qed.

Lemma cast_compose_distribute :
forall n n' m o o' prfn prfo (zx0 : ZX n m) (zx1 : ZX m o),
forall {n} n' {m o} o' prfn prfo (zx0 : ZX n m) (zx1 : ZX m o),
cast n' o' prfn prfo (zx0 ⟷ zx1) ∝
cast n' m prfn eq_refl zx0 ⟷ cast m o' eq_refl prfo zx1.
Proof.
Expand All @@ -156,6 +156,18 @@ Proof.
reflexivity.
Qed.

Lemma cast_compose_distribute_general :
forall {n} n' {m} m' {o} o' prfn prfm prfo (zx0 : ZX n m) (zx1 : ZX m o),
cast n' o' prfn prfo (zx0 ⟷ zx1) ∝
cast n' m' prfn prfm zx0 ⟷ cast m' o' prfm prfo zx1.
Proof.
intros.
subst.
simpl_casts.
reflexivity.
Qed.


Lemma cast_compose_l :
forall {n n' m m' o} prfn prfm (zx0 : ZX n m) (zx1 : ZX m' o),
cast n' m' prfn prfm zx0 ⟷ zx1 ∝
Expand Down
2 changes: 1 addition & 1 deletion src/CoreRules/ComposeRules.v
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ Proof.
rewrite n_wire_semantics.
Msimpl.
reflexivity.
Qed.
Qed.
4 changes: 4 additions & 0 deletions src/CoreRules/CoreAutomation.v
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Tactic Notation "bundle_wires" := wire_to_n_wire_safe; (* change wires to n_wire
(fun n m o p => @nwire_stack_compose_topleft n m o p)
(fun n m o p => @nwire_stack_compose_botleft n m o p)
: cleanup_zx_db.
#[export] Hint Rewrite <- nstack1_compose : cleanup_zx_db.
#[export] Hint Rewrite <- nstack_compose : cleanup_zx_db.
Tactic Notation "cleanup_zx" := auto_cast_eqn (autorewrite with cleanup_zx_db).

#[export] Hint Rewrite
Expand All @@ -62,3 +64,5 @@ Tactic Notation "cleanup_zx" := auto_cast_eqn (autorewrite with cleanup_zx_db).
Ltac transpose_of H := intros; apply transpose_diagrams; repeat (simpl; autorewrite with transpose_db); apply H.
Ltac adjoint_of H := intros; apply adjoint_diagrams; repeat (simpl; autorewrite with adjoint_db); apply H.
Ltac colorswap_of H := intros; apply colorswap_diagrams; repeat (simpl; autorewrite with colorswap_db); apply H.

Ltac zx_simpl := simpl; repeat (cleanup_zx; simpl_casts).
Loading
Loading