File Coverage

blib/lib/Quantum/Superpositions/Lazy/Computation.pm
Criterion Covered Total %
statement 74 75 98.6
branch 12 14 85.7
condition 2 6 33.3
subroutine 16 16 100.0
pod 1 4 25.0
total 105 115 91.3


line stmt bran cond sub pod time code
1             package Quantum::Superpositions::Lazy::Computation;
2              
3             our $VERSION = '1.11';
4              
5 15     15   193 use v5.24;
  15         48  
6 15     15   122 use warnings;
  15         40  
  15         727  
7 15     15   101 use Moo;
  15         33  
  15         81  
8 15     15   10715 use Quantum::Superpositions::Lazy::Operation::Computational;
  15         59  
  15         537  
9 15     15   5823 use Quantum::Superpositions::Lazy::ComputedState;
  15         47  
  15         597  
10 15     15   119 use Quantum::Superpositions::Lazy::Util qw(is_collapsible get_iterator);
  15         32  
  15         829  
11 15     15   96 use Types::Common::Numeric qw(PositiveNum);
  15         29  
  15         122  
12 15     15   6353 use Types::Standard qw(ConsumerOf ArrayRef Str);
  15         31  
  15         173  
13 15     15   12261 use List::Util qw(product);
  15         36  
  15         868  
14              
15 15     15   84 use namespace::clean;
  15         27  
  15         94  
16              
17             with "Quantum::Superpositions::Lazy::Role::Collapsible";
18              
19             has "operation" => (
20             is => "ro",
21             isa => (ConsumerOf ["Quantum::Superpositions::Lazy::Role::Operation"])
22             ->plus_coercions(Str,
23             q{Quantum::Superpositions::Lazy::Operation::Computational->new(sign => $_)}
24             ),
25             coerce => 1,
26             required => 1,
27             );
28              
29             has "values" => (
30             is => "ro",
31             isa => ArrayRef->where(q{@$_ > 0}),
32             required => 1,
33             );
34              
35 379     379 1 757 sub weight_sum { 1 }
36              
37             sub collapse
38             {
39 30     30 0 448 my ($self) = @_;
40              
41             my @members = map {
42 30 100       69 (is_collapsible $_) ? $_->collapse : $_
  60         321  
43             } $self->values->@*;
44              
45 30         453 return $self->operation->run(@members);
46             }
47              
48             sub is_collapsed
49             {
50 2     2 0 4182 my ($self) = @_;
51              
52             # a single uncollapsed state means that the computation
53             # is not fully collapsed
54 2         7 foreach my $member ($self->values->@*) {
55 2 50 33     6 if (is_collapsible($member) && !$member->is_collapsed) {
56 2         16 return 0;
57             }
58             }
59 0         0 return 1;
60             }
61              
62             sub reset
63             {
64 11     11 0 521 my ($self) = @_;
65              
66 11         26 foreach my $member ($self->values->@*) {
67 22 50       46 if (is_collapsible $member) {
68 22         376 $member->reset;
69             }
70             }
71              
72 11         64 return $self;
73             }
74              
75             sub _cartesian_product
76             {
77 53     53   117 my ($self, $input_states, $sourced) = @_;
78              
79 53         77 my %states;
80 53         181 my $iterator = get_iterator $input_states->@*;
81              
82 53         137 while (my @params = $iterator->()) {
83 81065         112186 my @source = map { $_->[1] } @params;
  162144         287686  
84 81065         193485 my $result = $self->operation->run(@source);
85 81065         116064 my $probability = product map { $_->[0] } @params;
  162144         279381  
86              
87 81065 100       280840 if (exists $states{$result}) {
88 38348         70562 $states{$result}[0] += $probability;
89             }
90             else {
91 42717         205506 $states{$result} = [
92             $probability,
93             $result,
94             ];
95             }
96              
97 81065 100       150045 if ($sourced) {
98 65104         291407 push $states{$result}[2]->@*, \@source;
99             }
100             }
101              
102 53         27706 return [values %states];
103             }
104              
105             sub _build_complete_states
106             {
107 53     53   940 my ($self) = @_;
108              
109 53         90 my @input_states;
110 53         163 for my $value ($self->values->@*) {
111 109         150 my $local_states;
112              
113 109 100       262 if (is_collapsible $value) {
114 84         1512 my $total = $value->weight_sum;
115             $local_states = [
116             map {
117 84         522 [$_->weight / $total, $_->value]
  16126         120035  
118             } $value->states->@*
119             ];
120             }
121             else {
122 25         61 $local_states = [[1, $value]];
123             }
124              
125 109         769 push @input_states, $local_states;
126             }
127              
128 53         94 my $sourced = $Quantum::Superpositions::Lazy::global_sourced_calculations;
129 53         164 my $states = $self->_cartesian_product(\@input_states, $sourced);
130              
131 53 100       148 if ($sourced) {
132             return [
133             map {
134 6   33     111 Quantum::Superpositions::Lazy::ComputedState->new(
  37627         5021905  
135             weight => $_->[0],
136             value => $_->[1],
137             source => $_->[2] // $_->[1],
138             operation => $self->operation,
139             )
140             } $states->@*
141             ];
142             }
143             else {
144 47         7656 return $states;
145             }
146              
147             }
148              
149             1;
150              
151             __END__