ECF 1.5
Quantum.cpp
1/*
2Quantum.cpp
3Written by Walter O. Krawec
4
5Copyright (c) 2016 Walter O. Krawec
6
7Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
9The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12*/
13
14#include "Quantum.h"
15
16namespace quantum
17{
18void Basis::orthoganalize()
19{
20 if(B.empty()) return;
21 std::vector < std::vector <Complex> > u;
22 u.push_back(B[0]);
23 for(unsigned int i=1; i<B.size(); ++i)
24 {
25 u.push_back(B[i]);
26 Complex top, bottom, p, c;
27 for(unsigned int k=0; k<i; ++k)
28 {
29 top = innerProduct(B[i], u[k]);
30 p = innerProduct(u[k], u[k]);
31 bottom = algebra::ComplexHelper::invert(p);
32 p = algebra::ComplexHelper::mult(top, bottom);
33 for(unsigned int j=0; j<B[i].size(); ++j)
34 {
35 c = algebra::ComplexHelper::mult(p, u[k][j]);
36 u[i][j] = u[i][j] - c;
37 }
38 }
39 }
40
41 for(unsigned int i=0; i<B.size(); ++i)
42 {
43 double n = norm(u[i]);
44 if(n > 0.00000001)
45 n = 1.0f/n;
46 B[i] = u[i];
47 for(unsigned int j=0; j<B[i].size(); ++j)
48 {
49 B[i][j] *= n;
50 }
51 }
52}
53
54Complex KetBra::trace(std::vector <Basis>& basis)
55{
56 unsigned int basisIndex = basis.size()+1;
57 for(unsigned int i=0; i<basis.size(); ++i)
58 {
59 if(!basis[i].B.empty())
60 basisIndex = i;
61 }
62
63 Complex tr=1, zero = 0;
64
65 for(unsigned int i=0; i<ket.size(); ++i)
66 {
67 //if(basis[i].B.empty() && ket[i] != bra[i])
68 // return zero;
69 if(i != ket.size()-1 && ket[i] != bra[i])
70 return zero;
72 if(i == ket.size()-1)
73 {
74 Complex sum=0;
75
76 for(unsigned int j=0; j<basis[basis.size()-1].B[ket[i]].size(); ++j)
77 {
78 //std::cout << "<" << bra[i] << "|" << ket[i] << ">";
79 Complex b = conj(basis[basis.size()-1].B[ket[i]][j]);
80
81 Complex b2 = algebra::ComplexHelper::mult(basis[basis.size()-1].B[bra[i]][j], b);
82 //b = algebra::ComplexHelper::mult(tr, b2);
83 sum += b2;
84 }
85 Complex b;
86 b = algebra::ComplexHelper::mult(tr, sum);
87 tr = b;
88 }
89 }
90
91 Complex c = algebra::ComplexHelper::mult(p, tr);
92 tr = c;
93 //if(tr.imag > 0.00001 || tr.imag < -0.00001) throw (std::string("trace imaginary!"));
94 return tr;
95}
96Complex KetBra::trace()
97{
98
99 Complex tr=1, zero = 0;
100
101 for(unsigned int i=0; i<ket.size(); ++i)
102 {
103 if(ket[i] != bra[i])
104 return zero;
105 }
106
107 Complex c = algebra::ComplexHelper::mult(p, tr);
108 tr = c;
109 return tr;
110}
111
112
113void DensityList::applyOp(int space)
114{
115 // assumes space+1 is set to |0>
116 // will map |00> -> |00> + |11> + |22> + ... + |n-1n-1>
117 // |10> -> |0n> + ...
118
119 // assumes dim(space+1) >= dim(space)^2
120
121 std::list <KetBra>::iterator Iter;
122 std::list <KetBra> newDensity;
123 for(Iter=density.begin(); Iter != density.end(); ++Iter)
124 {
125 for(int i=0; i<dimension[space]; ++i)
126 {
127 for(int j=0; j<dimension[space]; ++j)
128 {
129 KetBra kb;
130 kb = *Iter;
131 kb.ket[space] = i;
132 kb.ket[space+1] = Iter->ket[space]*dimension[space]+i;
133 kb.bra[space] = j;
134 kb.bra[space+1] = Iter->bra[space]*dimension[space]+j;
135 newDensity.push_back(kb);
136 }
137 }
138 }
139
140 density = newDensity;
141}
142
143void DensityList::conditionalSet(std::vector <int>& targetSpace, std::vector <int>& targetVal, std::vector <int>& condSpace, std::vector <int>& condVal)
144{
145 std::list <KetBra>::iterator Iter;
146 for(Iter = density.begin(); Iter != density.end(); ++Iter)
147 {
148 bool val = true;
149 for(int i=0; i<(int)condSpace.size(); ++i)
150 {
151 if(Iter->ket[condSpace[i]] != condVal[i])
152 val = false;
153 }
154 if(val)
155 {
156 for(int i=0; i<(int)targetSpace.size(); ++i)
157 Iter->ket[targetSpace[i]] = targetVal[i];
158 }
159
160 val = true;
161 for(int i=0; i<(int)condSpace.size(); ++i)
162 {
163 if(Iter->bra[condSpace[i]] != condVal[i])
164 val = false;
165 }
166 if(val)
167 {
168 for(int i=0; i<(int)targetSpace.size(); ++i)
169 Iter->bra[targetSpace[i]] = targetVal[i];
170 }
171 }
172}
173
174void DensityList::applyOp(int startSpace, int endSpace)
175{
176 // maps |0..0> -> |0..00> + |0..11> + ... etc. etc.
177 // first compute N = dim(input space)
178 int N = 1;
179 for(int i=startSpace; i<endSpace; ++i)
180 N *= dimension[i];
181
182 std::list <KetBra>::iterator Iter;
183 std::list <KetBra> newDensity;
184 for(Iter=density.begin(); Iter != density.end(); ++Iter)
185 {
186 // first compute |index> where |i> lives in input_space:
187 int indexKet=0, indexBra = 0, dim=1;
188 for(int i=startSpace; i<endSpace; ++i)
189 {
190 indexKet += dim*Iter->ket[i];
191 indexBra += dim*Iter->bra[i];
192 dim *= dimension[i];
193 }
194 std::vector <int> k,b;
195 k.resize(endSpace-startSpace);
196 b.resize(endSpace-startSpace);
197 for(int i=0; i<endSpace-startSpace; ++i)
198 {
199 k[i] = 0;
200 b[i] = 0;
201 }
202 for(int i=0; i<N; ++i)
203 {
204 for(int a=0; a<endSpace-startSpace; ++a)
205 b[a] = 0;
206
207 for(int j=0; j<N; ++j)
208 {
209 KetBra kb;
210 kb = *Iter;
211 for(int m=startSpace; m<endSpace; ++m)
212 {
213 kb.ket[m] = k[m-startSpace];
214 kb.bra[m] = b[m-startSpace];
215 }
216 kb.ket[endSpace] = indexKet*N+i;
217 kb.bra[endSpace] = indexBra*N+j;
218 newDensity.push_back(kb);
219
220 for(int m=0; m<endSpace-startSpace; ++m)
221 {
222 b[m] ++;
223 if(b[m] >= dimension[m+startSpace])
224 b[m] = 0;
225 else
226 break;
227 }
228 }
229 for(int m=0; m<endSpace-startSpace; ++m)
230 {
231 k[m] ++;
232 if(k[m] >= dimension[m+startSpace])
233 k[m] = 0;
234 else
235 break;
236 }
237 }
238 }
239
240 density = newDensity;
241}
242
243void DensityList::trace(int space, DensityList& output)
244{
245 std::list <KetBra>::iterator Iter;
246 output = *this;
247 output.density.clear();
248
249 for(Iter=density.begin(); Iter != density.end(); ++Iter)
250 {
251 if(Iter->ket[space] == Iter->bra[space])
252 {
253 KetBra kb = *Iter;
254 kb.ket[space] = -1;
255 kb.bra[space] = -1;
256 output.density.push_back(kb);
257 }
258 }
259}
260
261void DensityList::trace(int space)
262{
263 DensityList output;
264 std::list <KetBra>::iterator Iter;
265 output = *this;
266 output.density.clear();
267
268 for(Iter=density.begin(); Iter != density.end(); ++Iter)
269 {
270 if(Iter->ket[space] == Iter->bra[space])
271 {
272 KetBra kb = *Iter;
273 kb.ket[space] = -1;
274 kb.bra[space] = -1;
275 output.density.push_back(kb);
276 }
277 }
278 density = output.density;
279}
280
281void DensityList::applyOp(int space1, int space2, Basis& op)
282{
283 std::list <KetBra>::iterator Iter;
284 std::list <KetBra> newDensity;
285
286 for(Iter=density.begin(); Iter != density.end(); ++Iter)
287 {
288 std::vector < std::vector <int> > newKets, newBras;
289 std::vector <Complex> pk, pb;
290
291 // first ket side:
292 // compute index:
293 int index = Iter->ket[space1] * dimension[space2] + Iter->ket[space2];
294 // now expand:
295 int c1=0, c2=0;
296 for(unsigned int i=0; i<op.B[index].size(); ++i)
297 {
298 std::vector <int> k = Iter->ket;
299 k[space1] = c1;
300 k[space2] = c2;
301 pk.push_back(op.B[index][i]);
302 newKets.push_back(k);
303 ++c2;
304 if(c2 >= dimension[space2])
305 {
306 c2 = 0;
307 ++c1;
308 }
309 }
310
311 // now bra side:
312 index = Iter->bra[space1] * dimension[space2] + Iter->bra[space2];
313 // now expand:
314 c1=0;
315 c2=0;
316 for(unsigned int i=0; i<op.B[index].size(); ++i)
317 {
318 std::vector <int> b = Iter->bra;
319 b[space1] = c1;
320 b[space2] = c2;
321 Complex c = conj(op.B[index][i]);
322
323 pb.push_back(c);
324 newBras.push_back(b);
325 ++c2;
326 if(c2 >= dimension[space2])
327 {
328 c2 = 0;
329 ++c1;
330 }
331 }
332
333 // now combine:
334 for(unsigned int i=0; i<newKets.size(); ++i)
335 {
336 for(unsigned int j=0; j<newBras.size(); ++j)
337 {
338 KetBra kb;
339 kb.ket = newKets[i];
340 kb.bra = newBras[j];
341 Complex c;
342 c = algebra::ComplexHelper::mult(pk[i], pb[j]);
343 kb.p = algebra::ComplexHelper::mult(Iter->p, c);
344 if(creal(kb.p) != 0 || cimag(kb.p) != 0)
345 newDensity.push_back(kb);
346 }
347 }
348 }
349
350 density = newDensity;
351}
352
353void DensityList::applyOp(int space1, int space2, int space3, Basis& op)
354{
355 std::list <KetBra>::iterator Iter;
356 std::list <KetBra> newDensity;
357
358 for(Iter=density.begin(); Iter != density.end(); ++Iter)
359 {
360 std::vector < std::vector <int> > newKets, newBras;
361 std::vector <Complex> pk, pb;
362
363 // first ket side:
364 // compute index:
365 int index = Iter->ket[space1] * dimension[space2] * dimension[space3] + Iter->ket[space2] * dimension[space3] + Iter->ket[space3];
366 // now expand:
367 int c1=0, c2=0, c3=0;
368 for(unsigned int i=0; i<op.B[index].size(); ++i)
369 {
370 std::vector <int> k = Iter->ket;
371 k[space1] = c1;
372 k[space2] = c2;
373 k[space3] = c3;
374 pk.push_back(op.B[index][i]);
375 newKets.push_back(k);
376 ++c3;
377 if(c3 >= dimension[space3])
378 {
379 c3 = 0;
380 ++c2;
381 if(c2 >= dimension[space2])
382 {
383 c2 = 0;
384 ++c1;
385 }
386 }
387 }
388
389 // now bra side:
390 index = Iter->bra[space1] * dimension[space2] * dimension[space3] + Iter->bra[space2] * dimension[space3] + Iter->bra[space3];
391 // now expand:
392 c1=0;
393 c2=0;
394 c3=0;
395 for(unsigned int i=0; i<op.B[index].size(); ++i)
396 {
397 std::vector <int> b = Iter->bra;
398 b[space1] = c1;
399 b[space2] = c2;
400 b[space3] = c3;
401 Complex c = conj(op.B[index][i]);
402
403 pb.push_back(c);
404 newBras.push_back(b);
405 ++c3;
406 if(c3 >= dimension[space3])
407 {
408 c3 = 0;
409 ++c2;
410 if(c2 >= dimension[space2])
411 {
412 c2 = 0;
413 ++c1;
414 }
415 }
416 }
417
418 // now combine:
419 for(unsigned int i=0; i<newKets.size(); ++i)
420 {
421 for(unsigned int j=0; j<newBras.size(); ++j)
422 {
423 KetBra kb;
424 kb.ket = newKets[i];
425 kb.bra = newBras[j];
426 Complex c;
427 c = algebra::ComplexHelper::mult(pk[i], pb[j]);
428 kb.p = algebra::ComplexHelper::mult(Iter->p, c);
429
430 if(fabs(creal(kb.p)) >= 0.0000001 || fabs(cimag(kb.p)) >= 0.0000001)
431 newDensity.push_back(kb);
432 }
433 }
434 }
435
436 density = newDensity;
437}
438
439void DensityList::applyConditionalOp(int condSpace, int cond, int space, algebra::mat& U)
440{
441 std::list <KetBra>::iterator Iter;
442
443 std::list <KetBra> newDensity;
444 Complex one=1;
445
446 for(Iter=density.begin(); Iter != density.end(); ++Iter)
447 {
448 std::vector < std::vector <int> > ket, bra;
449 std::vector <Complex> pk, pb;
450 if(Iter->ket[condSpace] == cond)
451 {
452 std::vector <int> k = Iter->ket;
453 for(int r=0; r<U.getRows(); ++r)
454 {
455 k[space] = r;
456 Complex c = U(r, Iter->ket[space]);
457 pk.push_back(c);
458 ket.push_back(k);
459 }
460 }
461 else
462 {
463 ket.push_back(Iter->ket);
464 pk.push_back(one);
465 }
466
467 if(Iter->bra[condSpace] == cond)
468 {
469 std::vector <int> b = Iter->bra;
470 for(int r=0; r<U.getRows(); ++r)
471 {
472 b[space] = r;
473 Complex c = conj(U(r, Iter->bra[space]));
474
475 pb.push_back(c);
476 bra.push_back(b);
477 }
478 }
479 else
480 {
481 bra.push_back(Iter->bra);
482 pb.push_back(one);
483 }
484
485 for(unsigned int i=0; i<ket.size(); ++i)
486 {
487 for(unsigned int j=0; j<bra.size(); ++j)
488 {
489 KetBra kb;
490 kb.ket = ket[i];
491 kb.bra = bra[j];
492 Complex c;
493 c = algebra::ComplexHelper::mult(pk[i], pb[j]);
494 kb.p = algebra::ComplexHelper::mult(Iter->p, c);
495 if(creal(kb.p) != 0 || cimag(kb.p) != 0)
496 newDensity.push_back(kb);
497 }
498 }
499 }
500
501 density = newDensity;
502}
503
504void DensityList::applyOp(int space, algebra::mat& U)
505{
506 std::list <KetBra>::iterator Iter;
507
508 std::list <KetBra> newDensity;
509 Complex one=1;
510 for(Iter=density.begin(); Iter != density.end(); ++Iter)
511 {
512 std::vector < std::vector <int> > ket, bra;
513 std::vector <Complex> pk, pb;
514 //if(Iter->ket[condSpace] == cond)
515 {
516 std::vector <int> k = Iter->ket;
517 for(int r=0; r<U.getRows(); ++r)
518 {
519 k[space] = r;
520 Complex c = U(r, Iter->ket[space]);
521 pk.push_back(c);
522 ket.push_back(k);
523 }
524 }
525 /*else
526 {
527 ket.push_back(Iter->ket);
528 pk.push_back(one);
529 }*/
530
531 //if(Iter->bra[condSpace] == cond)
532 {
533 std::vector <int> b = Iter->bra;
534 for(int r=0; r<U.getRows(); ++r)
535 {
536 b[space] = r;
537 Complex c = conj(U(r, Iter->bra[space]));
538
539 pb.push_back(c);
540 bra.push_back(b);
541 }
542 }
543 /*else
544 {
545 bra.push_back(Iter->bra);
546 pb.push_back(one);
547 }*/
548
549 for(unsigned int i=0; i<ket.size(); ++i)
550 {
551 for(unsigned int j=0; j<bra.size(); ++j)
552 {
553 KetBra kb;
554 kb.ket = ket[i];
555 kb.bra = bra[j];
556 Complex c;
557 c = algebra::ComplexHelper::mult(pk[i], pb[j]);
558 kb.p = algebra::ComplexHelper::mult(Iter->p, c);
559 if(creal(kb.p) != 0 || cimag(kb.p) != 0)
560 newDensity.push_back(kb);
561 }
562 }
563 }
564
565 density = newDensity;
566}
567
568// WK: Added for GA+prac-QKD project - very much a hack specific to this project
569// assumes transitSpace is the index for the T wire; T+1 is the E guess wire (must be dim 2)
570// and T+2 is arbitrary dimension (Eaux)
571void DensityList::applyOp(algebra::mat& U, int transitSpace)
572{
573 std::list <KetBra>::iterator Iter;
574
575 std::list <KetBra> newDensity;
576 Complex one=1;
577 for(Iter=density.begin(); Iter != density.end(); ++Iter)
578 {
579 std::vector < std::vector <int> > ket, bra;
580 std::vector <Complex> pk, pb;
581 {
582 std::vector <int> k = Iter->ket;
583 int n = dimension[transitSpace+2];
584 int a = Iter->ket[transitSpace+2];
585 int g = Iter->ket[transitSpace+1];
586 int t = Iter->ket[transitSpace];
587 int col = a+g*n+2*n*t;
588
589 for(int a2 = 0; a2<n; ++a2){
590 for(int g2=0; g2<2; ++g2){
591 for(int t2=0; t2<2; ++t2){
592 int row = a2+g2*n+2*n*t2;
593 Complex c = U(row, col);
594 k[transitSpace] = t2;
595 k[transitSpace+1] = g2;
596 k[transitSpace+2] = a2;
597 pk.push_back(c);
598 ket.push_back(k);
599 }
600 }
601 }
602 }
603
604 {
605 std::vector <int> b = Iter->bra;
606 int n = dimension[transitSpace+2];
607 int a = Iter->bra[transitSpace+2];
608 int g = Iter->bra[transitSpace+1];
609 int t = Iter->bra[transitSpace];
610 int col = a+g*n+2*n*t;
611
612 for(int a2 = 0; a2<n; ++a2){
613 for(int g2=0; g2<2; ++g2){
614 for(int t2=0; t2<2; ++t2){
615 int row = a2+g2*n+2*n*t2;
616 Complex c = conj(U(row, col));
617 b[transitSpace] = t2;
618 b[transitSpace+1] = g2;
619 b[transitSpace+2] = a2;
620 pb.push_back(c);
621 bra.push_back(b);
622 }
623 }
624 }
625 }
626
627 for(unsigned int i=0; i<ket.size(); ++i)
628 {
629 for(unsigned int j=0; j<bra.size(); ++j)
630 {
631 KetBra kb;
632 kb.ket = ket[i];
633 kb.bra = bra[j];
634 Complex c;
635 c = algebra::ComplexHelper::mult(pk[i], pb[j]);
636 kb.p = algebra::ComplexHelper::mult(Iter->p, c);
637 if(creal(kb.p) != 0 || cimag(kb.p) != 0)
638 newDensity.push_back(kb);
639 }
640 }
641 }
642
643 density = newDensity;
644}
645
646
647void DensityList::project(int space, int state, DensityList& output)
648{
649 std::list <KetBra>::iterator Iter;
650 output = *this;
651 output.density.clear();
652
653 for(Iter=density.begin(); Iter != density.end(); ++Iter)
654 {
655 if(Iter->ket[space] == Iter->bra[space] && Iter->ket[space] == state)
656 {
657 KetBra kb = *Iter;
658 output.density.push_back(kb);
659 }
660 }
661}
662
663void DensityList::project(int space, int state)
664{
665 std::list <KetBra>::iterator Iter;
666 std::list <KetBra> newDensity;
667
668 for(Iter=density.begin(); Iter != density.end(); ++Iter)
669 {
670 if(Iter->ket[space] == Iter->bra[space] && Iter->ket[space] == state)
671 {
672 KetBra kb = *Iter;
673 newDensity.push_back(kb);
674 }
675 }
676
677 density = newDensity;
678}
679
680void DensityList::applyHadamard(int space)
681{
682 algebra::mat H;
683 H.create(2);
684 H(0,0) = 1.0/sqrt(2.0);
685 H(0,1) = 1.0/sqrt(2.0);
686 H(1,0) = 1.0/sqrt(2.0);
687 H(1,1) = -1.0/sqrt(2.0);
688 applyOp(space, H);
689}
690
691void DensityList::applyRotation(int space, double rotation)
692{
693 // this might be more efficient if we just go through list...
694 algebra::mat R;
695 R.create(2);
696 R(0,0) = 1;
697 R(0,1) = 0;
698 R(1,0) = 0;
699 R(1,1) = cexp(rotation);
700 applyOp(space, R);
701}
702
703void DensityList::applySU2(int space, double p, double theta, double psi)
704{
705 if(p > 1)
706 p = 1;
707 if(p < 0)
708 p = 0;
709 // this might be more efficient if we just go through list...
710 algebra::mat R;
711 R.create(2);
712 R(0,0) = sqrt(p)*cexp(I*theta);
713 R(0,1) = -sqrt(1-p)*cexp(-I*psi);
714 R(1,0) = sqrt(1-p)*cexp(I*psi);
715 R(1,1) = sqrt(p)*cexp(-I*theta);
716
717 //R.print(std::cout);
718 applyOp(space, R);
719}
720
721
722void DensityList::applyHadamard(int target, int control)
723{
724 algebra::mat H;
725 H.create(2);
726 H(0,0) = 1.0/sqrt(2.0);
727 H(0,1) = 1.0/sqrt(2.0);
728 H(1,0) = 1.0/sqrt(2.0);
729 H(1,1) = -1.0/sqrt(2.0);
730 if(control >= 0)
731 applyConditionalOp(control, 1, target, H);
732 else
733 applyOp(target, H);
734}
735
736void DensityList::applyPiOver8(int target, int control)
737{
738 algebra::mat H;
739 H.create(2);
740 H(0,0) = 1.0;
741 H(0,1) = 0;
742 H(1,0) = 0;
743 H(1,1) = cos(3.1415/4.0) + I*sin(3.1415/4.0);
744 if(control >= 0)
745 applyConditionalOp(control, 1, target, H);
746 else
747 applyOp(target, H);
748}
749
750
751void DensityList::applySU2(int target, int control, double p, double theta, double psi)
752{
753 if(p > 1)
754 p = 1;
755 if(p < 0)
756 p = 0;
757 // this might be more efficient if we just go through list...
758 algebra::mat R;
759 R.create(2);
760 R(0,0) = sqrt(p)*cexp(I*theta);
761 R(0,1) = -sqrt(1-p)*cexp(-I*psi);
762 R(1,0) = sqrt(1-p)*cexp(I*psi);
763 R(1,1) = sqrt(p)*cexp(-I*theta);
764
765 //R.print(std::cout);
766 if(control >= 0)
767 applyConditionalOp(control, 1, target, R);
768 else
769 applyOp(target, R);
770}
771
772void DensityList::applyNOT(int target, int control)
773{
774 if(control >= 0)
775 CNOT(control, target);
776 else
777 NOT(target);
778}
779
780
781
782
783void DensityList::CNOT(int controlSpace, int targetSpace)
784{
785 if(controlSpace == targetSpace)
786 return;
787 std::list <KetBra>::iterator Iter;
788 //std::list <KetBra> newDensity;
789
790 for(Iter=density.begin(); Iter != density.end(); ++Iter)
791 {
792 if(Iter->ket[controlSpace] == 1)
793 Iter->ket[targetSpace] = 1-Iter->ket[targetSpace];
794 if(Iter->bra[controlSpace] == 1)
795 Iter->bra[targetSpace] = 1-Iter->bra[targetSpace];
796 }
797}
798
799void DensityList::NOT(int space)
800{
801 std::list <KetBra>::iterator Iter;
802 //std::list <KetBra> newDensity;
803
804 for(Iter=density.begin(); Iter != density.end(); ++Iter)
805 {
806 Iter->ket[space] = 1-Iter->ket[space];
807 Iter->bra[space] = 1-Iter->bra[space];
808 }
809}
810
811void DensityList::splitAndSave(double p1, double p2, int space)
812{
813 std::list <KetBra>::iterator Iter;
814 std::list <KetBra> newDensity;
815
816 for(Iter = density.begin(); Iter != density.end(); ++Iter)
817 {
818 KetBra kb;
819 kb = *Iter;
820 kb.p *= p1;
821
822 newDensity.push_back(kb);
823 kb.ket[space] = 1;
824 kb.bra[space] = 1;
825 newDensity.push_back(kb);
826 }
827
828 density = newDensity;
829}
830void DensityList::swap(int space1, int space2)
831{
832 std::list <KetBra>::iterator Iter;
833
834 for(Iter = density.begin(); Iter != density.end(); ++Iter)
835 {
836 int temp = Iter->ket[space1];
837 Iter->ket[space1] = Iter->ket[space2];
838 Iter->ket[space2] = temp;
839
840 temp = Iter->bra[space1];
841 Iter->bra[space1] = Iter->bra[space2];
842 Iter->bra[space2] = temp;
843 }
844}
845
846double DensityList::entropy()
847{
848 algebra::mat M;
849 computeDensityMat(M);
850 return M.entropy();
851}
852
853double DensityList::ShannonEntropy()
854{
855 algebra::mat M;
856 computeDensityMat(M);
857 double sum = 0;
858 for(int i=0; i<M.getRows(); ++i){
859 if(fabs(cimag(M(i,i))) > 0.0000001){
860 std::cout << "Density List Error: Negative eigenvalue.\n";
861 throw std::string("Error");
862 }
863 double e = creal( M(i,i) );
864 sum -= e*SafeLog(e);
865 }
866 return sum;
867}
868
869void DensityList::measureAndSave(int measureSpace, int saveSpace)
870{
871 // assumes dim[saveSpace] >= dim[measureSpace]
872 std::list <KetBra>::iterator Iter;
873 std::list <KetBra> newDensity;
874
875 for(Iter = density.begin(); Iter != density.end(); ++Iter)
876 {
877 if(Iter->ket[measureSpace] == Iter->bra[measureSpace])
878 {
879 KetBra kb = *Iter;
880 kb.ket[saveSpace] = Iter->ket[measureSpace];
881 kb.bra[saveSpace] = kb.ket[saveSpace];
882 newDensity.push_back(kb);
883 }
884 }
885
886 density = newDensity;
887}
888
889void DensityList::measure(int measureSpace)
890{
891 // assumes dim[saveSpace] >= dim[measureSpace]
892 std::list <KetBra>::iterator Iter;
893 std::list <KetBra> newDensity;
894
895 for(Iter = density.begin(); Iter != density.end(); ++Iter)
896 {
897 if(Iter->ket[measureSpace] == Iter->bra[measureSpace])
898 {
899 KetBra kb = *Iter;
900 newDensity.push_back(kb);
901 }
902 }
903
904 density = newDensity;
905}
906
907double DensityList::calculatePr(int measureSpace, int state)
908{
909 // first |state><state| rho |state><state|:
910 std::list <KetBra>::iterator Iter;
911 std::list <KetBra> tempDensity;
912
913 for(Iter = density.begin(); Iter != density.end(); ++Iter)
914 {
915 if(Iter->ket[measureSpace] == state && Iter->ket[measureSpace] == Iter->bra[measureSpace])
916 {
917 KetBra kb = *Iter;
918 tempDensity.push_back(kb);
919 }
920 }
921
922 if(tempDensity.empty())
923 return 0.0;
924
925 // now calculate tr(tempDensity)
926 Complex p=0, c;
927
928 for(Iter = tempDensity.begin(); Iter != tempDensity.end(); ++Iter)
929 {
930 c = Iter->trace();
931 p += c;
932 }
933
934 // now calculate tr(density)
935 Complex p2=0;
936
937 for(Iter = density.begin(); Iter != density.end(); ++Iter)
938 {
939 c = Iter->trace();
940 p2 += c;
941 }
942
943 c = algebra::ComplexHelper::invert(p2);
944 p2 = algebra::ComplexHelper::mult(c, p);
945
946 if(cimag(p2) > 0.00000001 || cimag(p2) < -0.00000001)
947 throw std::string("Trace error.");
948 return creal(p2);
949}
950
951double DensityList::trace()
952{
953 std::list <KetBra>::iterator Iter;
954 Complex p2=0;
955
956 for(Iter = density.begin(); Iter != density.end(); ++Iter)
957 p2 += Iter->trace();;
958
959 if(cimag(p2) > 0.00000001 || cimag(p2) < -0.00000001)
960 throw std::string("Trace error.");
961 return creal(p2);
962}
963
964double DensityList::calculatePr(int space1, int state1, int space2, int state2)
965{
966 // first |state><state| rho |state><state|:
967 std::list <KetBra>::iterator Iter;
968 std::list <KetBra> tempDensity;
969
970 for(Iter = density.begin(); Iter != density.end(); ++Iter)
971 {
972 if(Iter->ket[space1] == state1 && Iter->ket[space1] == Iter->bra[space1] &&
973 Iter->ket[space2] == state2 && Iter->ket[space2] == Iter->bra[space2])
974 {
975 KetBra kb = *Iter;
976 tempDensity.push_back(kb);
977 }
978 }
979
980 if(tempDensity.empty())
981 return 0.0;
982
983 // now calculate tr(tempDensity)
984 Complex p=0, c;
985
986 for(Iter = tempDensity.begin(); Iter != tempDensity.end(); ++Iter)
987 {
988 c = Iter->trace();
989 p += c;
990 }
991
992 // now calculate tr(density)
993 Complex p2=0;
994
995 for(Iter = density.begin(); Iter != density.end(); ++Iter)
996 {
997 c = Iter->trace();
998 p2 += c;
999 }
1000
1001 c = algebra::ComplexHelper::invert(p2);
1002 p2 = algebra::ComplexHelper::mult(c, p);
1003
1004 if(cimag(p2) > 0.00000001 || cimag(p2) < -0.00000001)
1005 throw std::string("Trace error.");
1006 return creal(p2);
1007}
1008
1009double DensityList::calculatePr(const std::vector <int>& spaceList, const std::vector <int>& stateList)
1010{
1011 // first |state><state| rho |state><state|:
1012 std::list <KetBra>::iterator Iter;
1013 std::list <KetBra> tempDensity;
1014
1015 for(Iter = density.begin(); Iter != density.end(); ++Iter)
1016 {
1017 bool measure = true;
1018 for(unsigned int i=0; i<spaceList.size(); ++i)
1019 {
1020 if(Iter->ket[spaceList[i]] != stateList[i])
1021 {
1022 measure = false;
1023 break;
1024 }
1025 }
1026 if(measure)
1027 {
1028 KetBra kb = *Iter;
1029 tempDensity.push_back(kb);
1030 }
1031 }
1032
1033 if(tempDensity.empty())
1034 return 0.0;
1035
1036 // now calculate tr(tempDensity)
1037 Complex p=0, c;
1038
1039 for(Iter = tempDensity.begin(); Iter != tempDensity.end(); ++Iter)
1040 {
1041 c = Iter->trace();
1042 p += c;
1043 }
1044
1045 // now calculate tr(density)
1046 Complex p2=0;
1047
1048 for(Iter = density.begin(); Iter != density.end(); ++Iter)
1049 {
1050 c = Iter->trace();
1051 p2 += c;
1052 }
1053
1054 c = algebra::ComplexHelper::invert(p2);
1055 p2 = algebra::ComplexHelper::mult(c, p);
1056
1057 if(cimag(p2) > 0.00000001 || cimag(p2) < -0.00000001)
1058 throw std::string("Trace error.");
1059 return creal(p2);
1060}
1061
1063{
1064 int n = 1;
1065 for(unsigned int i=0; i<density.begin()->ket.size(); ++i)
1066 {
1067 if(density.begin()->ket[i] != -1)
1068 n *= dimension[i];
1069 }
1070
1071 int basisIndex = dimension.size()-1;
1072 // basisIndex = last index not traced out!
1073 for(basisIndex=dimension.size()-1; basisIndex>=0; --basisIndex){
1074 if(density.begin()->ket[basisIndex] != -1)
1075 break;
1076 }
1077 output.create(n);
1078 output.zero();
1079
1080 //int count = density.size();
1081 //int counter = 0;
1082
1083 std::list <KetBra>::iterator Iter;
1084 for(Iter = density.begin(); Iter != density.end(); ++Iter)
1085 {
1086 //if(count > 5000 && counter%500 == 0)
1087 // std::cout << "\t" << counter << "/" << count << "\n";
1088 //++counter;
1089 // change basis to be |i>|e><j|<e|
1090 int indexI=0, indexJ=0;
1091 for(unsigned int i=0; i<Iter->ket.size(); ++i)
1092 {
1093 if(Iter->ket[i] == -1 || i == basisIndex) continue;
1094 indexI = indexI*dimension[i] + Iter->ket[i];
1095 indexJ = indexJ*dimension[i] + Iter->bra[i];
1096 }
1097
1098 int startRow = indexI*dimension[basisIndex];
1099 int startCol = indexJ*dimension[basisIndex];
1100 int i = Iter->ket[basisIndex];
1101 int j = Iter->bra[basisIndex];
1102
1103 output(startRow+i, startCol+j) += Iter->p;
1115 }
1116
1117 Complex tr = output.trace();
1118 Complex tr2 = algebra::ComplexHelper::invert(tr);
1119 output.multiplyScalar(tr2);
1120}
1121
1122void DensityList::computeDensityMat(algebra::mat& output)
1123{
1124 // first determine size:
1125 int n = 1;
1126 for(unsigned int i=0; i<density.begin()->ket.size(); ++i)
1127 {
1128 if(density.begin()->ket[i] != -1)
1129 n *= dimension[i];
1130 }
1131
1132
1133 output.create(n);
1134 output.zero();
1135
1136 std::list <KetBra>::iterator Iter;
1137 algebra::mat k, b, t, t2, temp, temp2;
1138
1139 int count = density.size();
1140 int counter = 0;
1141
1142 //double smallRe = fabs(density.begin()->p.real);
1143 for(Iter = density.begin(); Iter != density.end(); ++Iter)
1144 {
1145 //if(count > 5000 && counter%500 == 0)
1146 // std::cout << "\t" << counter << "/" << count << "\n";
1147 //if(fabs(Iter->p.real) < smallRe)
1148 // smallRe = fabs(Iter->p.real);
1149 ++counter;
1150 k.create(1, 1);
1151 b.create(1, 1);
1152 k(0,0) = 1.0;
1153 b(0,0) = 1.0;
1154 for(unsigned int i=0; i<Iter->ket.size(); ++i)
1155 {
1156 if(Iter->ket[i] == -1) continue;
1157
1158 t.create(dimension[i], 1);
1159 t2.create(1, dimension[i]);
1160 t.zero();
1161 t(Iter->ket[i], 0) = 1.0;
1162
1163 k.tensor(&t, &temp);
1164 k = temp;
1165
1166 t2.zero();
1167 t2(0, Iter->bra[i]) = 1.0;
1168
1169 b.tensor(&t2, &temp);
1170 b = temp;
1171
1172 }
1173
1174 k.multiply(b, temp);
1175 temp.multiplyScalar(Iter->p);
1176
1177 output.add(&temp, &temp2);
1178 output = temp2;
1179 }
1180
1181 Complex tr = output.trace();
1182 Complex tr2 = algebra::ComplexHelper::invert(tr);
1183 output.multiplyScalar(tr2);
1184
1185 //std::cout << "\t\tsmallRe = " << smallRe << "\n";
1186}
1187
1188}
void computeDensityMatFast(algebra::mat &output)
Definition: Quantum.cpp:1062