Quantum-Entanglement

 view release on metacpan or  search on metacpan

Entanglement.pm  view on Meta::CPAN

}

# any MUTating OPerator
sub mutop {
  my $c = $_[0];
  my $code = $_[1];
  my $os = $c->[1];
  my $universe = ${$c->[0]};
  foreach my $state (@$universe) {
    $state->[$os] = &$code($state->[$os]);
  }
  return $c;
}

sub unnop {
  my $c = $_[0];
  my $code = $_[1];
  my $os = $c->[1];
  my $val = $c->_add; my $universe = ${$c->[0]};
  foreach my $state (@$universe) {
    push(@$state, $state->[$os-1], &$code($state->[$os]) );
  }
  return $val;
}

##
# performing a conditional in paralell on the states (ie. without looking)
# returns a new variable

sub p_op {
  my ($arg1, $op, $arg2, $true_cf, $false_cf) = @_;
  $true_cf  = ref($true_cf)  ? $true_cf  : sub {1};
  $false_cf = ref($false_cf) ? $false_cf : sub {0};
  my $r = 0;
  unless (ref($arg1) && UNIVERSAL::isa($arg1, 'Quantum::Entanglement')) {
    $r = 1;
    ($arg1, $arg2) = ($arg2, $arg1);
  }
  my $tcref;
  eval "
     \$tcref = sub {
       local \*QE::arg1 = \\\$_[0];
       local \*QE::arg2 = \\\$_[1];
       if (\$_[0] $op \$_[1]) {
         return \&\$true_cf;
       }
       else {
         return \&\$false_cf;
       }
     }
  "; croak "$0: something wrong in p_op $@" if $@;

  return binop($arg1, $arg2, $r, $tcref);
}

# allows for other functions to be performed accross states, can take
# as many entangled variables as you like...
# can take code ref, or "symbolic" function name (eg. p_func('substr', ..))
sub p_func {
  my $func = shift;
  my $package = (caller)[0];
  # build up the function call by shifting off
  # entangled variables until something isn't entangled
  my $foo = ref($func) ? "&\$func(" : "$func(";
  my @temp = @_;
  my $first = $temp[0];
  do {
    my $c = shift @temp;
    _join($first,$c);
  } while (ref($temp[0]) && UNIVERSAL::isa($temp[0],'Quantum::Entanglement'));
  my @p_codes = ();
  do {
    my $c = shift;
    $foo .= '$state->[' . $c->[1] . '],';
    push @p_codes, $c->[1]-1;
  } while ( ref($_[0]) && UNIVERSAL::isa($_[0], 'Quantum::Entanglement'));
  $foo .= scalar(@_)? '@args);' : ');';
  my @args = @_;
  # loop over states, evaluating function in caller's package
  my $var = $first->_add;
  my $p_code = join('*', map {"\$state->[$_]"} @p_codes);
  my $universe = ${$first->[0]};
  foreach my $state (@$universe) {
    my $new_prob = eval $p_code;
    push(@$state, $new_prob, eval "package $package; $foo");
    croak "Internal error: $@" if $@;
  }
  return $var;
}

# This allows the introduction of new states into the system, based
# on the current values and probability amplitudes of current states
# must be given a code ref, followed by a list of entangled vars whose
# states will be passed to the function.
sub q_logic {
  my $func = shift;
  my (@offsets);
  my $first = $_[0];
  _join($first,$_) foreach @_;
  @offsets = map {$_->[1]-1, $_->[1]} @_;
  my $var = $first->_add;
  my $universe = ${$first->[0]};
  my @resultant_space;
  foreach my $state (@$universe) {
    my @new_states = &$func(@{$state}[@offsets]);
    do {
      push @resultant_space, [@$state, splice(@new_states,0,2)];
    } while (@new_states);
  }
  @{$universe} = @resultant_space;
  return $var;
}

# takes ft of amplitudes of a var, creates new state with the
# transformed amplitudes and the values from the first state.
sub QFT {
  my $c = $_[0];
  my $var = $c->_add;
  my $os = $c->[1];
  my $universe = ${$c->[0]};
  my @inputs = map {$_->[$os-1]} @$universe; # get current probs



( run in 3.460 seconds using v1.01-cache-2.11-cpan-b16cb0d3907 )