-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathDeutsch_Jozsa.thy
1780 lines (1649 loc) · 91.8 KB
/
Deutsch_Jozsa.thy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(*
Authors:
Hanna Lachnitt, TU Wien, lachnitt@student.tuwien.ac.at
Anthony Bordg, University of Cambridge, apdb3@cam.ac.uk
*)
theory Deutsch_Jozsa
imports
Deutsch
More_Tensor
Binary_Nat
begin
section \<open>The Deutsch-Jozsa Algorithm\<close>
text \<open>
Given a function $f:{0,1}^n \mapsto {0,1}$, the Deutsch-Jozsa algorithm decides if this function is
constant or balanced with a single $f(x)$ circuit to evaluate the function for multiple values of $x$
simultaneously. The algorithm makes use of quantum parallelism and quantum interference.
\<close>
subsection \<open>Input function\<close>
text \<open>
A constant function with values in {0,1} returns either always 0 or always 1.
A balanced function is 0 for half of the inputs and 1 for the other half.
\<close>
locale bob_fun =
fixes f:: "nat \<Rightarrow> nat" and n:: "nat"
assumes dom: "f \<in> ({(i::nat). i < 2^n} \<rightarrow>\<^sub>E {0,1})"
assumes dim: "n \<ge> 1"
context bob_fun
begin
definition const:: "nat \<Rightarrow> bool" where
"const c = (\<forall>x\<in>{i::nat. i<2^n}. f x = c)"
definition is_const:: bool where
"is_const \<equiv> const 0 \<or> const 1"
definition is_balanced:: bool where
"is_balanced \<equiv> \<exists>A B ::nat set. A \<subseteq> {i::nat. i < 2^n} \<and> B \<subseteq> {i::nat. i < 2^n}
\<and> card A = 2^(n-1) \<and> card B = 2^(n-1)
\<and> (\<forall>x\<in>A. f x = 0) \<and> (\<forall>x\<in>B. f x = 1)"
lemma is_balanced_inter:
fixes A B:: "nat set"
assumes "\<forall>x \<in> A. f x = 0" and "\<forall>x \<in> B. f x = 1"
shows "A \<inter> B = {}"
using assms by auto
lemma is_balanced_union:
fixes A B:: "nat set"
assumes "A \<subseteq> {i::nat. i < 2^n}" and "B \<subseteq> {i::nat. i < 2^n}"
and "card A = 2^(n-1)" and "card B = 2^(n-1)"
and "A \<inter> B = {}"
shows "A \<union> B = {i::nat. i < 2^n}"
proof-
have "finite A" and "finite B"
apply (simp add: assms(3) card_ge_0_finite)
apply (simp add: assms(4) card_ge_0_finite).
then have "card(A \<union> B) = 2 * 2^(n-1)"
using assms(3-5) by (simp add: card_Un_disjoint)
then have "card(A \<union> B) = 2^n"
by (metis Nat.nat.simps(3) One_nat_def dim le_0_eq power_eq_if)
moreover have "\<dots> = card({i::nat. i < 2^n})" by simp
moreover have "A \<union> B \<subseteq> {i::nat. i < 2^n}"
using assms(1,2) by simp
moreover have "finite ({i::nat. i < 2^n})" by simp
ultimately show ?thesis
using card_subset_eq[of "{i::nat. i < 2^n}" "A \<union> B"] by simp
qed
lemma f_ge_0: "\<forall>x. f x \<ge> 0" by simp
lemma f_dom_not_zero:
shows "f \<in> ({i::nat. n \<ge> 1 \<and> i < 2^n} \<rightarrow>\<^sub>E {0,1})"
using dim dom by simp
lemma f_values: "\<forall>x \<in> {(i::nat). i < 2^n} . f x = 0 \<or> f x = 1"
using dom by auto
end (* bob_fun *)
text \<open>The input function has to be constant or balanced.\<close>
locale jozsa = bob_fun +
assumes const_or_balanced: "is_const \<or> is_balanced "
text \<open>
Introduce two customised rules: disjunctions with four disjuncts and induction starting from one
instead of zero.
\<close>
(* To deal with Uf it is often necessary to do a case distinction with four different cases.*)
lemma disj_four_cases:
assumes "A \<or> B \<or> C \<or> D" and "A \<Longrightarrow> P" and "B \<Longrightarrow> P" and "C \<Longrightarrow> P" and "D \<Longrightarrow> P"
shows "P"
using assms by auto
text \<open>The unitary transform @{term U\<^sub>f}.\<close>
definition (in jozsa) jozsa_transform:: "complex Matrix.mat" ("U\<^sub>f") where
"U\<^sub>f \<equiv> Matrix.mat (2^(n+1)) (2^(n+1)) (\<lambda>(i,j).
if i = j then (1-f(i div 2)) else
if i = j + 1 \<and> odd i then f(i div 2) else
if i = j - 1 \<and> even i \<and> j\<ge>1 then f(i div 2) else 0)"
lemma (in jozsa) jozsa_transform_dim [simp]:
shows "dim_row U\<^sub>f = 2^(n+1)" and "dim_col U\<^sub>f = 2^(n+1)"
by (auto simp add: jozsa_transform_def)
lemma (in jozsa) jozsa_transform_coeff_is_zero [simp]:
assumes "i < dim_row U\<^sub>f \<and> j < dim_col U\<^sub>f"
shows "(i\<noteq>j \<and> \<not>(i=j+1 \<and> odd i) \<and> \<not> (i=j-1 \<and> even i \<and> j\<ge>1)) \<longrightarrow> U\<^sub>f $$ (i,j) = 0"
using jozsa_transform_def assms by auto
lemma (in jozsa) jozsa_transform_coeff [simp]:
assumes "i < dim_row U\<^sub>f \<and> j < dim_col U\<^sub>f"
shows "i = j \<longrightarrow> U\<^sub>f $$ (i,j) = 1 - f (i div 2)"
and "i = j + 1 \<and> odd i \<longrightarrow> U\<^sub>f $$ (i,j) = f (i div 2)"
and "j \<ge> 1 \<and> i = j - 1 \<and> even i \<longrightarrow> U\<^sub>f $$ (i,j) = f (i div 2)"
using jozsa_transform_def assms by auto
lemma (in jozsa) U\<^sub>f_mult_without_empty_summands_sum_even:
fixes i j A
assumes "i < dim_row U\<^sub>f" and "j < dim_col A" and "even i" and "dim_col U\<^sub>f = dim_row A"
shows "(\<Sum>k\<in>{0..< dim_row A}. U\<^sub>f $$ (i,k) * A $$ (k,j)) =(\<Sum>k\<in>{i,i+1}. U\<^sub>f $$ (i,k) * A $$ (k,j))"
proof-
have "(\<Sum>k \<in> {0..< 2^(n+1)}. U\<^sub>f $$ (i,k) * A $$ (k,j)) =
(\<Sum>k \<in> {0..<i}. U\<^sub>f $$ (i,k) * A $$ (k,j)) +
(\<Sum>k \<in> {i,i+1}. U\<^sub>f $$ (i,k) * A $$ (k,j)) +
(\<Sum>k \<in> {(i+2)..< 2^(n+1)}. U\<^sub>f $$ (i,k) * A $$ (k,j))"
proof-
have "{0..< 2^(n+1)} = {0..<i} \<union> {i..< 2^(n+1)}
\<and> {i..< 2^(n+1)} = {i,i+1} \<union> {(i+2)..<2^(n+1)}" using assms(1-3) by auto
moreover have "{0..<i} \<inter> {i,i+1} = {}
\<and> {i,i+1} \<inter> {(i+2)..< 2^(n+1)} = {}
\<and> {0..<i} \<inter> {(i+2)..< 2^(n+1)} = {}" using assms by simp
ultimately show ?thesis
using sum.union_disjoint
by (metis (no_types, lifting) finite_Un finite_atLeastLessThan is_num_normalize(1) ivl_disj_int_two(3))
qed
moreover have "(\<Sum>k \<in> {0..<i}. U\<^sub>f $$ (i,k) * A $$ (k,j)) = 0"
proof-
have "k \<in> {0..<i} \<longrightarrow> (i\<noteq>k \<and> \<not>(i=k+1 \<and> odd i) \<and> \<not> (i=k-1 \<and> even i \<and> k\<ge>1))" for k
using assms by auto
then have "k \<in> {0..<i} \<longrightarrow> U\<^sub>f $$ (i,k) = 0" for k
using assms(1) by auto
then show ?thesis by simp
qed
moreover have "(\<Sum>k \<in> {(i+2)..< 2^(n+1)}. U\<^sub>f $$ (i,k) * A $$ (k,j)) = 0"
proof-
have "k\<in>{(i+2)..< 2^(n+1)} \<longrightarrow> (i\<noteq>k \<and> \<not>(i=k+1 \<and> odd i) \<and> \<not> (i=k-1 \<and> even i \<and> k\<ge>1))" for k by auto
then have "k \<in> {(i+2)..< 2^(n+1)}\<longrightarrow> U\<^sub>f $$ (i,k) = 0" for k
using assms(1) by auto
then show ?thesis by simp
qed
moreover have "dim_row A = 2^(n+1)" using assms(4) by simp
ultimately show "?thesis" by(metis (no_types, lifting) add.left_neutral add.right_neutral)
qed
lemma (in jozsa) U\<^sub>f_mult_without_empty_summands_even:
fixes i j A
assumes "i < dim_row U\<^sub>f" and "j < dim_col A" and "even i" and "dim_col U\<^sub>f = dim_row A"
shows "(U\<^sub>f * A) $$ (i,j) = (\<Sum>k \<in> {i,i+1}. U\<^sub>f $$ (i,k) * A $$ (k,j))"
proof-
have "(U\<^sub>f * A) $$ (i,j) = (\<Sum> k\<in>{0..< dim_row A}. (U\<^sub>f $$ (i,k)) * (A $$ (k,j)))"
using assms(1,2,4) index_matrix_prod by (simp add: atLeast0LessThan)
then show ?thesis
using assms U\<^sub>f_mult_without_empty_summands_sum_even by simp
qed
lemma (in jozsa) U\<^sub>f_mult_without_empty_summands_sum_odd:
fixes i j A
assumes "i < dim_row U\<^sub>f" and "j < dim_col A" and "odd i" and "dim_col U\<^sub>f = dim_row A"
shows "(\<Sum>k\<in>{0..< dim_row A}. U\<^sub>f $$ (i,k) * A $$ (k,j)) =(\<Sum>k\<in>{i-1,i}. U\<^sub>f $$ (i,k) * A $$ (k,j))"
proof-
have "(\<Sum>k\<in>{0..< 2^(n+1)}. U\<^sub>f $$ (i,k) * A $$ (k,j)) =
(\<Sum>k \<in> {0..<i-1}. U\<^sub>f $$ (i,k) * A $$ (k,j)) +
(\<Sum>k \<in> {i-1,i}. U\<^sub>f $$ (i,k) * A $$ (k,j)) +
(\<Sum>k \<in> {i+1..< 2^(n+1)}. U\<^sub>f $$ (i,k) * A $$ (k,j))"
proof-
have "{0..< 2^(n+1)} = {0..<i-1} \<union> {i-1..< 2^(n+1)}
\<and> {i-1..< 2^(n+1)} = {i-1,i} \<union> {i+1..<2^(n+1)}" using assms(1-3) by auto
moreover have "{0..<i-1} \<inter> {i-1,i} = {}
\<and> {i-1,i} \<inter> {i+1..< 2^(n+1)} = {}
\<and> {0..<i-1} \<inter> {i+1..< 2^(n+1)} = {}" using assms by simp
ultimately show ?thesis
using sum.union_disjoint
by(metis (no_types, lifting) finite_Un finite_atLeastLessThan is_num_normalize(1) ivl_disj_int_two(3))
qed
moreover have "(\<Sum>k \<in> {0..<i-1}. U\<^sub>f $$ (i,k) * A $$ (k,j)) = 0"
proof-
have "k \<in> {0..<i-1} \<longrightarrow> (i\<noteq>k \<and> \<not>(i=k+1 \<and> odd i) \<and> \<not> (i=k-1 \<and> even i \<and> k\<ge>1))" for k by auto
then have "k \<in> {0..<i-1} \<longrightarrow> U\<^sub>f $$ (i,k) = 0" for k
using assms(1) by auto
then show ?thesis by simp
qed
moreover have "(\<Sum>k \<in> {i+1..< 2^(n+1)}. U\<^sub>f $$ (i,k) * A $$ (k,j)) = 0"
using assms(3) by auto
moreover have "dim_row A = 2^(n+1)" using assms(4) by simp
ultimately show "?thesis" by(metis (no_types, lifting) add.left_neutral add.right_neutral)
qed
lemma (in jozsa) U\<^sub>f_mult_without_empty_summands_odd:
fixes i j A
assumes "i < dim_row U\<^sub>f" and "j < dim_col A" and "odd i" and "dim_col U\<^sub>f = dim_row A"
shows "(U\<^sub>f * A) $$ (i,j) = (\<Sum>k \<in> {i-1,i}. U\<^sub>f $$ (i,k) * A $$ (k,j)) "
proof-
have "(U\<^sub>f * A) $$ (i,j) = (\<Sum>k \<in> {0 ..< dim_row A}. (U\<^sub>f $$ (i,k)) * (A $$ (k,j)))"
using assms(1,2,4) index_matrix_prod by (simp add: atLeast0LessThan)
then show "?thesis"
using assms U\<^sub>f_mult_without_empty_summands_sum_odd by auto
qed
text \<open>@{term U\<^sub>f} is a gate.\<close>
lemma (in jozsa) transpose_of_jozsa_transform:
shows "(U\<^sub>f)\<^sup>t = U\<^sub>f"
proof
show "dim_row (U\<^sub>f\<^sup>t) = dim_row U\<^sub>f" by simp
next
show "dim_col (U\<^sub>f\<^sup>t) = dim_col U\<^sub>f" by simp
next
fix i j:: nat
assume a0: "i < dim_row U\<^sub>f" and a1: "j < dim_col U\<^sub>f"
then show "U\<^sub>f\<^sup>t $$ (i, j) = U\<^sub>f $$ (i, j)"
proof (induct rule: disj_four_cases)
show "i=j \<or> (i=j+1 \<and> odd i) \<or> (i=j-1 \<and> even i \<and> j\<ge>1) \<or> (i\<noteq>j \<and> \<not>(i=j+1 \<and> odd i) \<and> \<not> (i=j-1 \<and> even i \<and> j\<ge>1))"
by linarith
next
assume "i = j"
then show "U\<^sub>f\<^sup>t $$ (i,j) = U\<^sub>f $$ (i,j)" using a0 by simp
next
assume "(i=j+1 \<and> odd i)"
then show "U\<^sub>f\<^sup>t $$ (i,j) = U\<^sub>f $$ (i,j)" using transpose_mat_def a0 a1 by auto
next
assume a2:"(i=j-1 \<and> even i \<and> j\<ge>1)"
then have "U\<^sub>f $$ (i,j) = f (i div 2)"
using a0 a1 jozsa_transform_coeff by auto
moreover have "U\<^sub>f $$ (j,i) = f (i div 2)"
using a0 a1 a2 jozsa_transform_coeff
by (metis add_diff_assoc2 diff_add_inverse2 even_plus_one_iff even_succ_div_two jozsa_transform_dim)
ultimately show "?thesis"
using transpose_mat_def a0 a1 by simp
next
assume a2:"(i\<noteq>j \<and> \<not>(i=j+1 \<and> odd i) \<and> \<not> (i=j-1 \<and> even i \<and> j\<ge>1))"
then have "(j\<noteq>i \<and> \<not>(j=i+1 \<and> odd j) \<and> \<not> (j=i-1 \<and> even j \<and> i\<ge>1))"
by (metis le_imp_diff_is_add diff_add_inverse even_plus_one_iff le_add1)
then have "U\<^sub>f $$ (j,i) = 0"
using jozsa_transform_coeff_is_zero a0 a1 by auto
moreover have "U\<^sub>f $$ (i,j) = 0"
using jozsa_transform_coeff_is_zero a0 a1 a2 by auto
ultimately show "U\<^sub>f\<^sup>t $$ (i,j) = U\<^sub>f $$ (i,j)"
using transpose_mat_def a0 a1 by simp
qed
qed
lemma (in jozsa) adjoint_of_jozsa_transform:
shows "(U\<^sub>f)\<^sup>\<dagger> = U\<^sub>f"
proof
show "dim_row (U\<^sub>f\<^sup>\<dagger>) = dim_row U\<^sub>f" by simp
next
show "dim_col (U\<^sub>f\<^sup>\<dagger>) = dim_col U\<^sub>f" by simp
next
fix i j:: nat
assume a0: "i < dim_row U\<^sub>f" and a1: "j < dim_col U\<^sub>f"
then show "U\<^sub>f\<^sup>\<dagger> $$ (i,j) = U\<^sub>f $$ (i,j)"
proof (induct rule: disj_four_cases)
show "i=j \<or> (i=j+1 \<and> odd i) \<or> (i=j-1 \<and> even i \<and> j\<ge>1) \<or> (i\<noteq>j \<and> \<not>(i=j+1 \<and> odd i) \<and> \<not> (i=j-1 \<and> even i \<and> j\<ge>1))"
by linarith
next
assume "i=j"
then show "U\<^sub>f\<^sup>\<dagger> $$ (i,j) = U\<^sub>f $$ (i,j)" using a0 dagger_def by simp
next
assume "(i=j+1 \<and> odd i)"
then show "U\<^sub>f\<^sup>\<dagger> $$ (i,j) = U\<^sub>f $$ (i,j)" using a0 dagger_def by auto
next
assume a2:"(i=j-1 \<and> even i \<and> j\<ge>1)"
then have "U\<^sub>f $$ (i,j) = f (i div 2)"
using a0 a1 jozsa_transform_coeff by auto
moreover have "U\<^sub>f\<^sup>\<dagger> $$ (j,i) = f (i div 2)"
using a1 a2 jozsa_transform_coeff dagger_def by auto
ultimately show "U\<^sub>f\<^sup>\<dagger> $$ (i,j) = U\<^sub>f $$ (i,j)"
by(metis a0 a1 cnj_transpose_is_dagger dim_row_of_dagger index_transpose_mat dagger_of_transpose_is_cnj transpose_of_jozsa_transform)
next
assume a2: "(i\<noteq>j \<and> \<not>(i=j+1 \<and> odd i) \<and> \<not> (i=j-1 \<and> even i \<and> j\<ge>1))"
then have f0:"(i\<noteq>j \<and> \<not>(j=i+1 \<and> odd j) \<and> \<not> (j=i-1 \<and> even j \<and> i\<ge>1))"
by (metis le_imp_diff_is_add diff_add_inverse even_plus_one_iff le_add1)
then have "U\<^sub>f $$ (j,i) = 0" and "cnj 0 = 0"
using jozsa_transform_coeff_is_zero a0 a1 a2 by auto
then have "U\<^sub>f\<^sup>\<dagger> $$ (i,j) = 0"
using a0 a1 dagger_def by simp
then show "U\<^sub>f\<^sup>\<dagger> $$ (i, j) = U\<^sub>f $$ (i, j)"
using a0 a1 a2 jozsa_transform_coeff_is_zero by auto
qed
qed
lemma (in jozsa) jozsa_transform_is_unitary_index_even:
fixes i j:: nat
assumes "i < dim_row U\<^sub>f" and "j < dim_col U\<^sub>f" and "even i"
shows "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
proof-
have "(U\<^sub>f * U\<^sub>f) $$ (i,j) = (\<Sum>k \<in> {i,i+1}. U\<^sub>f $$ (i,k) * U\<^sub>f $$ (k,j)) "
using U\<^sub>f_mult_without_empty_summands_even[of i j U\<^sub>f ] assms by simp
moreover have "U\<^sub>f $$ (i,i) * U\<^sub>f $$ (i,j) = (1-f(i div 2)) * U\<^sub>f $$ (i,j)"
using assms(1,3) by simp
moreover have f0: "U\<^sub>f $$ (i,i+1) * U\<^sub>f $$ (i+1,j) = f(i div 2) * U\<^sub>f $$ (i+1,j)"
by (metis One_nat_def Suc_leI add.right_neutral add_Suc_right assms(1) assms(3) diff_add_inverse2
even_add even_mult_iff jozsa_transform_coeff(3) jozsa_transform_dim le_add2 le_eq_less_or_eq odd_one
one_add_one power.simps(2))
ultimately have f1: "(U\<^sub>f * U\<^sub>f) $$ (i,j) = (1-f(i div 2)) * U\<^sub>f $$ (i,j) + f(i div 2) * U\<^sub>f $$ (i+1,j)" by auto
thus ?thesis
proof (induct rule: disj_four_cases)
show "j=i \<or> (j=i+1 \<and> odd j) \<or> (j=i-1 \<and> even j \<and> i\<ge>1) \<or> (j\<noteq>i \<and> \<not>(j=i+1 \<and> odd j) \<and> \<not> (j=i-1 \<and> even j \<and> i\<ge>1))"
by linarith
next
assume a0:"j=i"
then have "U\<^sub>f $$ (i,j) = (1-f(i div 2))"
using assms(1,2) a0 by simp
moreover have "U\<^sub>f $$ (i+1,j) = f(i div 2)"
using assms(1,3) a0 by auto
ultimately have "(U\<^sub>f * U\<^sub>f) $$ (i,j) = (1-f(i div 2)) * (1-f(i div 2)) + f(i div 2) * f(i div 2)"
using f1 by simp
moreover have "(1-f(i div 2)) * (1-f(i div 2)) + f(i div 2) * f(i div 2) = 1"
using f_values assms(1)
by (metis (no_types, lifting) Nat.minus_nat.diff_0 diff_add_0 diff_add_inverse jozsa_transform_dim(1)
less_power_add_imp_div_less mem_Collect_eq mult_eq_if one_power2 power2_eq_square power_one_right)
ultimately show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)" by(metis assms(2) a0 index_one_mat(1) of_nat_1)
next
assume a0: "(j=i+1 \<and> odd j)"
then have "U\<^sub>f $$ (i,j) = f(i div 2)"
using assms(1,2) a0 by simp
moreover have "U\<^sub>f $$ (i+1,j) = (1-f(i div 2))"
using assms(2,3) a0 by simp
ultimately have "(U\<^sub>f * U\<^sub>f) $$ (i,j) = (1-f(i div 2)) * f(i div 2) + f(i div 2) * (1-f(i div 2))"
using f0 f1 assms by simp
then show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
using assms(1,2) a0 by auto
next
assume "(j=i-1 \<and> even j \<and> i\<ge>1)"
then show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
using assms(3) dvd_diffD1 odd_one by blast
next
assume a0:"(j\<noteq>i \<and> \<not>(j=i+1 \<and> odd j) \<and> \<not> (j=i-1 \<and> even j \<and> i\<ge>1))"
then have "U\<^sub>f $$ (i,j) = 0"
using assms(1,2) by(metis index_transpose_mat(1) jozsa_transform_coeff_is_zero jozsa_transform_dim transpose_of_jozsa_transform)
moreover have "U\<^sub>f $$ (i+1,j) = 0"
using assms a0 by auto
ultimately have "(U\<^sub>f * U\<^sub>f) $$ (i,j) = (1-f(i div 2)) * 0 + f(i div 2) * 0"
by (simp add: f1)
then show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
using a0 assms(1,2) by(metis add.left_neutral index_one_mat(1) jozsa_transform_dim mult_0_right of_nat_0)
qed
qed
lemma (in jozsa) jozsa_transform_is_unitary_index_odd:
fixes i j:: nat
assumes "i < dim_row U\<^sub>f" and "j < dim_col U\<^sub>f" and "odd i"
shows "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
proof-
have f0: "i \<ge> 1"
using linorder_not_less assms(3) by auto
have "(U\<^sub>f * U\<^sub>f) $$ (i,j) = (\<Sum>k \<in> {i-1,i}. U\<^sub>f $$ (i,k) * U\<^sub>f $$ (k,j)) "
using U\<^sub>f_mult_without_empty_summands_odd[of i j U\<^sub>f ] assms by simp
moreover have "(\<Sum>k \<in> {i-1,i}. U\<^sub>f $$ (i,k) * U\<^sub>f $$ (k,j))
= U\<^sub>f $$ (i,i-1) * U\<^sub>f $$ (i-1,j) + U\<^sub>f $$ (i,i) * U\<^sub>f $$ (i,j)"
using f0 by simp
moreover have "U\<^sub>f $$ (i,i) * U\<^sub>f $$ (i,j) = (1-f(i div 2)) * U\<^sub>f $$ (i,j)"
using assms(1,2) by simp
moreover have f1: "U\<^sub>f $$ (i,i-1) * U\<^sub>f $$ (i-1,j) = f(i div 2) * U\<^sub>f $$ (i-1,j)"
using assms(1) assms(3) by simp
ultimately have f2: "(U\<^sub>f * U\<^sub>f) $$ (i,j) = f(i div 2) * U\<^sub>f $$ (i-1,j) + (1-f(i div 2)) * U\<^sub>f $$ (i,j)" by simp
then show "?thesis"
proof (induct rule: disj_four_cases)
show "j=i \<or> (j=i+1 \<and> odd j) \<or> (j=i-1 \<and> even j \<and> i\<ge>1) \<or> (j\<noteq>i \<and> \<not>(j=i+1 \<and> odd j) \<and> \<not> (j=i-1 \<and> even j \<and> i\<ge>1))"
by linarith
next
assume a0:"j=i"
then have "U\<^sub>f $$ (i,j) = (1-f(i div 2))"
using assms(1,2) by simp
moreover have "U\<^sub>f $$ (i-1,j) = f(i div 2)"
using a0 assms
by (metis index_transpose_mat(1) jozsa_transform_coeff(2) less_imp_diff_less odd_two_times_div_two_nat
odd_two_times_div_two_succ transpose_of_jozsa_transform)
ultimately have "(U\<^sub>f * U\<^sub>f) $$ (i,j) = f(i div 2) * f(i div 2) + (1-f(i div 2)) * (1-f(i div 2))"
using f2 by simp
moreover have "f(i div 2) * f(i div 2) + (1-f(i div 2)) * (1-f(i div 2)) = 1"
using f_values assms(1)
by (metis (no_types, lifting) Nat.minus_nat.diff_0 diff_add_0 diff_add_inverse jozsa_transform_dim(1)
less_power_add_imp_div_less mem_Collect_eq mult_eq_if one_power2 power2_eq_square power_one_right)
ultimately show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)" by(metis assms(2) a0 index_one_mat(1) of_nat_1)
next
assume a0:"(j=i+1 \<and> odd j)"
then show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
using assms(3) dvd_diffD1 odd_one even_plus_one_iff by blast
next
assume a0:"(j=i-1 \<and> even j \<and> i\<ge>1)"
then have "(U\<^sub>f * U\<^sub>f) $$ (i,j) = f(i div 2) * (1-f(i div 2)) + (1-f(i div 2)) * f(i div 2)"
using f0 f1 f2 assms
by (metis jozsa_transform_coeff(1) Groups.ab_semigroup_mult_class.mult.commute even_succ_div_two f2
jozsa_transform_dim odd_two_times_div_two_nat odd_two_times_div_two_succ of_nat_add of_nat_mult)
then show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
using assms(1) a0 by auto
next
assume a0:"j\<noteq>i \<and> \<not>(j=i+1 \<and> odd j) \<and> \<not> (j=i-1 \<and> even j \<and> i\<ge>1)"
then have "U\<^sub>f $$ (i,j) = 0"
by (metis assms(1,2) index_transpose_mat(1) jozsa_transform_coeff_is_zero jozsa_transform_dim transpose_of_jozsa_transform)
moreover have "U\<^sub>f $$ (i-1,j) = 0"
using assms a0 f0 apply auto
by (smt One_nat_def Suc_n_not_le_n add_diff_inverse_nat assms(1) assms(2) diff_Suc_less even_add
jozsa_transform_coeff_is_zero jozsa_axioms less_imp_le less_le_trans less_one odd_one)
ultimately have "(U\<^sub>f * U\<^sub>f) $$ (i,j) = (1-f(i div 2)) * 0 + f(i div 2) * 0"
using f2 by simp
then show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
using a0 assms by (metis add.left_neutral index_one_mat(1) jozsa_transform_dim mult_0_right of_nat_0)
qed
qed
lemma (in jozsa) jozsa_transform_is_gate:
shows "gate (n+1) U\<^sub>f"
proof
show "dim_row U\<^sub>f = 2^(n+1)" by simp
next
show "square_mat U\<^sub>f" by simp
next
show "unitary U\<^sub>f"
proof-
have "U\<^sub>f * U\<^sub>f = 1\<^sub>m (dim_col U\<^sub>f)"
proof
show "dim_row (U\<^sub>f * U\<^sub>f) = dim_row (1\<^sub>m (dim_col U\<^sub>f))" by simp
next
show "dim_col (U\<^sub>f * U\<^sub>f) = dim_col (1\<^sub>m (dim_col U\<^sub>f))" by simp
next
fix i j:: nat
assume "i < dim_row (1\<^sub>m (dim_col U\<^sub>f))" and "j < dim_col (1\<^sub>m (dim_col U\<^sub>f))"
then have "i < dim_row U\<^sub>f" and "j < dim_col U\<^sub>f" by auto
then show "(U\<^sub>f * U\<^sub>f) $$ (i,j) = 1\<^sub>m (dim_col U\<^sub>f) $$ (i,j)"
using jozsa_transform_is_unitary_index_odd jozsa_transform_is_unitary_index_even by blast
qed
thus ?thesis by (simp add: adjoint_of_jozsa_transform unitary_def)
qed
qed
text \<open>N-fold application of the tensor product\<close>
fun iter_tensor:: "complex Matrix.mat \<Rightarrow> nat \<Rightarrow> complex Matrix.mat" ("_ \<otimes>\<^bsup>_\<^esup>" 75) where
"A \<otimes>\<^bsup>(Suc 0)\<^esup> = A"
| "A \<otimes>\<^bsup>(Suc k)\<^esup> = A \<Otimes> (A \<otimes>\<^bsup>k\<^esup>)"
lemma one_tensor_is_id [simp]:
fixes A
shows "A \<otimes>\<^bsup>1\<^esup> = A"
using one_mat_def by simp
lemma iter_tensor_suc:
fixes n
assumes "n \<ge> 1"
shows " A \<otimes>\<^bsup>(Suc n)\<^esup> = A \<Otimes> (A \<otimes>\<^bsup>n\<^esup>)"
using assms by (metis Deutsch_Jozsa.iter_tensor.simps(2) One_nat_def Suc_le_D)
lemma dim_row_of_iter_tensor [simp]:
fixes A n
assumes "n \<ge> 1"
shows "dim_row(A \<otimes>\<^bsup>n\<^esup>) = (dim_row A)^n"
using assms
proof (rule nat_induct_at_least)
show "dim_row (A \<otimes>\<^bsup>1\<^esup>) = (dim_row A)^1"
using one_tensor_is_id by simp
next
fix n:: nat
assume "n \<ge> 1" and "dim_row (A \<otimes>\<^bsup>n\<^esup>) = (dim_row A)^n"
then show "dim_row (A \<otimes>\<^bsup>Suc n\<^esup>) = (dim_row A)^Suc n"
using iter_tensor_suc assms dim_row_tensor_mat by simp
qed
lemma dim_col_of_iter_tensor [simp]:
fixes A n
assumes "n \<ge> 1"
shows "dim_col(A \<otimes>\<^bsup>n\<^esup>) = (dim_col A)^n"
using assms
proof (rule nat_induct_at_least)
show "dim_col (A \<otimes>\<^bsup>1\<^esup>) = (dim_col A)^1"
using one_tensor_is_id by simp
next
fix n:: nat
assume "n \<ge> 1" and "dim_col (A \<otimes>\<^bsup>n\<^esup>) = (dim_col A)^n"
then show "dim_col (A \<otimes>\<^bsup>Suc n\<^esup>) = (dim_col A)^Suc n"
using iter_tensor_suc assms dim_col_tensor_mat by simp
qed
lemma iter_tensor_values:
fixes A n i j
assumes "n \<ge> 1" and "i < dim_row (A \<Otimes> (A \<otimes>\<^bsup>n\<^esup>))" and "j < dim_col (A \<Otimes> (A \<otimes>\<^bsup>n\<^esup>))"
shows "(A \<otimes>\<^bsup>(Suc n)\<^esup>) $$ (i,j) = (A \<Otimes> (A \<otimes>\<^bsup>n\<^esup>)) $$ (i,j)"
using assms by (metis One_nat_def le_0_eq not0_implies_Suc iter_tensor.simps(2))
lemma iter_tensor_mult_distr:
assumes "n \<ge> 1" and "dim_col A = dim_row B" and "dim_col A > 0" and "dim_col B > 0"
shows "(A \<otimes>\<^bsup>(Suc n)\<^esup>) * (B \<otimes>\<^bsup>(Suc n)\<^esup>) = (A * B) \<Otimes> ((A \<otimes>\<^bsup>n\<^esup>) * (B \<otimes>\<^bsup>n\<^esup>))"
proof-
have "(A \<otimes>\<^bsup>(Suc n)\<^esup>) * (B \<otimes>\<^bsup>(Suc n)\<^esup>) = (A \<Otimes> (A \<otimes>\<^bsup>n\<^esup>)) * (B \<Otimes> (B \<otimes>\<^bsup>n\<^esup>))"
using Suc_le_D assms(1) by fastforce
then show "?thesis"
using mult_distr_tensor[of "A" "B" "(iter_tensor A n)" "(iter_tensor B n)"] assms by simp
qed
lemma index_tensor_mat_with_vec2_row_cond:
fixes A B:: "complex Matrix.mat" and i:: "nat"
assumes "i < 2 * (dim_row B)" and "i \<ge> dim_row B" and "dim_col B > 0"
and "dim_row A = 2" and "dim_col A = 1"
shows "(A \<Otimes> B) $$ (i,0) = (A $$ (1,0)) * (B $$ (i-dim_row B,0))"
proof-
have "(A \<Otimes> B) $$ (i,0) = A $$ (i div (dim_row B),0) * B $$ (i mod (dim_row B),0)"
using assms index_tensor_mat[of A "dim_row A" "dim_col A" B "dim_row B" "dim_col B" i 0] by simp
moreover have "i div (dim_row B) = 1"
using assms(1,2,4) by simp
then have "i mod (dim_row B) = i - (dim_row B)"
by (simp add: modulo_nat_def)
ultimately show "(A \<Otimes> B) $$ (i,0) = (A $$ (1,0)) * (B $$ (i-dim_row B,0))"
by (simp add: \<open>i div dim_row B = 1\<close>)
qed
lemma iter_tensor_of_gate_is_gate:
fixes A:: "complex Matrix.mat" and n m:: "nat"
assumes "gate m A" and "n \<ge> 1"
shows "gate (m*n) (A \<otimes>\<^bsup>n\<^esup>)"
using assms(2)
proof(rule nat_induct_at_least)
show "gate (m * 1) (A \<otimes>\<^bsup>1\<^esup>)" using assms(1) by simp
next
fix n:: nat
assume "n \<ge> 1" and IH:"gate (m * n) (A \<otimes>\<^bsup>n\<^esup>)"
then have "A \<otimes>\<^bsup>(Suc n)\<^esup> = A \<Otimes> (A \<otimes>\<^bsup>n\<^esup>)"
by (simp add: iter_tensor_suc)
moreover have "gate (m*n + m) (A \<otimes>\<^bsup>(Suc n)\<^esup>)"
using tensor_gate assms(1) by (simp add: IH add.commute calculation(1))
then show "gate (m*(Suc n)) (A \<otimes>\<^bsup>(Suc n)\<^esup>)"
by (simp add: add.commute)
qed
lemma iter_tensor_of_state_is_state:
fixes A:: "complex Matrix.mat" and n m:: "nat"
assumes "state m A" and "n\<ge>1"
shows "state (m*n) (A \<otimes>\<^bsup>n\<^esup>)"
using assms(2)
proof(rule nat_induct_at_least)
show "state (m * 1) (A \<otimes>\<^bsup>1\<^esup>)"
using one_tensor_is_id assms(1) by simp
next
fix n:: nat
assume "n \<ge> 1" and IH:"state (m * n) (A \<otimes>\<^bsup>n\<^esup>)"
then have "A \<otimes>\<^bsup>(Suc n)\<^esup> = A \<Otimes> (A \<otimes>\<^bsup>n\<^esup>)"
by (simp add: iter_tensor_suc)
moreover have "state (m*n + m) (A \<otimes>\<^bsup>(Suc n)\<^esup>)"
using tensor_gate assms(1) by (simp add: IH add.commute calculation)
then show "state (m*(Suc n)) (A \<otimes>\<^bsup>(Suc n)\<^esup>)"
by (simp add: add.commute)
qed
text \<open>
We prepare n+1 qubits. The first n qubits in the state $|0\rangle$, the last one in the state
$|1\rangle$.
\<close>
abbreviation \<psi>\<^sub>1\<^sub>0:: "nat \<Rightarrow> complex Matrix.mat" where
"\<psi>\<^sub>1\<^sub>0 n \<equiv> Matrix.mat (2^n) 1 (\<lambda>(i,j). 1/(sqrt 2)^n)"
lemma \<psi>\<^sub>1\<^sub>0_values:
fixes i j n
assumes "i < dim_row (\<psi>\<^sub>1\<^sub>0 n)" and "j < dim_col (\<psi>\<^sub>1\<^sub>0 n)"
shows "(\<psi>\<^sub>1\<^sub>0 n) $$ (i,j) = 1/(sqrt 2)^n"
using assms case_prod_conv by simp
text \<open>$H^{\otimes n}$ is applied to $|0\rangle^{\otimes n}$.\<close>
lemma H_on_ket_zero:
shows "(H * |zero\<rangle>) = \<psi>\<^sub>1\<^sub>0 1"
proof
fix i j:: nat
assume "i < dim_row (\<psi>\<^sub>1\<^sub>0 1)" and "j < dim_col (\<psi>\<^sub>1\<^sub>0 1)"
then have f1: "i \<in> {0,1} \<and> j = 0" by (simp add: less_2_cases)
then show "(H * |zero\<rangle>) $$ (i,j) = (\<psi>\<^sub>1\<^sub>0 1) $$ (i,j)"
by (auto simp add: times_mat_def scalar_prod_def H_def ket_vec_def)
next
show "dim_row (H * |zero\<rangle>) = dim_row (\<psi>\<^sub>1\<^sub>0 1)" by (simp add: H_def)
next
show "dim_col (H * |zero\<rangle>) = dim_col (\<psi>\<^sub>1\<^sub>0 1)" using H_def
by (simp add: ket_vec_def)
qed
lemma \<psi>\<^sub>1\<^sub>0_tensor:
assumes "n \<ge> 1"
shows "(\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n) = (\<psi>\<^sub>1\<^sub>0 (Suc n))"
proof
have "dim_row (\<psi>\<^sub>1\<^sub>0 1) * dim_row (\<psi>\<^sub>1\<^sub>0 n) = 2^(Suc n)" by simp
then show "dim_row ((\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)) = dim_row (\<psi>\<^sub>1\<^sub>0 (Suc n))" by simp
next
have "dim_col (\<psi>\<^sub>1\<^sub>0 1) * dim_col (\<psi>\<^sub>1\<^sub>0 n) = 1" by simp
then show "dim_col ((\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)) = dim_col (\<psi>\<^sub>1\<^sub>0 (Suc n))" by simp
next
fix i j:: nat
assume a0: "i < dim_row (\<psi>\<^sub>1\<^sub>0 (Suc n))" and a1: "j < dim_col (\<psi>\<^sub>1\<^sub>0 (Suc n))"
then have f0: "j = 0" and f1: "i < 2^(Suc n)" by auto
then have f2:"(\<psi>\<^sub>1\<^sub>0 (Suc n)) $$ (i,j) = 1/(sqrt 2)^(Suc n)"
using \<psi>\<^sub>1\<^sub>0_values[of "i" "(Suc n)" "j"] a0 a1 by simp
show "((\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)) $$ (i,j) = (\<psi>\<^sub>1\<^sub>0 (Suc n)) $$ (i,j)"
proof (rule disjE) (*case distinction*)
show "i < dim_row (\<psi>\<^sub>1\<^sub>0 n) \<or> i \<ge> dim_row (\<psi>\<^sub>1\<^sub>0 n)" by linarith
next (* case i < dim_row (\<psi>\<^sub>1\<^sub>0 n) *)
assume a2: "i < dim_row (\<psi>\<^sub>1\<^sub>0 n)"
then have "((\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)) $$ (i,j) = (\<psi>\<^sub>1\<^sub>0 1) $$ (0,0) * (\<psi>\<^sub>1\<^sub>0 n) $$ (i,0)"
using index_tensor_mat f0 assms by simp
also have "... = 1/sqrt(2) * 1/(sqrt(2)^n)"
using \<psi>\<^sub>1\<^sub>0_values a2 assms by simp
finally show "((\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)) $$ (i,j) = (\<psi>\<^sub>1\<^sub>0 (Suc n)) $$ (i,j)"
using f2 divide_divide_eq_left power_Suc by simp
next (* case i \<ge> dim_row (\<psi>\<^sub>1\<^sub>0 n) *)
assume "i \<ge> dim_row (\<psi>\<^sub>1\<^sub>0 n)"
then have "((\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)) $$ (i,0) = ((\<psi>\<^sub>1\<^sub>0 1) $$ (1, 0)) * ((\<psi>\<^sub>1\<^sub>0 n) $$ ( i -dim_row (\<psi>\<^sub>1\<^sub>0 n),0))"
using index_tensor_mat_with_vec2_row_cond[of i "(\<psi>\<^sub>1\<^sub>0 1)" "(\<psi>\<^sub>1\<^sub>0 n)" ] a0 a1 f0
by (metis dim_col_mat(1) dim_row_mat(1) index_tensor_mat_with_vec2_row_cond power_Suc power_one_right)
then have "((\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)) $$ (i,0) = 1/sqrt(2) * 1/(sqrt 2)^n"
using \<psi>\<^sub>1\<^sub>0_values[of "i -dim_row (\<psi>\<^sub>1\<^sub>0 n)" "n" "j"] a0 a1 by simp
then show "((\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)) $$ (i,j) = (\<psi>\<^sub>1\<^sub>0 (Suc n)) $$ (i,j)"
using f0 f1 divide_divide_eq_left power_Suc by simp
qed
qed
lemma \<psi>\<^sub>1\<^sub>0_tensor_is_state:
assumes "n \<ge> 1"
shows "state n ( |zero\<rangle> \<otimes>\<^bsup>n\<^esup>)"
using iter_tensor_of_state_is_state ket_zero_is_state assms by fastforce
lemma iter_tensor_of_H_is_gate:
assumes "n \<ge> 1"
shows "gate n (H \<otimes>\<^bsup>n\<^esup>)"
using iter_tensor_of_gate_is_gate H_is_gate assms by fastforce
lemma iter_tensor_of_H_on_zero_tensor:
assumes "n \<ge> 1"
shows "(H \<otimes>\<^bsup>n\<^esup>) * ( |zero\<rangle> \<otimes>\<^bsup>n\<^esup>) = \<psi>\<^sub>1\<^sub>0 n"
using assms
proof(rule nat_induct_at_least)
show "(H \<otimes>\<^bsup>1\<^esup>) * ( |zero\<rangle> \<otimes>\<^bsup>1\<^esup>) = \<psi>\<^sub>1\<^sub>0 1"
using H_on_ket_zero by simp
next
fix n:: nat
assume a0: "n \<ge> 1" and IH: "(H \<otimes>\<^bsup>n\<^esup>) * ( |zero\<rangle> \<otimes>\<^bsup>n\<^esup>) = \<psi>\<^sub>1\<^sub>0 n"
then have "(H \<otimes>\<^bsup>(Suc n)\<^esup>) * ( |zero\<rangle> \<otimes>\<^bsup>(Suc n)\<^esup>) = (H * |zero\<rangle>) \<Otimes> ((H \<otimes>\<^bsup>n\<^esup>) * ( |zero\<rangle> \<otimes>\<^bsup>n\<^esup>))"
using iter_tensor_mult_distr[of "n" "H" "|zero\<rangle>"] a0 ket_vec_def H_def by(simp add: H_def)
also have "... = (H * |zero\<rangle>) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)" using IH by simp
also have "... = (\<psi>\<^sub>1\<^sub>0 1) \<Otimes> (\<psi>\<^sub>1\<^sub>0 n)" using H_on_ket_zero by simp
also have "... = (\<psi>\<^sub>1\<^sub>0 (Suc n))" using \<psi>\<^sub>1\<^sub>0_tensor a0 by simp
finally show "(H \<otimes>\<^bsup>(Suc n)\<^esup>) * ( |zero\<rangle> \<otimes>\<^bsup>(Suc n)\<^esup>) = (\<psi>\<^sub>1\<^sub>0 (Suc n))" by simp
qed
lemma \<psi>\<^sub>1\<^sub>0_is_state:
assumes "n \<ge> 1"
shows "state n (\<psi>\<^sub>1\<^sub>0 n)"
using iter_tensor_of_H_is_gate \<psi>\<^sub>1\<^sub>0_tensor_is_state assms gate_on_state_is_state iter_tensor_of_H_on_zero_tensor assms by metis
abbreviation \<psi>\<^sub>1\<^sub>1:: "complex Matrix.mat" where
"\<psi>\<^sub>1\<^sub>1 \<equiv> Matrix.mat 2 1 (\<lambda>(i,j). if i=0 then 1/sqrt(2) else -1/sqrt(2))"
lemma H_on_ket_one_is_\<psi>\<^sub>1\<^sub>1:
shows "(H * |one\<rangle>) = \<psi>\<^sub>1\<^sub>1"
proof
fix i j:: nat
assume "i < dim_row \<psi>\<^sub>1\<^sub>1" and "j < dim_col \<psi>\<^sub>1\<^sub>1"
then have "i \<in> {0,1} \<and> j = 0" by (simp add: less_2_cases)
then show "(H * |one\<rangle>) $$ (i,j) = \<psi>\<^sub>1\<^sub>1 $$ (i,j)"
by (auto simp add: times_mat_def scalar_prod_def H_def ket_vec_def)
next
show "dim_row (H * |one\<rangle>) = dim_row \<psi>\<^sub>1\<^sub>1" by (simp add: H_def)
next
show "dim_col (H * |one\<rangle>) = dim_col \<psi>\<^sub>1\<^sub>1" by (simp add: H_def ket_vec_def)
qed
abbreviation \<psi>\<^sub>1:: "nat \<Rightarrow> complex Matrix.mat" where
"\<psi>\<^sub>1 n \<equiv> Matrix.mat (2^(n+1)) 1 (\<lambda>(i,j). if even i then 1/(sqrt 2)^(n+1) else -1/(sqrt 2)^(n+1))"
lemma \<psi>\<^sub>1_values_even[simp]:
fixes i j n
assumes "i < dim_row (\<psi>\<^sub>1 n)" and "j < dim_col (\<psi>\<^sub>1 n)" and "even i"
shows "(\<psi>\<^sub>1 n) $$ (i,j) = 1/(sqrt 2)^(n+1)"
using assms case_prod_conv by simp
lemma \<psi>\<^sub>1_values_odd [simp]:
fixes i j n
assumes "i < dim_row (\<psi>\<^sub>1 n)" and "j < dim_col (\<psi>\<^sub>1 n)" and "odd i"
shows "(\<psi>\<^sub>1 n) $$ (i,j) = -1/(sqrt 2)^(n+1)"
using assms case_prod_conv by simp
lemma "\<psi>\<^sub>1\<^sub>0_tensor_\<psi>\<^sub>1\<^sub>1_is_\<psi>\<^sub>1":
assumes "n \<ge> 1"
shows "(\<psi>\<^sub>1\<^sub>0 n) \<Otimes> \<psi>\<^sub>1\<^sub>1 = \<psi>\<^sub>1 n"
proof
show "dim_col ((\<psi>\<^sub>1\<^sub>0 n) \<Otimes> \<psi>\<^sub>1\<^sub>1) = dim_col (\<psi>\<^sub>1 n)" by simp
next
show "dim_row ((\<psi>\<^sub>1\<^sub>0 n) \<Otimes> \<psi>\<^sub>1\<^sub>1) = dim_row (\<psi>\<^sub>1 n)" by simp
next
fix i j:: nat
assume a0: "i < dim_row (\<psi>\<^sub>1 n)" and a1: "j < dim_col (\<psi>\<^sub>1 n)"
then have "i < 2^(n+1)" and "j = 0" by auto
then have f0: "((\<psi>\<^sub>1\<^sub>0 n) \<Otimes> \<psi>\<^sub>1\<^sub>1) $$ (i,j) = 1/(sqrt 2)^n * \<psi>\<^sub>1\<^sub>1 $$ (i mod 2, j)"
using \<psi>\<^sub>1\<^sub>0_values[of "i div 2" n "j div 1"] a0 a1 by simp
show "((\<psi>\<^sub>1\<^sub>0 n) \<Otimes> \<psi>\<^sub>1\<^sub>1) $$ (i,j) = (\<psi>\<^sub>1 n) $$ (i,j)"
using f0 \<psi>\<^sub>1_values_even \<psi>\<^sub>1_values_odd a0 a1 by auto
qed
lemma \<psi>\<^sub>1_is_state:
assumes "n \<ge> 1"
shows "state (n+1) (\<psi>\<^sub>1 n)"
using assms \<psi>\<^sub>1\<^sub>0_tensor_\<psi>\<^sub>1\<^sub>1_is_\<psi>\<^sub>1 \<psi>\<^sub>1\<^sub>0_is_state H_on_ket_one_is_state H_on_ket_one_is_\<psi>\<^sub>1\<^sub>1 tensor_state by metis
abbreviation (in jozsa) \<psi>\<^sub>2:: "complex Matrix.mat" where
"\<psi>\<^sub>2 \<equiv> Matrix.mat (2^(n+1)) 1 (\<lambda>(i,j). if even i then (-1)^f(i div 2)/(sqrt 2)^(n+1)
else (-1)^(f(i div 2)+1)/(sqrt 2)^(n+1))"
lemma (in jozsa) \<psi>\<^sub>2_values_even [simp]:
fixes i j
assumes "i < dim_row \<psi>\<^sub>2 " and "j < dim_col \<psi>\<^sub>2" and "even i"
shows "\<psi>\<^sub>2 $$ (i,j) = (-1)^f(i div 2)/(sqrt 2)^(n+1)"
using assms case_prod_conv by simp
lemma (in jozsa) \<psi>\<^sub>2_values_odd [simp]:
fixes i j
assumes "i < dim_row \<psi>\<^sub>2" and "j < dim_col \<psi>\<^sub>2" and "odd i"
shows "\<psi>\<^sub>2 $$ (i,j) = (-1)^(f(i div 2)+1)/(sqrt 2)^(n+1)"
using assms case_prod_conv by simp
lemma (in jozsa) \<psi>\<^sub>2_values_odd_hidden [simp]:
assumes "2*k+1 < dim_row \<psi>\<^sub>2" and "j < dim_col \<psi>\<^sub>2"
shows "\<psi>\<^sub>2 $$ (2*k+1,j) = ((-1)^(f((2*k+1) div 2)+1))/(sqrt 2)^(n+1)"
using assms by simp
lemma (in jozsa) snd_rep_of_\<psi>\<^sub>2:
assumes "i < dim_row \<psi>\<^sub>2"
shows "((1-f(i div 2)) + -f(i div 2)) * 1/(sqrt 2)^(n+1) = (-1)^f(i div 2)/(sqrt 2)^(n+1)"
and "(-(1-f(i div 2))+(f(i div 2)))* 1/(sqrt 2)^(n+1) = (-1)^(f(i div 2)+1)/(sqrt 2)^(n+1)"
proof-
have "i div 2 \<in> {i. i < 2 ^ n}"
using assms by auto
then have "real (Suc 0 - f (i div 2)) - real (f (i div 2)) = (- 1) ^ f (i div 2)"
using assms f_values by auto
thus "((1-f(i div 2)) + -f(i div 2)) * 1/(sqrt 2)^(n+1) = (-1)^f(i div 2)/(sqrt 2)^(n+1)" by auto
next
have "i div 2 \<in> {i. i < 2^n}"
using assms by simp
then have "(real (f (i div 2)) - real (Suc 0 - f (i div 2))) / (sqrt 2 ^ (n+1)) =
- ((- 1) ^ f (i div 2) / (sqrt 2 ^ (n+1)))"
using assms f_values by fastforce
then show "(-(1-f(i div 2))+(f(i div 2)))* 1/(sqrt 2)^(n+1) = (-1)^(f(i div 2)+1)/(sqrt 2)^(n+1)" by simp
qed
lemma (in jozsa) jozsa_transform_times_\<psi>\<^sub>1_is_\<psi>\<^sub>2:
shows "U\<^sub>f * (\<psi>\<^sub>1 n) = \<psi>\<^sub>2"
proof
show "dim_row (U\<^sub>f * (\<psi>\<^sub>1 n)) = dim_row \<psi>\<^sub>2" by simp
next
show "dim_col (U\<^sub>f * (\<psi>\<^sub>1 n)) = dim_col \<psi>\<^sub>2" by simp
next
fix i j ::nat
assume a0: "i < dim_row \<psi>\<^sub>2" and a1: "j < dim_col \<psi>\<^sub>2"
then have f0:"i \<in> {0..2^(n+1)} \<and> j=0" by simp
then have f1: "i < dim_row U\<^sub>f \<and> j < dim_col U\<^sub>f " using a0 by simp
have f2: "i < dim_row (\<psi>\<^sub>1 n) \<and> j < dim_col (\<psi>\<^sub>1 n)" using a0 a1 by simp
show "(U\<^sub>f * (\<psi>\<^sub>1 n)) $$ (i,j) = \<psi>\<^sub>2 $$ (i,j)"
proof (rule disjE)
show "even i \<or> odd i" by auto
next
assume a2: "even i"
then have "(U\<^sub>f * (\<psi>\<^sub>1 n)) $$ (i,j) = (\<Sum>k \<in> {i,i+1}. U\<^sub>f $$ (i,k) * (\<psi>\<^sub>1 n) $$ (k,j))"
using f1 f2 U\<^sub>f_mult_without_empty_summands_even[of i j "(\<psi>\<^sub>1 n)"] by simp
moreover have "U\<^sub>f $$ (i,i) * (\<psi>\<^sub>1 n) $$ (i,j) = (1-f(i div 2))* 1/(sqrt 2)^(n+1)"
using f0 f1 a2 by simp
moreover have "U\<^sub>f $$ (i,i+1) * (\<psi>\<^sub>1 n) $$ (i+1,j) = (-f(i div 2))* 1/(sqrt 2)^(n+1)"
using f0 f1 a2 by auto
ultimately have "(U\<^sub>f * (\<psi>\<^sub>1 n)) $$ (i,j) = (1-f(i div 2))* 1/(sqrt 2)^(n+1) + (-f(i div 2))* 1/(sqrt 2)^(n+1)" by simp
also have "... = ((1-f(i div 2))+-f(i div 2)) * 1/(sqrt 2)^(n+1)"
using add_divide_distrib
by (metis (no_types, hide_lams) mult.right_neutral of_int_add of_int_of_nat_eq)
also have "... = \<psi>\<^sub>2 $$ (i,j)"
using a0 a1 a2 snd_rep_of_\<psi>\<^sub>2 by simp
finally show "(U\<^sub>f * (\<psi>\<^sub>1 n)) $$ (i,j) = \<psi>\<^sub>2 $$ (i,j)" by simp
next
assume a2: "odd i"
then have f6: "i\<ge>1"
using linorder_not_less by auto
have "(U\<^sub>f * (\<psi>\<^sub>1 n)) $$ (i,j) = (\<Sum>k \<in> {i-1,i}. U\<^sub>f $$ (i,k) * (\<psi>\<^sub>1 n) $$ (k,j))"
using f1 f2 a2 U\<^sub>f_mult_without_empty_summands_odd[of i j "(\<psi>\<^sub>1 n)"]
by (metis dim_row_mat(1) jozsa_transform_dim(2))
moreover have "(\<Sum>k \<in> {i-1,i}. U\<^sub>f $$ (i,k) * (\<psi>\<^sub>1 n) $$ (k,j))
= U\<^sub>f $$ (i,i-1) * (\<psi>\<^sub>1 n) $$ (i-1,j) + U\<^sub>f $$ (i,i) * (\<psi>\<^sub>1 n) $$ (i,j)"
using a2 f6 by simp
moreover have "U\<^sub>f $$ (i,i) * (\<psi>\<^sub>1 n) $$ (i,j) = (1-f(i div 2))* -1/(sqrt 2)^(n+1)"
using f1 f2 a2 by simp
moreover have "U\<^sub>f $$ (i,i-1) * (\<psi>\<^sub>1 n) $$ (i-1,j) = f(i div 2)* 1/(sqrt 2)^(n+1)"
using a0 a1 a2 by simp
ultimately have "(U\<^sub>f * (\<psi>\<^sub>1 n)) $$ (i,j) = (1-f(i div 2))* -1/(sqrt 2)^(n+1) +(f(i div 2))* 1/(sqrt 2)^(n+1)"
using of_real_add by simp
also have "... = (-(1-f(i div 2)) + (f(i div 2))) * 1/(sqrt 2)^(n+1)"
by (metis (no_types, hide_lams) mult.right_neutral add_divide_distrib mult_minus1_right
of_int_add of_int_of_nat_eq)
also have "... = (-1)^(f(i div 2)+1)/(sqrt 2)^(n+1)"
using a0 a1 a2 snd_rep_of_\<psi>\<^sub>2 by simp
finally show "(U\<^sub>f * (\<psi>\<^sub>1 n)) $$ (i,j) = \<psi>\<^sub>2 $$ (i,j)"
using a0 a1 a2 by simp
qed
qed
lemma (in jozsa) \<psi>\<^sub>2_is_state:
shows "state (n+1) \<psi>\<^sub>2"
using jozsa_transform_times_\<psi>\<^sub>1_is_\<psi>\<^sub>2 jozsa_transform_is_gate \<psi>\<^sub>1_is_state dim gate_on_state_is_state by fastforce
text \<open>@{text "H^\<^sub>\<otimes> n"} is the result of taking the nth tensor product of H\<close>
abbreviation iter_tensor_of_H_rep:: "nat \<Rightarrow> complex Matrix.mat" ("H^\<^sub>\<otimes> _") where
"iter_tensor_of_H_rep n \<equiv> Matrix.mat (2^n) (2^n) (\<lambda>(i,j).(-1)^(i \<cdot>\<^bsub>n\<^esub> j)/(sqrt 2)^n)"
lemma tensor_of_H_values [simp]:
fixes n i j:: nat
assumes "i < dim_row (H^\<^sub>\<otimes> n)" and "j < dim_col (H^\<^sub>\<otimes> n)"
shows "(H^\<^sub>\<otimes> n) $$ (i,j) = (-1)^(i \<cdot>\<^bsub>n\<^esub> j)/(sqrt 2)^n"
using assms by simp
lemma dim_row_of_iter_tensor_of_H [simp]:
assumes "n \<ge> 1"
shows "1 < dim_row (H^\<^sub>\<otimes> n)"
using assms by(metis One_nat_def Suc_1 dim_row_mat(1) le_trans lessI linorder_not_less one_less_power)
lemma iter_tensor_of_H_fst_pos:
fixes n i j:: nat
assumes "i < 2^n \<or> j < 2^n" and "i < 2^(n+1) \<and> j < 2^(n+1)"
shows "(H^\<^sub>\<otimes> (Suc n)) $$ (i,j) = 1/sqrt(2) * ((H^\<^sub>\<otimes> n) $$ (i mod 2^n, j mod 2^n))"
proof-
have "(H^\<^sub>\<otimes> (Suc n)) $$ (i,j) = (-1)^(bip i (Suc n) j)/(sqrt 2)^(Suc n)"
using assms by simp
moreover have "bip i (Suc n) j = bip (i mod 2^n) n (j mod 2^n)"
using bitwise_inner_prod_fst_el_0 assms(1) by simp
ultimately show ?thesis
using bitwise_inner_prod_def by simp
qed
lemma iter_tensor_of_H_fst_neg:
fixes n i j:: nat
assumes "i \<ge> 2^n \<and> j \<ge> 2^n" and "i < 2^(n+1) \<and> j < 2^(n+1)"
shows "(H^\<^sub>\<otimes> (Suc n)) $$ (i,j) = -1/sqrt(2) * (H^\<^sub>\<otimes> n) $$ (i mod 2^n, j mod 2^n)"
proof-
have "(H^\<^sub>\<otimes> (Suc n)) $$ (i,j) = (-1)^(bip i (n+1) j)/(sqrt 2)^(n+1)"
using assms(2) by simp
moreover have "bip i (n+1) j = 1 + bip (i mod 2^n) n (j mod 2^n)"
using bitwise_inner_prod_fst_el_is_1 assms by simp
ultimately show ?thesis by simp
qed
lemma H_tensor_iter_tensor_of_H:
fixes n:: nat
shows "(H \<Otimes> H^\<^sub>\<otimes> n) = H^\<^sub>\<otimes> (Suc n)"
proof
fix i j:: nat
assume a0: "i < dim_row (H^\<^sub>\<otimes> (Suc n))" and a1: "j < dim_col (H^\<^sub>\<otimes> (Suc n))"
then have f0: "i \<in> {0..<2^(n+1)} \<and> j \<in> {0..<2^(n+1)}" by simp
then have f1: "(H \<Otimes> H^\<^sub>\<otimes> n) $$ (i,j) = H $$ (i div (dim_row (H^\<^sub>\<otimes> n)),j div (dim_col (H^\<^sub>\<otimes> n)))
* (H^\<^sub>\<otimes> n) $$ (i mod (dim_row (H^\<^sub>\<otimes> n)),j mod (dim_col (H^\<^sub>\<otimes> n)))"
by (simp add: H_without_scalar_prod)
show "(H \<Otimes> H^\<^sub>\<otimes> n) $$ (i,j) = (H^\<^sub>\<otimes> (Suc n)) $$ (i,j)"
proof (rule disjE)
show "(i < 2^n \<or> j < 2^n) \<or> \<not>(i < 2^n \<or> j < 2^n)" by auto
next
assume a2: "(i < 2^n \<or> j < 2^n)"
then have "(H^\<^sub>\<otimes> (Suc n)) $$ (i,j) = 1/sqrt(2) * ((H^\<^sub>\<otimes> n) $$ (i mod 2^n, j mod 2^n))"
using a0 a1 f0 iter_tensor_of_H_fst_pos by (metis (mono_tags, lifting) atLeastLessThan_iff)
moreover have "H $$ (i div (dim_row (H^\<^sub>\<otimes> n)),j div (dim_col (H^\<^sub>\<otimes> n))) = 1/sqrt 2"
using a0 a1 f0 H_without_scalar_prod H_values a2
by (metis (no_types, lifting) dim_col_mat(1) dim_row_mat(1) div_less le_eq_less_or_eq
le_numeral_extra(2) less_power_add_imp_div_less plus_1_eq_Suc power_one_right)
ultimately show "(H \<Otimes> H^\<^sub>\<otimes> n) $$ (i,j) = (H^\<^sub>\<otimes> (Suc n)) $$ (i,j)"
using f1 by simp
next
assume a2: "\<not>(i < 2^n \<or> j < 2^n)"
then have "i \<ge> 2^n \<and> j \<ge> 2^n" by simp
then have f2:"(H^\<^sub>\<otimes> (Suc n)) $$ (i,j) = -1/sqrt(2) * ((H^\<^sub>\<otimes> n) $$ (i mod 2^n, j mod 2^n))"
using a0 a1 f0 iter_tensor_of_H_fst_neg by simp
have "i div (dim_row (H^\<^sub>\<otimes> n)) =1" and "j div (dim_row (H^\<^sub>\<otimes> n)) = 1"
using a2 a0 a1 by auto
then have "H $$ (i div (dim_row (H^\<^sub>\<otimes> n)),j div (dim_col (H^\<^sub>\<otimes> n))) = -1/sqrt 2"
using a0 a1 f0 H_values_right_bottom[of "i div (dim_row (H^\<^sub>\<otimes> n))" "j div (dim_col (H^\<^sub>\<otimes> n))"] a2
by fastforce
then show "(H \<Otimes> H^\<^sub>\<otimes> n) $$ (i,j) = (H^\<^sub>\<otimes> (Suc n)) $$ (i,j)"
using f1 f2 by simp
qed
next
show "dim_row (H \<Otimes> H^\<^sub>\<otimes> n) = dim_row (H^\<^sub>\<otimes> (Suc n))"
by (simp add: H_without_scalar_prod)
next
show "dim_col (H \<Otimes> H^\<^sub>\<otimes> n) = dim_col (H^\<^sub>\<otimes> (Suc n))"
by (simp add: H_without_scalar_prod)
qed
text \<open>
We prove that @{term "H^\<^sub>\<otimes> n"} is indeed the matrix representation of @{term "H \<otimes>\<^bsup>n\<^esup>"}, the iterated
tensor product of the Hadamard gate H.
\<close>
lemma one_tensor_of_H_is_H:
shows "(H^\<^sub>\<otimes> 1) = H"
proof(rule eq_matI)
show "dim_row (H^\<^sub>\<otimes> 1) = dim_row H"
by (simp add: H_without_scalar_prod)
next
show "dim_col (H^\<^sub>\<otimes> 1) = dim_col H"
by (simp add: H_without_scalar_prod)
next
fix i j:: nat
assume a0:"i < dim_row H" and a1:"j < dim_col H"
then show "(H^\<^sub>\<otimes> 1) $$ (i,j) = H $$ (i,j)"
proof-
have "(H^\<^sub>\<otimes> 1) $$ (0, 0) = 1/sqrt(2)"
using bitwise_inner_prod_def bin_rep_def by simp
moreover have "(H^\<^sub>\<otimes> 1) $$ (0,1) = 1/sqrt(2)"
using bitwise_inner_prod_def bin_rep_def by simp
moreover have "(H^\<^sub>\<otimes> 1) $$ (1,0) = 1/sqrt(2)"
using bitwise_inner_prod_def bin_rep_def by simp
moreover have "(H^\<^sub>\<otimes> 1) $$ (1,1) = -1/sqrt(2)"
using bitwise_inner_prod_def bin_rep_def by simp
ultimately show "(H^\<^sub>\<otimes> 1) $$ (i,j) = H $$ (i,j)"
using a0 a1 H_values H_values_right_bottom
by (metis (no_types, lifting) H_without_scalar_prod One_nat_def dim_col_mat(1) dim_row_mat(1)
divide_minus_left less_2_cases)
qed
qed
lemma iter_tensor_of_H_rep_is_correct:
fixes n:: nat
assumes "n \<ge> 1"
shows "(H \<otimes>\<^bsup>n\<^esup>) = H^\<^sub>\<otimes> n"
using assms
proof(rule nat_induct_at_least)
show "(H \<otimes>\<^bsup>1\<^esup>) = H^\<^sub>\<otimes> 1"
using one_tensor_is_id one_tensor_of_H_is_H by simp
next
fix n:: nat
assume a0:"n \<ge> 1" and IH:"(H \<otimes>\<^bsup>n\<^esup>) = H^\<^sub>\<otimes> n"
then have "(H \<otimes>\<^bsup>(Suc n)\<^esup>) = H \<Otimes> (H \<otimes>\<^bsup>n\<^esup>)"
using iter_tensor_suc Nat.Suc_eq_plus1 by metis
also have "... = H \<Otimes> (H^\<^sub>\<otimes> n)"
using IH by simp
also have "... = H^\<^sub>\<otimes> (Suc n)"
using a0 H_tensor_iter_tensor_of_H by simp
finally show "(H \<otimes>\<^bsup>(Suc n)\<^esup>) = H^\<^sub>\<otimes> (Suc n)"
by simp
qed
text \<open>@{text "HId^\<^sub>\<otimes> 1"} is the result of taking the tensor product of the nth tensor of H and Id 1 \<close>
abbreviation tensor_of_H_tensor_Id:: "nat \<Rightarrow> complex Matrix.mat" ("HId^\<^sub>\<otimes> _") where
"tensor_of_H_tensor_Id n \<equiv> Matrix.mat (2^(n+1)) (2^(n+1)) (\<lambda>(i,j).
if (i mod 2 = j mod 2) then (-1)^((i div 2) \<cdot>\<^bsub>n\<^esub> (j div 2))/(sqrt 2)^n else 0)"
lemma mod_2_is_both_even_or_odd:
"((even i \<and> even j) \<or> (odd i \<and> odd j)) \<longleftrightarrow> (i mod 2 = j mod 2)"
by (metis dvd_eq_mod_eq_0 odd_iff_mod_2_eq_one)
lemma HId_values [simp]:
assumes "n \<ge> 1" and "i < dim_row (HId^\<^sub>\<otimes> n)" and "j < dim_col (HId^\<^sub>\<otimes> n)"
shows "even i \<and> even j \<longrightarrow> (HId^\<^sub>\<otimes> n) $$ (i,j) = (-1)^((i div 2) \<cdot>\<^bsub>n\<^esub> (j div 2))/(sqrt 2)^n"
and "odd i \<and> odd j \<longrightarrow> (HId^\<^sub>\<otimes> n) $$ (i,j) = (-1)^((i div 2) \<cdot>\<^bsub>n\<^esub> (j div 2))/(sqrt 2)^n"
and "(i mod 2 = j mod 2) \<longrightarrow> (HId^\<^sub>\<otimes> n) $$ (i,j) = (-1)^((i div 2) \<cdot>\<^bsub>n\<^esub> (j div 2))/(sqrt 2)^n"
and "\<not>(i mod 2 = j mod 2) \<longrightarrow> (HId^\<^sub>\<otimes> n) $$ (i,j) = 0"
using assms mod_2_is_both_even_or_odd by auto
lemma iter_tensor_of_H_tensor_Id_is_HId:
shows "(H^\<^sub>\<otimes> n) \<Otimes> Id 1 = HId^\<^sub>\<otimes> n"
proof
show "dim_row ((H^\<^sub>\<otimes> n) \<Otimes> Id 1) = dim_row (HId^\<^sub>\<otimes> n)"
by (simp add: Quantum.Id_def)
next
show "dim_col ((H^\<^sub>\<otimes> n) \<Otimes> Id 1) = dim_col (HId^\<^sub>\<otimes> n)"
by (simp add: Quantum.Id_def)
next
fix i j:: nat
assume a0: "i < dim_row (HId^\<^sub>\<otimes> n)" and a1: "j < dim_col (HId^\<^sub>\<otimes> n)"
then have f0: "i < (2^(n+1)) \<and> j < (2^(n+1))" by simp
then have "i < dim_row (H^\<^sub>\<otimes> n) * dim_row (Id 1) \<and> j < dim_col (H^\<^sub>\<otimes> n) * dim_col (Id 1)"
using Id_def by simp
moreover have "dim_col (H^\<^sub>\<otimes> n) \<ge> 0 \<and> dim_col (Id 1) \<ge> 0"
using Id_def by simp
ultimately have f1: "((H^\<^sub>\<otimes> n) \<Otimes> (Id 1)) $$ (i,j)
= (H^\<^sub>\<otimes> n) $$ (i div (dim_row (Id 1)),j div (dim_col (Id 1))) *
(Id 1) $$ (i mod (dim_row (Id 1)),j mod (dim_col (Id 1)))"
by (simp add: Quantum.Id_def)
show "((H^\<^sub>\<otimes> n)\<Otimes>Id 1) $$ (i,j) = (HId^\<^sub>\<otimes> n) $$ (i,j)"
proof (rule disjE)
show "(i mod 2 = j mod 2) \<or> \<not> (i mod 2 = j mod 2)" by simp