Module Argument.
Definition bullet := var 0.
(* encodes symbol true *)
Definition b2 := (arr bullet bullet).
(* encodes symbol false *)
Definition b3 := arr bullet (arr bullet bullet).
Fixpoint append_word (s: formula) (v: list bool) :=
match v with
| [] => s
| a :: v =>
if a then
append_word (arr b2 s) v else
append_word (arr b3 s) v
end.
Definition encode_word (v: list bool) := append_word bullet v.
Definition encode_pair (s t: formula) := arr b3 (arr s (arr t b3)).
Local Notation "⟨ s , t ⟩" := (encode_pair s t).
Local Notation "⟦ v ⟧" := (encode_word v).
Local Notation "s → t" := (arr s t) (at level 50).
(* environment encoding the instance ((v, w), P) of BMPCP *)
Definition Γ v w P :=
(encode_pair (var 1) (var 1)) ::
(arr (encode_pair (encode_word v) (encode_word w)) a_b_a) ::
map (fun '(v, w) => arr (encode_pair (append_word (var 2) v) (append_word (var 3) w)) (encode_pair (var 2) (var 3))) ((v, w) :: P).
Definition encode_bool b := if b then b2 else b3.
Fixpoint encode_list {X: Type} (encode_X: X -> formula) (A: list X) : formula :=
match A with
| [] => bullet
| a :: A => encode_pair (encode_X a) (encode_list encode_X A)
end.
Fixpoint encode_word' (s: formula) (v: list bool) :=
match v with
| [] => s
| a :: v => encode_word' (encode_pair s (if a then b2 else b3)) v
end.
Definition encode_word_pair '(x, y) := encode_pair (encode_list encode_bool x) (encode_list encode_bool y).
(* formula encoding the given PCP instance *)
Definition PCPf P x y :=
encode_pair
(encode_pair (encode_list encode_word_pair P) (encode_list encode_word_pair P))
(encode_pair (encode_pair (encode_word' bullet x) bullet) (encode_pair (encode_word' bullet y) bullet)).
Definition PCPf' Q P s t :=
encode_pair
(encode_pair (encode_list encode_word_pair Q) (encode_list encode_word_pair P))
(encode_pair s t).

(* if the formula (PCPf ((v, w) :: P) v w) is derivable from ΓPCP, then BMPCP has a solution *)
Lemma ΓPCP_completeness {v w P} : hsc ΓPCP (PCPf ((v, w) :: P) v w) -> MPCPb ((v, w), P).