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             $Quantum::Superpositions::Lazy::Computation::VERSION = '1.12';
3 15     15   192 use v5.24;
  15         48  
4 15     15   72 use warnings;
  15         28  
  15         343  
5 15     15   64 use Moo;
  15         37  
  15         87  
6 15     15   10677 use Quantum::Superpositions::Lazy::Operation::Computational;
  15         43  
  15         517  
7 15     15   5600 use Quantum::Superpositions::Lazy::ComputedState;
  15         44  
  15         587  
8 15     15   125 use Quantum::Superpositions::Lazy::Util qw(is_collapsible get_iterator);
  15         29  
  15         796  
9 15     15   90 use Types::Common::Numeric qw(PositiveNum);
  15         29  
  15         110  
10 15     15   6192 use Types::Standard qw(ConsumerOf ArrayRef Str);
  15         37  
  15         139  
11 15     15   12828 use List::Util qw(product);
  15         31  
  15         836  
12              
13 15     15   84 use namespace::clean;
  15         29  
  15         91  
14              
15             with "Quantum::Superpositions::Lazy::Role::Collapsible";
16              
17             has "operation" => (
18             is => "ro",
19             isa => (ConsumerOf ["Quantum::Superpositions::Lazy::Role::Operation"])
20             ->plus_coercions(Str,
21             q{Quantum::Superpositions::Lazy::Operation::Computational->new(sign => $_)}
22             ),
23             coerce => 1,
24             required => 1,
25             );
26              
27             has "values" => (
28             is => "ro",
29             isa => ArrayRef->where(q{@$_ > 0}),
30             required => 1,
31             );
32              
33 379     379 1 788 sub weight_sum { 1 }
34              
35             sub collapse
36             {
37 30     30 0 492 my ($self) = @_;
38              
39             my @members = map {
40 30 100       86 (is_collapsible $_) ? $_->collapse : $_
  60         351  
41             } $self->values->@*;
42              
43 30         512 return $self->operation->run(@members);
44             }
45              
46             sub is_collapsed
47             {
48 2     2 0 4053 my ($self) = @_;
49              
50             # a single uncollapsed state means that the computation
51             # is not fully collapsed
52 2         7 foreach my $member ($self->values->@*) {
53 2 50 33     6 if (is_collapsible($member) && !$member->is_collapsed) {
54 2         7 return 0;
55             }
56             }
57 0         0 return 1;
58             }
59              
60             sub reset
61             {
62 11     11 0 485 my ($self) = @_;
63              
64 11         35 foreach my $member ($self->values->@*) {
65 22 50       49 if (is_collapsible $member) {
66 22         405 $member->reset;
67             }
68             }
69              
70 11         26 return $self;
71             }
72              
73             sub _cartesian_product
74             {
75 53     53   129 my ($self, $input_states, $sourced) = @_;
76              
77 53         88 my %states;
78 53         157 my $iterator = get_iterator $input_states->@*;
79              
80 53         136 while (my @params = $iterator->()) {
81 81065         115150 my @source = map { $_->[1] } @params;
  162144         298143  
82 81065         196192 my $result = $self->operation->run(@source);
83 81065         120834 my $probability = product map { $_->[0] } @params;
  162144         285082  
84              
85 81065 100       283952 if (exists $states{$result}) {
86 38348         68814 $states{$result}[0] += $probability;
87             }
88             else {
89 42717         204605 $states{$result} = [
90             $probability,
91             $result,
92             ];
93             }
94              
95 81065 100       147079 if ($sourced) {
96 65104         292902 push $states{$result}[2]->@*, \@source;
97             }
98             }
99              
100 53         27239 return [values %states];
101             }
102              
103             sub _build_complete_states
104             {
105 53     53   909 my ($self) = @_;
106              
107 53         92 my @input_states;
108 53         153 for my $value ($self->values->@*) {
109 109         155 my $local_states;
110              
111 109 100       249 if (is_collapsible $value) {
112 84         1532 my $total = $value->weight_sum;
113             $local_states = [
114             map {
115 84         528 [$_->weight / $total, $_->value]
  16126         120529  
116             } $value->states->@*
117             ];
118             }
119             else {
120 25         56 $local_states = [[1, $value]];
121             }
122              
123 109         776 push @input_states, $local_states;
124             }
125              
126 53         98 my $sourced = $Quantum::Superpositions::Lazy::global_sourced_calculations;
127 53         157 my $states = $self->_cartesian_product(\@input_states, $sourced);
128              
129 53 100       136 if ($sourced) {
130             return [
131             map {
132 6   33     117 Quantum::Superpositions::Lazy::ComputedState->new(
  37627         4926606  
133             weight => $_->[0],
134             value => $_->[1],
135             source => $_->[2] // $_->[1],
136             operation => $self->operation,
137             )
138             } $states->@*
139             ];
140             }
141             else {
142 47         7568 return $states;
143             }
144              
145             }
146              
147             1;
148              
149             __END__