AI-ANN
view release on metacpan or search on metacpan
lib/AI/ANN/Neuron.pm view on Meta::CPAN
#!/usr/bin/perl
package AI::ANN::Neuron;
BEGIN {
$AI::ANN::Neuron::VERSION = '0.008';
}
# ABSTRACT: a neuron for an artificial neural network simulator
use strict;
use warnings;
use Moose;
use Inline C => <<'END_C';
double _execute_internals ( AV* inputs, AV* neurons, AV* inputweights, AV* neuronweights ) {
double output = 0.0;
int i;
int v1 = av_len(inputweights);
int v2 = av_len(inputs);
if (v2 < v1) {
v1 = v2;
}
if (v1 >= 0) {
for (i=0; i<=v1; i++) {
SV** val = av_fetch(inputs, i, 0);
SV** weight = av_fetch(inputweights, i, 0);
output += SvNV(*val) * SvNV(*weight);
}
}
v1 = av_len(neuronweights);
v2 = av_len(neurons);
if (v2 < v1) {
v1 = v2;
}
if (v1 >= 0) {
for (i=0; i<=v1; i++) {
SV** val = av_fetch(neurons, i, 0);
SV** weight = av_fetch(neuronweights, i, 0);
output += SvNV(*val) * SvNV(*weight);
}
}
return output;
}
END_C
has 'id' => (is => 'rw', isa => 'Int');
has 'inputs' => (is => 'rw', isa => 'ArrayRef', required => 1);
has 'neurons' => (is => 'rw', isa => 'ArrayRef', required => 1);
has 'eta_inputs' => (is => 'rw', isa => 'ArrayRef');
has 'eta_neurons' => (is => 'rw', isa => 'ArrayRef');
has 'inline_c' => (is => 'ro', isa => 'Int', required => 1, default => 1);
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my %data;
if ( @_ >= 2 && ref $_[0] && ref $_[1]) {
%data = ('inputs' => $_[0], 'neurons' => $_[1]);
$data{'eta_inputs'} = $_[2] if defined $_[2];
$data{'eta_neurons'} = $_[3] if defined $_[3];
} elsif ( @_ >= 3 && ref $_[1] && ref $_[2]) {
%data = ('id' => $_[0], 'inputs' => $_[1], 'neurons' => $_[2]);
$data{'eta_inputs'} = $_[3] if defined $_[3];
$data{'eta_neurons'} = $_[4] if defined $_[4];
} elsif ( @_ == 1 && ref $_[0] eq 'HASH' ) {
%data = %{$_[0]};
} else {
%data = @_;
}
if (ref $data{'inputs'} eq 'HASH') {
my @temparray;
foreach my $i (keys %{$data{'inputs'}}) {
if (defined $data{'inputs'}->{$i} && $data{'inputs'}->{$i} != 0) {
$temparray[$i]=$data{'inputs'}->{$i};
}
}
$data{'inputs'}=\@temparray;
}
if (ref $data{'neurons'} eq 'HASH') {
my @temparray;
foreach my $i (keys %{$data{'neurons'}}) {
if (defined $data{'neurons'}->{$i} && $data{'neurons'}->{$i} != 0) {
$temparray[$i]=$data{'neurons'}->{$i};
}
}
$data{'neurons'}=\@temparray;
}
if (defined $data{'eta_inputs'} && ref $data{'eta_inputs'} eq 'HASH') {
my @temparray;
foreach my $i (keys %{$data{'eta_inputs'}}) {
if (defined $data{'eta_inputs'}->{$i} && $data{'eta_inputs'}->{$i} != 0) {
$temparray[$i]=$data{'eta_inputs'}->{$i};
}
}
$data{'eta_inputs'}=\@temparray;
}
if (defined $data{'eta_neurons'} && ref $data{'eta_neurons'} eq 'HASH') {
my @temparray;
foreach my $i (keys %{$data{'eta_neurons'}}) {
if (defined $data{'eta_neurons'}->{$i} && $data{'eta_neurons'}->{$i} != 0) {
$temparray[$i]=$data{'eta_neurons'}->{$i};
}
}
$data{'eta_neurons'}=\@temparray;
}
foreach my $i (0..$#{$data{'inputs'}}) {
$data{'inputs'}->[$i] ||= 0;
}
foreach my $i (0..$#{$data{'neurons'}}) {
$data{'neurons'}->[$i] ||= 0;
}
foreach my $i (0..$#{$data{'eta_inputs'}}) {
$data{'eta_inputs'}->[$i] ||= 0;
}
foreach my $i (0..$#{$data{'eta_neurons'}}) {
$data{'eta_neurons'}->[$i] ||= 0;
}
return $class->$orig(%data);
};
sub ready {
my $self = shift;
my $inputs = shift;
my $neurons = shift;
if (ref $neurons eq 'HASH') {
my @temparray;
foreach my $i (keys %$neurons) {
if (defined $neurons->{$i} && $neurons->{$i} != 0) {
$temparray[$i]=$neurons->{$i};
}
}
$neurons=\@temparray;
}
my @inputs = @$inputs;
my @neurons = @$neurons;
foreach my $id (0..$#{$self->{'inputs'}}) {
unless ((not defined $self->{'inputs'}->[$id]) ||
$self->{'inputs'}->[$id] == 0 || defined $inputs[$id])
{return 0}
# This probably shouldn't ever happen, as it would be weird if our
# inputs weren't available yet.
}
foreach my $id (0..$#{$self->{'neurons'}}) {
unless ((not defined $self->{'neurons'}->[$id]) ||
$self->{'neurons'}->[$id] == 0 || defined $neurons[$id])
{return 0}
}
return 1;
}
sub execute {
my $self = shift;
my $inputs = shift;
my $neurons = shift;
if (ref $neurons eq 'HASH') {
my @temparray;
foreach my $i (keys %$neurons) {
$temparray[$i]=$neurons->{$i} || 0;
}
$neurons=\@temparray;
}
my @inputs = @$inputs;
my @neurons = @$neurons;
my @inputweights = @{$self->{'inputs'}};
my @neuronweights = @{$self->{'neurons'}};
# foreach my $i (0..$#inputs) {
# $inputs[$i] ||= 0;
# }
# foreach my $i (0..$#neurons) {
# $neurons[$i] ||= 0;
# }
# if ($#inputs < $#inputweights) {
# foreach my $i ($#inputs+1..$#inputweights) {
# $inputs[$i]=0;
# }
( run in 0.838 second using v1.01-cache-2.11-cpan-39bf76dae61 )