line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Quantum::Entanglement; |
2
|
1
|
|
|
1
|
|
8323
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
39
|
|
3
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
29
|
|
4
|
1
|
|
|
1
|
|
6
|
use Carp; |
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
76
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
BEGIN { |
7
|
1
|
|
|
1
|
|
4
|
use Exporter (); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
18
|
|
8
|
1
|
|
|
1
|
|
1139
|
use Math::Complex; |
|
1
|
|
|
|
|
18370
|
|
|
1
|
|
|
|
|
328
|
|
9
|
1
|
|
|
1
|
|
3
|
my @M_Complex = qw(i Re Im rho theta arg cplx cplxe); |
10
|
1
|
|
|
|
|
2
|
our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); |
11
|
1
|
|
|
|
|
2
|
$VERSION = 0.32; |
12
|
1
|
|
|
|
|
11
|
@ISA = qw(Exporter); |
13
|
1
|
|
|
|
|
2
|
@EXPORT = qw(&entangle &p_op &p_func &q_logic |
14
|
|
|
|
|
|
|
&save_state &restore_state); |
15
|
1
|
|
|
|
|
8
|
%EXPORT_TAGS = (DEFAULT => [@EXPORT], |
16
|
|
|
|
|
|
|
complex => [@M_Complex], |
17
|
|
|
|
|
|
|
QFT => [qw(&QFT)],); |
18
|
1
|
|
|
|
|
3353
|
@EXPORT_OK = (@M_Complex, '&QFT'); |
19
|
|
|
|
|
|
|
} |
20
|
|
|
|
|
|
|
our (@EXPORT_OK, @EXPORT); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
$Quantum::Entanglement::destroy = 1; # true=> p(0) states stomped on |
23
|
|
|
|
|
|
|
$Quantum::Entanglement::conform = 0; # true=> strives for truth when observing |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
## Contents: |
26
|
|
|
|
|
|
|
# Constructors |
27
|
|
|
|
|
|
|
# Utility Routines |
28
|
|
|
|
|
|
|
# Overload table |
29
|
|
|
|
|
|
|
# Overload routines |
30
|
|
|
|
|
|
|
# parallel operators and functions |
31
|
|
|
|
|
|
|
# methods for saving and restoring state |
32
|
|
|
|
|
|
|
# pod |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# =begin pretty pictures |
35
|
|
|
|
|
|
|
# |
36
|
|
|
|
|
|
|
# Things look a bit like this... |
37
|
|
|
|
|
|
|
# |
38
|
|
|
|
|
|
|
# $variable = [ref to var which itself refs to an annon array (the universe), |
39
|
|
|
|
|
|
|
# offset of values of variable within universe, |
40
|
|
|
|
|
|
|
# ref to var which itself refs to an annon array (the offsets)]; |
41
|
|
|
|
|
|
|
# |
42
|
|
|
|
|
|
|
# $offsets = [refs to all the offsets in a given universe, ...] |
43
|
|
|
|
|
|
|
# $universe= [ [prob1,val1,prob2,val2], |
44
|
|
|
|
|
|
|
# [prob1,val1,prob2,val2], etc. ] |
45
|
|
|
|
|
|
|
# |
46
|
|
|
|
|
|
|
# =cut |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# creates a new set of universes |
49
|
|
|
|
|
|
|
sub _new { |
50
|
6
|
|
|
6
|
|
11
|
my $universe = []; |
51
|
6
|
|
|
|
|
9
|
my $offsets = []; |
52
|
6
|
|
|
|
|
12
|
my $var = [\$universe,1,\$offsets]; |
53
|
6
|
|
|
|
|
13
|
$offsets->[0] = \ $var->[1]; |
54
|
6
|
|
|
|
|
16
|
while (@_) { |
55
|
10
|
|
|
|
|
32
|
push @$universe, [shift,shift]; |
56
|
|
|
|
|
|
|
} |
57
|
6
|
|
|
|
|
16
|
bless $var, 'Quantum::Entanglement'; |
58
|
6
|
|
|
|
|
17
|
return $var; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# add a variable without adding values (ie. a derived value) |
62
|
|
|
|
|
|
|
# returns the new variable |
63
|
|
|
|
|
|
|
sub _add { |
64
|
15
|
|
|
15
|
|
17
|
my $current = $_[0]; |
65
|
15
|
|
|
|
|
14
|
my $universe = ${ $current->[0]}; |
|
15
|
|
|
|
|
25
|
|
66
|
15
|
|
|
|
|
18
|
my $offset = scalar(@{$universe->[0]}) + 1; |
|
15
|
|
|
|
|
26
|
|
67
|
15
|
|
|
|
|
18
|
my $var= [\$universe,$offset,\ ${$current->[2]}]; |
|
15
|
|
|
|
|
35
|
|
68
|
15
|
|
|
|
|
18
|
push @{${$current->[2]}} , \$var->[1]; |
|
15
|
|
|
|
|
17
|
|
|
15
|
|
|
|
|
32
|
|
69
|
15
|
|
|
|
|
37
|
bless $var, 'Quantum::Entanglement'; |
70
|
15
|
|
|
|
|
27
|
return $var; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# joins together two previously unconnected universes |
74
|
|
|
|
|
|
|
# takes two variables as args, gets the universes from those. |
75
|
|
|
|
|
|
|
# should be used to modify objects in place. |
76
|
|
|
|
|
|
|
sub _join { |
77
|
15
|
|
|
15
|
|
16
|
my ($uni1,$uni2) = (${$_[0]->[0]},${$_[1]->[0]}); |
|
15
|
|
|
|
|
37
|
|
|
15
|
|
|
|
|
28
|
|
78
|
15
|
100
|
|
|
|
50
|
return () if $uni1 == $uni2; |
79
|
2
|
|
|
|
|
4
|
my $universe = []; |
80
|
2
|
|
|
|
|
4
|
foreach my $s2 (@$uni2) { |
81
|
4
|
|
|
|
|
8
|
foreach my $s1 (@$uni1) { |
82
|
8
|
|
|
|
|
23
|
push @$universe, [@$s1,@$s2]; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
} |
85
|
2
|
|
|
|
|
3
|
my $offsets1 = ${$_[0]->[2]}; |
|
2
|
|
|
|
|
5
|
|
86
|
2
|
|
|
|
|
12
|
my $offsets2 = ${$_[1]->[2]}; |
|
2
|
|
|
|
|
4
|
|
87
|
2
|
|
|
|
|
3
|
my $extra = scalar(@{$uni1->[0]}); |
|
2
|
|
|
|
|
4
|
|
88
|
2
|
|
|
|
|
5
|
push @$offsets1, map {$$_+=$extra; $_} @$offsets2; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
4
|
|
89
|
2
|
|
|
|
|
3
|
${$_[1]->[2]} = $offsets1; |
|
2
|
|
|
|
|
3
|
|
90
|
2
|
|
|
|
|
3
|
${$_[0]->[0]} = $universe; |
|
2
|
|
|
|
|
4
|
|
91
|
2
|
|
|
|
|
2
|
${$_[1]->[0]} = $universe; |
|
2
|
|
|
|
|
4
|
|
92
|
2
|
|
|
|
|
6
|
return (1); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# exported constructor |
96
|
|
|
|
|
|
|
sub entangle { |
97
|
6
|
|
|
6
|
1
|
788
|
return _new(@_); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
## Utility routines |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# a view of global state space, might still show historical states which |
103
|
|
|
|
|
|
|
# are no longer accessable, does not count as observation |
104
|
|
|
|
|
|
|
sub show_states { |
105
|
0
|
|
|
0
|
1
|
0
|
my $rt; |
106
|
0
|
|
|
|
|
0
|
my $var = shift; |
107
|
0
|
|
|
|
|
0
|
my $universe = ${$var->[0]}; |
|
0
|
|
|
|
|
0
|
|
108
|
0
|
0
|
|
|
|
0
|
if ($_[0]) { |
109
|
0
|
|
|
|
|
0
|
foreach (@$universe) { my $t; |
|
0
|
|
|
|
|
0
|
|
110
|
0
|
0
|
|
|
|
0
|
$rt .= (++$t % 2) ? "$_|" : overload::StrVal($_).">\t" foreach @$_; |
111
|
0
|
|
|
|
|
0
|
$rt .= "\n"; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
else { |
115
|
0
|
|
|
|
|
0
|
my $os = $var->[1]; |
116
|
|
|
|
|
|
|
$rt .= $_->[$os-1]."|".overload::StrVal($_->[$os]).">\t" |
117
|
0
|
|
|
|
|
0
|
foreach @$universe; |
118
|
0
|
|
|
|
|
0
|
substr($rt,-1,1,"\n"); |
119
|
|
|
|
|
|
|
} |
120
|
0
|
|
|
|
|
0
|
return $rt; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# egads! (and don't tell anyone about the grep, it's a secret) |
124
|
|
|
|
|
|
|
sub DESTROY { |
125
|
21
|
|
|
21
|
|
3854
|
my ($universe, $offsets) = (${$_[0]->[0]}, ${$_[0]->[2]}); |
|
21
|
|
|
|
|
57
|
|
|
21
|
|
|
|
|
42
|
|
126
|
21
|
|
|
|
|
38
|
my $os = $_[0]->[1]; |
127
|
21
|
|
|
|
|
138
|
splice(@$_,$os-1,2) foreach @$universe; |
128
|
21
|
50
|
|
|
|
44
|
@$offsets = grep {if ($$_ != $os) {$$_ -= 2 if $$_ > $os;1;} else {0;}} |
|
53
|
100
|
|
|
|
86
|
|
|
32
|
|
|
|
|
58
|
|
|
32
|
|
|
|
|
45
|
|
|
21
|
|
|
|
|
57
|
|
129
|
|
|
|
|
|
|
@$offsets; |
130
|
21
|
50
|
|
|
|
80
|
_rationalise_states([\$universe]) |
131
|
|
|
|
|
|
|
if $Quantum::Entanglement::destroy; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# takes two non normalised probabilities and returns true with prob(1/1+2) |
135
|
|
|
|
|
|
|
sub _sel_output { |
136
|
0
|
|
|
0
|
|
0
|
my ($c, $d) = @_; |
137
|
0
|
|
|
|
|
0
|
$c = abs($c)**2; |
138
|
0
|
|
|
|
|
0
|
$d = abs($d)**2; |
139
|
0
|
0
|
|
|
|
0
|
return rand(1) < ($c/($c+$d)) ? 1 : 0; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# Gets a ref to a hash of complex probs, produces ref to hash of sequential |
143
|
|
|
|
|
|
|
# probs and ref to array of ordering. |
144
|
|
|
|
|
|
|
sub _normalise { |
145
|
15
|
|
|
15
|
|
20
|
my $hr = $_[0]; |
146
|
15
|
|
|
|
|
23
|
my $h2 = {}; |
147
|
15
|
|
|
|
|
17
|
my $muts = [keys %{$hr}]; |
|
15
|
|
|
|
|
39
|
|
148
|
15
|
|
|
|
|
20
|
my $sum = 0; |
149
|
15
|
|
|
|
|
16
|
foreach (values %{$hr}) { |
|
15
|
|
|
|
|
35
|
|
150
|
15
|
|
|
|
|
44
|
$sum += abs($_)**2; |
151
|
|
|
|
|
|
|
} |
152
|
15
|
50
|
|
|
|
345
|
if ($sum <= 0) { |
153
|
0
|
|
|
|
|
0
|
croak "$0: Cannot behave probabilistically with -ve probs"; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
else { |
156
|
15
|
|
|
|
|
14
|
my $cum; |
157
|
15
|
|
|
|
|
37
|
@{$h2}{ @{$muts} } = map {$cum +=abs($_)**2; |
|
15
|
|
|
|
|
21
|
|
|
15
|
|
|
|
|
38
|
|
|
15
|
|
|
|
|
25
|
|
158
|
15
|
|
|
|
|
18
|
$cum / $sum } @{$hr}{ @{$muts} }; |
|
15
|
|
|
|
|
171
|
|
|
15
|
|
|
|
|
22
|
|
159
|
15
|
|
|
|
|
39
|
return ($h2, $muts); |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# this builds up a multi-layered hash so as to find the unique sets of |
164
|
|
|
|
|
|
|
# states, it then uses _unravel to get them back out of the hash |
165
|
|
|
|
|
|
|
sub _rationalise_states { |
166
|
21
|
|
|
21
|
|
34
|
my $universe = ${$_[0]->[0]}; |
|
21
|
|
|
|
|
34
|
|
167
|
21
|
|
|
|
|
27
|
my $len = scalar(@{$universe->[0]})/2; |
|
21
|
|
|
|
|
40
|
|
168
|
21
|
|
|
|
|
47
|
my @p_os = map {$_*2 } (0..$len-1); |
|
32
|
|
|
|
|
66
|
|
169
|
21
|
|
|
|
|
35
|
my @v_os = map {$_*2+1} (0..$len-1); |
|
32
|
|
|
|
|
67
|
|
170
|
21
|
|
|
|
|
33
|
my $foo = {}; |
171
|
21
|
|
|
|
|
59
|
foreach my $state (@$universe) { # build an icky data structure |
172
|
27
|
|
|
|
|
573
|
my $tref = $foo; |
173
|
27
|
|
|
|
|
44
|
foreach (@v_os) { |
174
|
44
|
50
|
|
|
|
84
|
my $val = ref($state->[$_]) ? overload::StrVal($state->[$_]) |
175
|
|
|
|
|
|
|
: $state->[$_]; |
176
|
44
|
100
|
|
|
|
79
|
if ($_==2*$len-1) { # last level of the structure |
177
|
23
|
100
|
|
|
|
36
|
if (exists $tref->{$val}) { |
178
|
6
|
|
|
|
|
7
|
my @temp = @{$state}[@p_os]; |
|
6
|
|
|
|
|
20
|
|
179
|
6
|
|
|
|
|
10
|
$_+=shift @temp foreach @{$tref->{$val}}[@p_os]; |
|
6
|
|
|
|
|
25
|
|
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
else { |
182
|
17
|
|
|
|
|
18
|
$tref->{$val} = [@{$state}]; |
|
17
|
|
|
|
|
95
|
|
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
else { # an intermediate level |
186
|
21
|
100
|
|
|
|
40
|
if (exists $tref->{$val}) { |
187
|
6
|
|
|
|
|
14
|
$tref = $tref->{$val}; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
else { |
190
|
15
|
|
|
|
|
48
|
$tref = $tref->{$val} = {}; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
# do something with it... |
196
|
21
|
|
|
|
|
137
|
@$universe =(); |
197
|
21
|
|
|
|
|
23
|
while (1) { |
198
|
38
|
|
|
|
|
64
|
my $aref = _unravel($foo); |
199
|
38
|
100
|
|
|
|
76
|
last unless $aref; |
200
|
17
|
|
|
|
|
27
|
push @$universe, $aref; |
201
|
|
|
|
|
|
|
} |
202
|
21
|
|
|
|
|
209
|
return $universe; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub _unravel { |
206
|
38
|
|
|
38
|
|
40
|
my $tref = $_[0]; |
207
|
38
|
100
|
|
|
|
99
|
return undef unless (scalar keys %$tref); |
208
|
17
|
|
|
|
|
19
|
my @hrs; |
209
|
17
|
|
|
|
|
18
|
my($last_ref, $val); |
210
|
17
|
|
|
|
|
19
|
do { |
211
|
32
|
|
|
|
|
34
|
$last_ref = $tref; |
212
|
32
|
|
|
|
|
78
|
($val,$tref) = %$tref; |
213
|
32
|
|
|
|
|
145
|
unshift @hrs, $val, $last_ref; |
214
|
|
|
|
|
|
|
} until (ref($tref) eq 'ARRAY'); |
215
|
17
|
|
|
|
|
18
|
delete ${$last_ref}{$val}; |
|
17
|
|
|
|
|
30
|
|
216
|
17
|
|
|
|
|
26
|
splice @hrs, 0,2; |
217
|
17
|
|
|
|
|
47
|
while (@hrs) { |
218
|
15
|
|
|
|
|
23
|
my $val = shift @hrs; |
219
|
15
|
|
|
|
|
56
|
my $h = shift @hrs; |
220
|
15
|
50
|
|
|
|
17
|
delete ${$h}{$val} if scalar(keys %{${$h}{$val}}) < 1; |
|
15
|
|
|
|
|
46
|
|
|
15
|
|
|
|
|
15
|
|
|
15
|
|
|
|
|
50
|
|
221
|
|
|
|
|
|
|
} |
222
|
17
|
|
|
|
|
45
|
return $tref; |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
## |
227
|
|
|
|
|
|
|
# Overloading. Everything except for assignment operators |
228
|
|
|
|
|
|
|
# are overloaded specifically. Need to specifically overload a lot |
229
|
|
|
|
|
|
|
# of stuff so that pruning of states can happen as soon as poss |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
use overload |
232
|
1
|
|
|
1
|
|
12
|
'+' => sub { binop(@_, sub{$_[0] + $_[1]} ) }, |
|
1
|
|
|
|
|
64
|
|
233
|
1
|
|
|
1
|
|
22
|
'*' => sub { binop(@_, sub{$_[0] * $_[1]} ) }, |
|
4
|
|
|
|
|
158
|
|
234
|
1
|
|
|
1
|
|
12
|
'-' => sub { binop(@_, sub{$_[0] - $_[1]} ) }, |
|
1
|
|
|
|
|
81
|
|
235
|
1
|
|
|
1
|
|
14
|
'/' => sub { binop(@_, sub{$_[0] / $_[1]} ) }, |
|
1
|
|
|
|
|
63
|
|
236
|
1
|
|
|
1
|
|
13
|
'**' => sub { binop(@_, sub{$_[0] **$_[1]} ) }, |
|
1
|
|
|
|
|
101
|
|
237
|
1
|
|
|
1
|
|
9
|
'%' => sub { binop(@_, sub{$_[0] % $_[1]} ) }, |
|
1
|
|
|
|
|
50
|
|
238
|
1
|
|
|
1
|
|
12
|
'x' => sub { binop(@_, sub{$_[0] x $_[1]} ) }, |
|
1
|
|
|
|
|
69
|
|
239
|
1
|
|
|
1
|
|
11
|
'.' => sub { binop(@_, sub{$_[0] . $_[1]} ) }, |
|
1
|
|
|
|
|
55
|
|
240
|
1
|
|
|
1
|
|
11
|
'<<' => sub { binop(@_, sub{$_[0] <<$_[1]} ) }, |
|
1
|
|
|
|
|
61
|
|
241
|
1
|
|
|
1
|
|
11
|
'>>' => sub { binop(@_, sub{$_[0] >>$_[1]} ) }, |
|
1
|
|
|
|
|
60
|
|
242
|
1
|
|
|
1
|
|
11
|
'&' => sub { binop(@_, sub{$_[0] & $_[1]} ) }, |
|
1
|
|
|
|
|
70
|
|
243
|
1
|
|
|
1
|
|
11
|
'|' => sub { binop(@_, sub{$_[0] | $_[1]} ) }, |
|
1
|
|
|
|
|
63
|
|
244
|
0
|
|
|
0
|
|
0
|
'^' => sub { binop(@_, sub{$_[0] ^ $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
245
|
0
|
|
|
0
|
|
0
|
'~' => sub { unnop($_[0], sub { ~$_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
246
|
0
|
|
|
0
|
|
0
|
'neg'=> sub { unnop($_[0], sub { -$_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
247
|
0
|
|
|
0
|
|
0
|
'!' => sub { unnop($_[0], sub { !$_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
248
|
0
|
|
|
0
|
|
0
|
'++' => sub { mutop($_[0], sub {++$_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
249
|
0
|
|
|
0
|
|
0
|
'--' => sub { mutop($_[0], sub {--$_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
250
|
0
|
|
|
0
|
|
0
|
'<' => sub { bioop(@_, sub{$_[0] < $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
251
|
0
|
|
|
0
|
|
0
|
'>' => sub { bioop(@_, sub{$_[0] > $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
252
|
0
|
|
|
0
|
|
0
|
'<=' => sub { bioop(@_, sub{$_[0] <= $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
253
|
0
|
|
|
0
|
|
0
|
'>=' => sub { bioop(@_, sub{$_[0] >= $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
254
|
0
|
|
|
0
|
|
0
|
'==' => sub { bioop(@_, sub{$_[0] == $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
255
|
0
|
|
|
0
|
|
0
|
'!=' => sub { bioop(@_, sub{$_[0] != $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
256
|
0
|
|
|
0
|
|
0
|
'lt' => sub { bioop(@_, sub{$_[0] lt $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
257
|
0
|
|
|
0
|
|
0
|
'le' => sub { bioop(@_, sub{$_[0] le $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
258
|
0
|
|
|
0
|
|
0
|
'ge' => sub { bioop(@_, sub{$_[0] ge $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
259
|
0
|
|
|
0
|
|
0
|
'gt' => sub { bioop(@_, sub{$_[0] gt $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
260
|
0
|
|
|
0
|
|
0
|
'eq' => sub { bioop(@_, sub{$_[0] eq $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
261
|
0
|
|
|
0
|
|
0
|
'ne' => sub { bioop(@_, sub{$_[0] ne $_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
262
|
0
|
|
|
0
|
|
0
|
'<=>'=> sub { binop(@_, sub{$_[0] <=>$_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
263
|
0
|
|
|
0
|
|
0
|
'cmp'=> sub { binop(@_, sub{$_[0] cmp$_[1]} ) }, |
|
0
|
|
|
|
|
0
|
|
264
|
0
|
|
|
0
|
|
0
|
'cos'=> sub { unnop($_[0], sub{ cos $_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
265
|
0
|
|
|
0
|
|
0
|
'sin'=> sub { unnop($_[0], sub{ sin $_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
266
|
0
|
|
|
0
|
|
0
|
'exp'=> sub { unnop($_[0], sub{ exp $_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
267
|
0
|
|
|
0
|
|
0
|
'abs'=> sub { unnop($_[0], sub{ abs $_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
268
|
0
|
|
|
0
|
|
0
|
'log'=> sub { unnop($_[0], sub{ log $_[0]} ) }, |
|
0
|
|
|
|
|
0
|
|
269
|
0
|
|
|
0
|
|
0
|
'sqrt'=>sub { unnop($_[0], sub{ sqrt $_[0]}) }, |
|
0
|
|
|
|
|
0
|
|
270
|
0
|
|
|
0
|
|
0
|
'atan2'=>sub{ binop(@_, sub{atan2($_[0], $_[1])} ) }, |
|
0
|
|
|
|
|
0
|
|
271
|
1
|
|
|
|
|
79
|
'&{}'=> \&sub_ent, |
272
|
|
|
|
|
|
|
'bool'=> \&bool_ent, q{""} => \&str_ent, '0+' => \&num_ent, |
273
|
|
|
|
|
|
|
'=' => \©_ent, |
274
|
1
|
|
|
1
|
|
13
|
'fallback' => 1; |
|
1
|
|
|
|
|
2
|
|
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
# copying (not observation, clones states, does not increase state space) |
277
|
|
|
|
|
|
|
sub copy_ent { |
278
|
0
|
|
|
0
|
0
|
0
|
my $os = $_[0]->[1]; |
279
|
0
|
|
|
|
|
0
|
my $val = $_[0]->_add; |
280
|
0
|
|
|
|
|
0
|
my $universe = ${$_[0]->[0]}; |
|
0
|
|
|
|
|
0
|
|
281
|
0
|
|
|
|
|
0
|
push(@$_, $_->[$os-1], $_->[$os]) foreach @$universe; |
282
|
0
|
|
|
|
|
0
|
return $val; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# running entangled subroutines |
286
|
|
|
|
|
|
|
sub sub_ent { |
287
|
0
|
|
|
0
|
0
|
0
|
my $obj = $_[0]; |
288
|
0
|
|
|
|
|
0
|
my $os = $obj->[1]; |
289
|
0
|
|
|
|
|
0
|
my $universe = ${$obj->[0]}; |
|
0
|
|
|
|
|
0
|
|
290
|
|
|
|
|
|
|
return sub { |
291
|
0
|
|
|
0
|
|
0
|
my $var = $obj->_add; |
292
|
0
|
|
|
|
|
0
|
foreach my $state (@$universe) { |
293
|
0
|
|
|
|
|
0
|
push(@$state, $state->[$os-1], |
294
|
|
|
|
|
|
|
scalar( $state->[$os]->(@_) )); |
295
|
|
|
|
|
|
|
} |
296
|
0
|
|
|
|
|
0
|
return $var; |
297
|
|
|
|
|
|
|
} |
298
|
0
|
|
|
|
|
0
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
# stringification (observation) |
301
|
|
|
|
|
|
|
sub str_ent { |
302
|
15
|
|
|
15
|
0
|
82
|
my $c = $_[0]; |
303
|
15
|
|
|
|
|
25
|
my $os = $c->[1]; |
304
|
15
|
|
|
|
|
16
|
my $universe = ${$c->[0]}; |
|
15
|
|
|
|
|
22
|
|
305
|
15
|
|
|
|
|
23
|
my %str_vals; |
306
|
|
|
|
|
|
|
# work out which state we want to retain |
307
|
15
|
|
|
|
|
21
|
foreach my $state (@$universe) { |
308
|
21
|
|
100
|
|
|
851
|
$str_vals{$state->[$os]} = $state->[$os-1] + ($str_vals{$state->[$os]}||0); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
15
|
|
|
|
|
1852
|
my ($hr, $ar) = _normalise(\%str_vals); |
312
|
15
|
|
|
|
|
83
|
my $rand = rand(1); |
313
|
15
|
|
|
|
|
14
|
my $rt; |
314
|
15
|
|
|
|
|
29
|
LOOP: foreach (@$ar) { |
315
|
15
|
50
|
|
|
|
13
|
if ( $rand < ${$hr}{$_}) { |
|
15
|
|
|
|
|
46
|
|
316
|
15
|
|
|
|
|
18
|
$rt = $_; |
317
|
15
|
|
|
|
|
33
|
last LOOP; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
# retain only that state |
321
|
15
|
|
|
|
|
25
|
my @retains; |
322
|
15
|
|
|
|
|
32
|
for (0..(@$universe-1)) { |
323
|
21
|
|
|
|
|
29
|
my $state = $universe->[$_]; |
324
|
21
|
|
|
|
|
28
|
my $foo = $state->[$os]; |
325
|
21
|
50
|
|
|
|
79
|
push(@retains, $_) if ("$foo" eq $rt); |
326
|
|
|
|
|
|
|
} |
327
|
15
|
50
|
|
|
|
35
|
if ($Quantum::Entanglement::destroy) { |
328
|
15
|
|
|
|
|
40
|
@$universe = @$universe[@retains]; |
329
|
15
|
|
|
|
|
135
|
return $rt; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# set all non retained states to zero probability, leave others alone |
333
|
0
|
|
|
|
|
0
|
my $next_retain = shift @retains; |
334
|
0
|
|
|
|
|
0
|
PURGE: foreach my $snum ( 0..(@$universe-1) ) { |
335
|
0
|
0
|
|
|
|
0
|
if ($snum == $next_retain) { |
336
|
0
|
|
0
|
|
|
0
|
$next_retain = shift(@retains) || -1; |
337
|
0
|
|
|
|
|
0
|
next PURGE; |
338
|
|
|
|
|
|
|
} |
339
|
0
|
|
|
|
|
0
|
my $state = ${$universe}[$snum]; |
|
0
|
|
|
|
|
0
|
|
340
|
0
|
|
|
|
|
0
|
$$state[$_] = 0 foreach grep {!($_ % 2)} (0..(@$state-1)) |
|
0
|
|
|
|
|
0
|
|
341
|
|
|
|
|
|
|
} |
342
|
0
|
|
|
|
|
0
|
return $rt; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# numification (have to coerce things into numbers then strings for |
346
|
|
|
|
|
|
|
# probability hash purposes, ick) (observation) |
347
|
|
|
|
|
|
|
sub num_ent { |
348
|
0
|
|
|
0
|
0
|
0
|
my $c = $_[0]; |
349
|
0
|
|
|
|
|
0
|
my $os = $c->[1]; |
350
|
0
|
|
|
|
|
0
|
my $universe = ${$c->[0]}; |
|
0
|
|
|
|
|
0
|
|
351
|
0
|
|
|
|
|
0
|
my %str_vals; |
352
|
|
|
|
|
|
|
# work out which state we want to retain |
353
|
0
|
|
|
|
|
0
|
foreach my $state (@$universe) { |
354
|
0
|
|
0
|
|
|
0
|
$str_vals{+$state->[$os]} = |
355
|
|
|
|
|
|
|
$state->[$os-1] + ($str_vals{+$state->[$os]}||0); |
356
|
|
|
|
|
|
|
} |
357
|
0
|
|
|
|
|
0
|
my ($hr, $ar) = _normalise(\%str_vals); |
358
|
0
|
|
|
|
|
0
|
my $rand = rand(1); |
359
|
0
|
|
|
|
|
0
|
my $rt; |
360
|
0
|
|
|
|
|
0
|
LOOP: foreach (@$ar) { |
361
|
0
|
0
|
|
|
|
0
|
if ( $rand < ${$hr}{$_}) { |
|
0
|
|
|
|
|
0
|
|
362
|
0
|
|
|
|
|
0
|
$rt = +$_; |
363
|
0
|
|
|
|
|
0
|
last LOOP; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
# retain only that state |
367
|
0
|
|
|
|
|
0
|
my @retains; |
368
|
0
|
|
|
|
|
0
|
for (0..(@$universe-1)) { |
369
|
0
|
|
|
|
|
0
|
my $state = $universe->[$_]; |
370
|
0
|
|
|
|
|
0
|
my $foo = +$state->[$os]; |
371
|
0
|
0
|
|
|
|
0
|
push(@retains, $_) if ($foo == $rt); |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
0
|
0
|
|
|
|
0
|
if ($Quantum::Entanglement::destroy) { |
375
|
0
|
|
|
|
|
0
|
@$universe = @$universe[@retains]; |
376
|
0
|
|
|
|
|
0
|
return $rt; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# set probabilty to zero for each state we know can't be so |
380
|
0
|
|
|
|
|
0
|
my $next_retain = shift @retains; |
381
|
0
|
|
|
|
|
0
|
PURGE: foreach my $snum ( 0..(@$universe-1) ) { |
382
|
0
|
0
|
|
|
|
0
|
if ($snum == $next_retain) { |
383
|
0
|
|
0
|
|
|
0
|
$next_retain = shift(@retains) || -1; |
384
|
0
|
|
|
|
|
0
|
next PURGE; |
385
|
|
|
|
|
|
|
} |
386
|
0
|
|
|
|
|
0
|
my $state = ${$universe}[$snum]; |
|
0
|
|
|
|
|
0
|
|
387
|
0
|
|
|
|
|
0
|
$$state[$_] = 0 foreach grep {!($_ % 2)} ( 0..(@$state-1) ) |
|
0
|
|
|
|
|
0
|
|
388
|
|
|
|
|
|
|
} |
389
|
0
|
|
|
|
|
0
|
return $rt; |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
# boolean context (observation) |
393
|
|
|
|
|
|
|
sub bool_ent { |
394
|
2
|
|
|
2
|
0
|
74
|
my $c = $_[0]; |
395
|
2
|
|
|
|
|
4
|
my $os = $c->[1]; |
396
|
2
|
|
|
|
|
3
|
my $universe = ${$c->[0]}; |
|
2
|
|
|
|
|
5
|
|
397
|
2
|
|
|
|
|
4
|
my ($rt,$ft,$p_true, $p_false) = (0,0,0,0); |
398
|
2
|
|
|
|
|
3
|
my (@true, @false); |
399
|
|
|
|
|
|
|
|
400
|
2
|
|
|
|
|
6
|
foreach (0..(@$universe-1)) { |
401
|
2
|
|
|
|
|
4
|
my $state = $universe->[$_]; |
402
|
2
|
|
|
|
|
3
|
my $c2 = $state->[$os]; |
403
|
2
|
50
|
|
|
|
11
|
if ($c2) { |
404
|
2
|
|
|
|
|
4
|
$rt++; |
405
|
2
|
|
|
|
|
3
|
push @true, $_; |
406
|
2
|
|
|
|
|
9
|
$p_true += $state->[$os-1]; |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
else { |
409
|
0
|
|
|
|
|
0
|
$ft++; |
410
|
0
|
|
|
|
|
0
|
push @false, $_; |
411
|
0
|
|
|
|
|
0
|
$p_false += $state->[$os-1]; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
2
|
50
|
|
|
|
193
|
return 0 unless $rt; # no states are true, so must be false |
416
|
2
|
50
|
|
|
|
12
|
return $rt unless $ft; # no states are false, so must be true |
417
|
|
|
|
|
|
|
# if it can be true, decide if it will end up being true or not |
418
|
0
|
|
|
|
|
0
|
my @retains; |
419
|
0
|
0
|
0
|
|
|
0
|
if ( _sel_output( $p_true,$p_false) |
420
|
|
|
|
|
|
|
or $Quantum::Entanglement::conform) { |
421
|
0
|
|
|
|
|
0
|
@retains = @true; |
422
|
0
|
|
|
|
|
0
|
$rt = $rt; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
else { |
425
|
0
|
|
|
|
|
0
|
@retains = @false; |
426
|
0
|
|
|
|
|
0
|
$rt = 0; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
|
429
|
0
|
0
|
|
|
|
0
|
if ($Quantum::Entanglement::destroy) { |
430
|
0
|
|
|
|
|
0
|
@$universe = @$universe[@retains]; |
431
|
0
|
|
|
|
|
0
|
return $rt; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
0
|
|
|
|
|
0
|
my $next_retain = shift @retains; |
435
|
0
|
|
|
|
|
0
|
PURGE: foreach my $snum ( 0..(@$universe-1) ) { |
436
|
0
|
0
|
|
|
|
0
|
if ($snum == $next_retain) { |
437
|
0
|
|
0
|
|
|
0
|
$next_retain = shift(@retains) || -1; |
438
|
0
|
|
|
|
|
0
|
next PURGE; |
439
|
|
|
|
|
|
|
} |
440
|
0
|
|
|
|
|
0
|
my $state = ${$universe}[$snum]; |
|
0
|
|
|
|
|
0
|
|
441
|
0
|
|
|
|
|
0
|
$$state[$_] = 0 foreach grep {!($_ % 2)} (0..(@$state-1)) |
|
0
|
|
|
|
|
0
|
|
442
|
|
|
|
|
|
|
} |
443
|
0
|
|
|
|
|
0
|
return $rt; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
### any BInary, Non-observational OPeration |
447
|
|
|
|
|
|
|
sub binop { |
448
|
15
|
|
|
15
|
0
|
31
|
my ($c,$d,$r,$code) = @_; |
449
|
15
|
|
|
|
|
20
|
my $var; |
450
|
|
|
|
|
|
|
my $universe; |
451
|
15
|
50
|
33
|
|
|
100
|
if ( ref($d) |
452
|
|
|
|
|
|
|
&& UNIVERSAL::isa($d, 'Quantum::Entanglement')) { |
453
|
15
|
|
|
|
|
33
|
_join($c,$d); |
454
|
15
|
|
|
|
|
21
|
my $od = $d->[1]; my $oc = $c->[1]; |
|
15
|
|
|
|
|
26
|
|
455
|
15
|
|
|
|
|
38
|
$var = _add($c); |
456
|
15
|
|
|
|
|
16
|
$universe = ${$c->[0]}; |
|
15
|
|
|
|
|
22
|
|
457
|
15
|
|
|
|
|
23
|
foreach my $state (@$universe) { |
458
|
21
|
|
|
|
|
113
|
push @$state, ($state->[$oc-1] * $state->[$od-1], |
459
|
|
|
|
|
|
|
&$code($state->[$oc],$state->[$od]) ); |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
else { # adding something to one state |
463
|
0
|
|
|
|
|
0
|
my $oc = $c->[1]; |
464
|
0
|
|
|
|
|
0
|
$var = _add($c); |
465
|
0
|
|
|
|
|
0
|
$universe = ${$c->[0]}; |
|
0
|
|
|
|
|
0
|
|
466
|
0
|
0
|
|
|
|
0
|
if ($r) { |
467
|
0
|
|
|
|
|
0
|
push(@$_, ($_->[$oc-1], &$code($d,$_->[$oc]))) foreach @$universe; |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
else { |
470
|
0
|
|
|
|
|
0
|
push(@$_, ($_->[$oc-1], &$code($_->[$oc],$d))) foreach @$universe; |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
} |
473
|
15
|
|
|
|
|
69
|
return $var; |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
# any BInary Observational OPeration |
477
|
|
|
|
|
|
|
sub bioop { |
478
|
0
|
|
|
0
|
0
|
0
|
my ($c, $d, $reverse, $code) = @_; |
479
|
0
|
|
|
|
|
0
|
my $rt = 0; |
480
|
0
|
|
|
|
|
0
|
my $ft = 0; |
481
|
0
|
|
|
|
|
0
|
my (@true, @false); |
482
|
0
|
|
|
|
|
0
|
my ($p_true, $p_false) = (0,0); |
483
|
0
|
|
|
|
|
0
|
my $universe; |
484
|
0
|
0
|
0
|
|
|
0
|
if (ref($d) && UNIVERSAL::isa($d, 'Quantum::Entanglement')) { |
485
|
0
|
|
|
|
|
0
|
$c->_join($d); |
486
|
0
|
|
|
|
|
0
|
$universe = ${$c->[0]}; |
|
0
|
|
|
|
|
0
|
|
487
|
0
|
|
|
|
|
0
|
foreach (0..(@$universe-1)) { |
488
|
0
|
|
|
|
|
0
|
my $state = $universe->[$_]; |
489
|
0
|
|
|
|
|
0
|
my $oc = $c->[1]; my $od = $d->[1]; |
|
0
|
|
|
|
|
0
|
|
490
|
0
|
|
|
|
|
0
|
my $d2 = $state->[$od]; |
491
|
0
|
|
|
|
|
0
|
my $c2 = $state->[$oc]; |
492
|
0
|
0
|
|
|
|
0
|
if (&$code($c2, $d2)) { |
493
|
0
|
|
|
|
|
0
|
$rt++; |
494
|
0
|
|
|
|
|
0
|
push @true, $_; |
495
|
0
|
|
|
|
|
0
|
$p_true += $state->[$oc-1]* $state->[$od-1]; |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
else { |
498
|
0
|
|
|
|
|
0
|
$ft++; |
499
|
0
|
|
|
|
|
0
|
push @false, $_; |
500
|
0
|
|
|
|
|
0
|
$p_false += $state->[$oc-1]* $state->[$od-1]; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
} |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
else { |
505
|
0
|
|
|
|
|
0
|
$universe = ${$c->[0]}; |
|
0
|
|
|
|
|
0
|
|
506
|
0
|
|
|
|
|
0
|
foreach (0..(@$universe-1)) { |
507
|
0
|
|
|
|
|
0
|
my $state = $universe->[$_]; |
508
|
0
|
|
|
|
|
0
|
my $d2 = $d; |
509
|
0
|
|
|
|
|
0
|
my $os = $c->[1]; |
510
|
0
|
|
|
|
|
0
|
my $c2 = $state->[$os]; |
511
|
0
|
0
|
|
|
|
0
|
($c2, $d2) = ($d2, $c2) if $reverse; |
512
|
0
|
0
|
|
|
|
0
|
if (&$code($c2,$d2)) { |
513
|
0
|
|
|
|
|
0
|
$rt++; |
514
|
0
|
|
|
|
|
0
|
push @true, $_; |
515
|
0
|
|
|
|
|
0
|
$p_true += $state->[$os-1]; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
else { |
518
|
0
|
|
|
|
|
0
|
$ft++; |
519
|
0
|
|
|
|
|
0
|
push @false, $_; |
520
|
0
|
|
|
|
|
0
|
$p_false += $state->[$os-1]; |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
} |
524
|
|
|
|
|
|
|
|
525
|
0
|
0
|
|
|
|
0
|
return 0 unless $rt; # no states are true, so must be false |
526
|
0
|
0
|
|
|
|
0
|
return $rt unless $ft; # no states are false, so must be true |
527
|
0
|
|
|
|
|
0
|
my @retains; |
528
|
|
|
|
|
|
|
# if it can be true, decide if it will end up being true or not |
529
|
0
|
0
|
0
|
|
|
0
|
if ( _sel_output( $p_true,$p_false) |
530
|
|
|
|
|
|
|
or $Quantum::Entanglement::conform) { |
531
|
0
|
|
|
|
|
0
|
@retains = @true; |
532
|
0
|
|
|
|
|
0
|
$rt = $rt; |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
else { |
535
|
0
|
|
|
|
|
0
|
@retains = @false; |
536
|
0
|
|
|
|
|
0
|
$rt = 0; |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
|
539
|
0
|
0
|
|
|
|
0
|
if ($Quantum::Entanglement::destroy) { |
540
|
0
|
|
|
|
|
0
|
@$universe = @$universe[@retains]; |
541
|
0
|
|
|
|
|
0
|
return $rt; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
0
|
|
|
|
|
0
|
my $next_retain = shift @retains; |
545
|
0
|
|
|
|
|
0
|
PURGE: foreach my $snum ( 0..(@$universe-1) ) { |
546
|
0
|
0
|
|
|
|
0
|
if ($snum == $next_retain) { |
547
|
0
|
|
0
|
|
|
0
|
$next_retain = shift(@retains) || -1; |
548
|
0
|
|
|
|
|
0
|
next PURGE; |
549
|
|
|
|
|
|
|
} |
550
|
0
|
|
|
|
|
0
|
my $state = ${$universe}[$snum]; |
|
0
|
|
|
|
|
0
|
|
551
|
0
|
|
|
|
|
0
|
$$state[$_] = 0 foreach grep {!($_ % 2)} (0..(@$state-1)) |
|
0
|
|
|
|
|
0
|
|
552
|
|
|
|
|
|
|
} |
553
|
0
|
|
|
|
|
0
|
return $rt; |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
# any MUTating OPerator |
558
|
|
|
|
|
|
|
sub mutop { |
559
|
0
|
|
|
0
|
0
|
0
|
my $c = $_[0]; |
560
|
0
|
|
|
|
|
0
|
my $code = $_[1]; |
561
|
0
|
|
|
|
|
0
|
my $os = $c->[1]; |
562
|
0
|
|
|
|
|
0
|
my $universe = ${$c->[0]}; |
|
0
|
|
|
|
|
0
|
|
563
|
0
|
|
|
|
|
0
|
foreach my $state (@$universe) { |
564
|
0
|
|
|
|
|
0
|
$state->[$os] = &$code($state->[$os]); |
565
|
|
|
|
|
|
|
} |
566
|
0
|
|
|
|
|
0
|
return $c; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
sub unnop { |
570
|
0
|
|
|
0
|
0
|
0
|
my $c = $_[0]; |
571
|
0
|
|
|
|
|
0
|
my $code = $_[1]; |
572
|
0
|
|
|
|
|
0
|
my $os = $c->[1]; |
573
|
0
|
|
|
|
|
0
|
my $val = $c->_add; my $universe = ${$c->[0]}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
574
|
0
|
|
|
|
|
0
|
foreach my $state (@$universe) { |
575
|
0
|
|
|
|
|
0
|
push(@$state, $state->[$os-1], &$code($state->[$os]) ); |
576
|
|
|
|
|
|
|
} |
577
|
0
|
|
|
|
|
0
|
return $val; |
578
|
|
|
|
|
|
|
} |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
## |
581
|
|
|
|
|
|
|
# performing a conditional in paralell on the states (ie. without looking) |
582
|
|
|
|
|
|
|
# returns a new variable |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
sub p_op { |
585
|
3
|
|
|
3
|
1
|
36
|
my ($arg1, $op, $arg2, $true_cf, $false_cf) = @_; |
586
|
3
|
50
|
|
0
|
|
8
|
$true_cf = ref($true_cf) ? $true_cf : sub {1}; |
|
0
|
|
|
|
|
0
|
|
587
|
3
|
50
|
|
0
|
|
8
|
$false_cf = ref($false_cf) ? $false_cf : sub {0}; |
|
0
|
|
|
|
|
0
|
|
588
|
3
|
|
|
|
|
5
|
my $r = 0; |
589
|
3
|
50
|
33
|
|
|
37
|
unless (ref($arg1) && UNIVERSAL::isa($arg1, 'Quantum::Entanglement')) { |
590
|
0
|
|
|
|
|
0
|
$r = 1; |
591
|
0
|
|
|
|
|
0
|
($arg1, $arg2) = ($arg2, $arg1); |
592
|
|
|
|
|
|
|
} |
593
|
3
|
|
|
|
|
5
|
my $tcref; |
594
|
3
|
|
|
|
|
579
|
eval " |
595
|
|
|
|
|
|
|
\$tcref = sub { |
596
|
|
|
|
|
|
|
local \*QE::arg1 = \\\$_[0]; |
597
|
|
|
|
|
|
|
local \*QE::arg2 = \\\$_[1]; |
598
|
|
|
|
|
|
|
if (\$_[0] $op \$_[1]) { |
599
|
|
|
|
|
|
|
return \&\$true_cf; |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
else { |
602
|
|
|
|
|
|
|
return \&\$false_cf; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
} |
605
|
3
|
50
|
|
|
|
37
|
"; croak "$0: something wrong in p_op $@" if $@; |
606
|
|
|
|
|
|
|
|
607
|
3
|
|
|
|
|
10
|
return binop($arg1, $arg2, $r, $tcref); |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
# allows for other functions to be performed accross states, can take |
611
|
|
|
|
|
|
|
# as many entangled variables as you like... |
612
|
|
|
|
|
|
|
# can take code ref, or "symbolic" function name (eg. p_func('substr', ..)) |
613
|
|
|
|
|
|
|
sub p_func { |
614
|
0
|
|
|
0
|
1
|
|
my $func = shift; |
615
|
0
|
|
|
|
|
|
my $package = (caller)[0]; |
616
|
|
|
|
|
|
|
# build up the function call by shifting off |
617
|
|
|
|
|
|
|
# entangled variables until something isn't entangled |
618
|
0
|
0
|
|
|
|
|
my $foo = ref($func) ? "&\$func(" : "$func("; |
619
|
0
|
|
|
|
|
|
my @temp = @_; |
620
|
0
|
|
|
|
|
|
my $first = $temp[0]; |
621
|
0
|
|
0
|
|
|
|
do { |
622
|
0
|
|
|
|
|
|
my $c = shift @temp; |
623
|
0
|
|
|
|
|
|
_join($first,$c); |
624
|
|
|
|
|
|
|
} while (ref($temp[0]) && UNIVERSAL::isa($temp[0],'Quantum::Entanglement')); |
625
|
0
|
|
|
|
|
|
my @p_codes = (); |
626
|
0
|
|
0
|
|
|
|
do { |
627
|
0
|
|
|
|
|
|
my $c = shift; |
628
|
0
|
|
|
|
|
|
$foo .= '$state->[' . $c->[1] . '],'; |
629
|
0
|
|
|
|
|
|
push @p_codes, $c->[1]-1; |
630
|
|
|
|
|
|
|
} while ( ref($_[0]) && UNIVERSAL::isa($_[0], 'Quantum::Entanglement')); |
631
|
0
|
0
|
|
|
|
|
$foo .= scalar(@_)? '@args);' : ');'; |
632
|
0
|
|
|
|
|
|
my @args = @_; |
633
|
|
|
|
|
|
|
# loop over states, evaluating function in caller's package |
634
|
0
|
|
|
|
|
|
my $var = $first->_add; |
635
|
0
|
|
|
|
|
|
my $p_code = join('*', map {"\$state->[$_]"} @p_codes); |
|
0
|
|
|
|
|
|
|
636
|
0
|
|
|
|
|
|
my $universe = ${$first->[0]}; |
|
0
|
|
|
|
|
|
|
637
|
0
|
|
|
|
|
|
foreach my $state (@$universe) { |
638
|
0
|
|
|
|
|
|
my $new_prob = eval $p_code; |
639
|
0
|
|
|
|
|
|
push(@$state, $new_prob, eval "package $package; $foo"); |
640
|
0
|
0
|
|
|
|
|
croak "Internal error: $@" if $@; |
641
|
|
|
|
|
|
|
} |
642
|
0
|
|
|
|
|
|
return $var; |
643
|
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
# This allows the introduction of new states into the system, based |
646
|
|
|
|
|
|
|
# on the current values and probability amplitudes of current states |
647
|
|
|
|
|
|
|
# must be given a code ref, followed by a list of entangled vars whose |
648
|
|
|
|
|
|
|
# states will be passed to the function. |
649
|
|
|
|
|
|
|
sub q_logic { |
650
|
0
|
|
|
0
|
1
|
|
my $func = shift; |
651
|
0
|
|
|
|
|
|
my (@offsets); |
652
|
0
|
|
|
|
|
|
my $first = $_[0]; |
653
|
0
|
|
|
|
|
|
_join($first,$_) foreach @_; |
654
|
0
|
|
|
|
|
|
@offsets = map {$_->[1]-1, $_->[1]} @_; |
|
0
|
|
|
|
|
|
|
655
|
0
|
|
|
|
|
|
my $var = $first->_add; |
656
|
0
|
|
|
|
|
|
my $universe = ${$first->[0]}; |
|
0
|
|
|
|
|
|
|
657
|
0
|
|
|
|
|
|
my @resultant_space; |
658
|
0
|
|
|
|
|
|
foreach my $state (@$universe) { |
659
|
0
|
|
|
|
|
|
my @new_states = &$func(@{$state}[@offsets]); |
|
0
|
|
|
|
|
|
|
660
|
0
|
|
|
|
|
|
do { |
661
|
0
|
|
|
|
|
|
push @resultant_space, [@$state, splice(@new_states,0,2)]; |
662
|
|
|
|
|
|
|
} while (@new_states); |
663
|
|
|
|
|
|
|
} |
664
|
0
|
|
|
|
|
|
@{$universe} = @resultant_space; |
|
0
|
|
|
|
|
|
|
665
|
0
|
|
|
|
|
|
return $var; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
# takes ft of amplitudes of a var, creates new state with the |
669
|
|
|
|
|
|
|
# transformed amplitudes and the values from the first state. |
670
|
|
|
|
|
|
|
sub QFT { |
671
|
0
|
|
|
0
|
1
|
|
my $c = $_[0]; |
672
|
0
|
|
|
|
|
|
my $var = $c->_add; |
673
|
0
|
|
|
|
|
|
my $os = $c->[1]; |
674
|
0
|
|
|
|
|
|
my $universe = ${$c->[0]}; |
|
0
|
|
|
|
|
|
|
675
|
0
|
|
|
|
|
|
my @inputs = map {$_->[$os-1]} @$universe; # get current probs |
|
0
|
|
|
|
|
|
|
676
|
0
|
|
|
|
|
|
my $num = scalar @inputs; |
677
|
0
|
|
|
|
|
|
foreach my $r (0..($num-1)) { |
678
|
0
|
|
|
|
|
|
my $prob = 0; |
679
|
0
|
|
|
|
|
|
foreach my $x (0..($num-1)) { |
680
|
0
|
|
|
|
|
|
$prob += cplxe(1,(-2*pi*$r*$x / $num)) * $inputs[$x]; |
681
|
|
|
|
|
|
|
} |
682
|
0
|
|
|
|
|
|
push @{$universe->[$r]}, $prob, $universe->[$r]->[$os]; |
|
0
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
} |
684
|
0
|
|
|
|
|
|
return $var; |
685
|
|
|
|
|
|
|
} |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
sub save_state{ |
688
|
0
|
|
|
0
|
1
|
|
my @os; |
689
|
0
|
|
|
|
|
|
my $stash = []; |
690
|
|
|
|
|
|
|
|
691
|
0
|
|
|
|
|
|
foreach (@_) { |
692
|
0
|
0
|
0
|
|
|
|
carp "Can only save state of Quantum::Entanglement variables" |
693
|
|
|
|
|
|
|
unless (ref($_) && UNIVERSAL::isa($_, 'Quantum::Entanglement')); |
694
|
|
|
|
|
|
|
} |
695
|
|
|
|
|
|
|
|
696
|
0
|
|
|
|
|
|
my $first = $_[0]; |
697
|
0
|
|
|
|
|
|
_join($first, $_) foreach @_; |
698
|
0
|
|
|
|
|
|
push(@os, $_->[1]) foreach @_; |
699
|
0
|
|
|
|
|
|
my $universe = ${$_[0]->[0]}; |
|
0
|
|
|
|
|
|
|
700
|
0
|
|
|
|
|
|
foreach my $state (@$universe) { |
701
|
0
|
|
|
|
|
|
push @$stash, [ @{$state}[map {$_-1,$_} @os] ]; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
} |
703
|
0
|
|
|
|
|
|
return bless $stash, 'Quantum::Entanglement::State'; |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
# completely clobbers current state with whatever was saved previously |
707
|
|
|
|
|
|
|
sub restore_state { |
708
|
0
|
|
|
0
|
0
|
|
my $stash = shift; |
709
|
|
|
|
|
|
|
|
710
|
0
|
|
|
|
|
|
my $num_saved = scalar(@{$stash->[0]}) /2; |
|
0
|
|
|
|
|
|
|
711
|
0
|
0
|
|
|
|
|
carp "You don't have any states saved!" unless $num_saved; |
712
|
0
|
|
|
|
|
|
my @newvars; |
713
|
0
|
|
|
|
|
|
$newvars[0] = _new(); |
714
|
0
|
|
|
|
|
|
${$newvars[0]->[0]}->[0] = ['fake','fake']; # no hackery here, no. |
|
0
|
|
|
|
|
|
|
715
|
0
|
0
|
|
|
|
|
if ($num_saved > 1) { |
716
|
0
|
|
|
|
|
|
for (2..$num_saved) { |
717
|
0
|
|
|
|
|
|
push(@newvars, $newvars[0]->_add()); |
718
|
0
|
|
|
|
|
|
push @{${$newvars[0]->[0]}->[0]}, qw(fake fake); # or here, never |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
} |
721
|
0
|
|
|
|
|
|
my $universe = ${$newvars[0]->[0]}; |
|
0
|
|
|
|
|
|
|
722
|
0
|
|
|
|
|
|
shift @$universe; |
723
|
0
|
|
|
|
|
|
foreach (@$stash) { |
724
|
0
|
|
|
|
|
|
push @$universe, [@$_]; |
725
|
|
|
|
|
|
|
} |
726
|
0
|
0
|
|
|
|
|
return wantarray ? @newvars : $newvars[0]; |
727
|
|
|
|
|
|
|
} |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
# this is needed for simplicity of exporting save_states |
730
|
|
|
|
|
|
|
package Quantum::Entanglement::State; |
731
|
|
|
|
|
|
|
@Quantum::Entanglement::State::ISA = qw(Quantum::Entanglement); |
732
|
0
|
|
|
0
|
|
|
sub DESTROY {} |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
1; |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
__END__; |