AI-ANN

 view release on metacpan or  search on metacpan

lib/AI/ANN.pm  view on Meta::CPAN

	}
	delete $data{'data'};
	return $class->$orig(%data);
};


sub execute {
	my $self = shift;
	my $inputs = $self->{'inputs'} = shift;
	# Don't bother dereferencing $inputs only to rereference a lot
	my $net = $self->{'network'}; # For less typing
	my $lastneuron = $#{$net};
	my @neurons = ();
	foreach my $i (0..$lastneuron) {
		$neurons[$i] = 0;
	}
	foreach my $i (0..$lastneuron) {
		delete $net->[$i]->{'done'};
		delete $net->[$i]->{'state'};
	}
	my $progress = 0;
	do {
		$progress = 0;
		foreach my $i (0..$lastneuron) {
			if ($net->[$i]->{'done'}) {next}
			if ($net->[$i]->{'object'}->ready($inputs, \@neurons)) {
				my $potential = $net->[$i]->{'object'}->execute($inputs, \@neurons);
                $self->{'rawpotentials'}->[$i] = $potential;
				$potential = $self->{'maxvalue'} if $potential > $self->{'maxvalue'};
				$potential = $self->{'minvalue'} if $potential < $self->{'minvalue'};
				$potential = &{$self->{'afunc'}}($potential);
				$neurons[$i] = $net->[$i]->{'state'} = $potential;
				$net->[$i]->{'done'} = 1;
				$progress++;
			}
		}
	} while ($progress); # If the network is feed-forward, we are now finished.
	
	my @notdone = grep {not (defined $net->[$_]->{'done'} &&
							 $net->[$_]->{'done'} == 1)} 0..$lastneuron;
	my @neuronstemp = ();
	if ($#notdone > 0) { #This is the part where we deal with loops and bad things
		my $maxerror = 0;
		my $loopcounter = 1;
		while (1) {
			foreach my $i (@notdone) { # Only bother iterating over the
									   # ones we couldn't solve exactly
				# We don't care if it's ready now, we're just going to interate
				# until it stabilizes.
				if (not defined $neurons[$i] && $i <= $lastneuron) {
					# Fixes warnings about uninitialized values, but we make 
					# sure $i is valid first.
					$neurons[$i] = 0;
				}
				my $potential = $net->[$i]->{'object'}->execute($inputs, \@neurons);
                $self->{'rawpotentials'}->[$i] = $potential;
				$potential = &{$self->{'afunc'}}($potential);
				$potential = $self->{'maxvalue'} if $potential > $self->{'maxvalue'};
				$potential = $self->{'minvalue'} if $potential < $self->{'minvalue'};
				$neuronstemp[$i] = $net->[$i]->{'state'} = $potential;
				# We want to know the absolute change
				if (abs($neurons[$i]-$neuronstemp[$i])>$maxerror) {
					$maxerror = abs($neurons[$i]-$neuronstemp[$i]);
				}
			}
			foreach my $i (0..$lastneuron) { 
				# Update $neurons, since that is what gets passed to execute
				$neurons[$i] = $neuronstemp[$i];
			}
			if (($maxerror < 0.0001 && $loopcounter >= 5) || $loopcounter > 250) {last}
			$loopcounter++;
			$maxerror=0;
		}
	}

	# Ok, hopefully all the neurons have happy values by now.
	# Get the output values for neurons corresponding to outputneurons
	my @output = map {$neurons[$_]} @{$self->{'outputneurons'}};
	return \@output;
}


sub get_state {
	my $self = shift;
	my $net = $self->{'network'}; # For less typing
	my @neurons = map {$net->[$_]->{'state'}} 0..$#{$self->{'network'}};
	my @output = map {$net->[$_]->{'state'}} @{$self->{'outputneurons'}};

	return $self->{'inputs'}, \@neurons, \@output;
}


sub get_internals {
	my $self = shift;
	my $net = $self->{'network'}; # For less typing
	my $retval = [];
	for (my $i = 0; $i <= $#{$self->{'network'}}; $i++) {
		$retval->[$i] = { iamanoutput => 0,
						  inputs => $net->[$i]->{'object'}->inputs(),
						  neurons => $net->[$i]->{'object'}->neurons(),
						  eta_inputs => $net->[$i]->{'object'}->eta_inputs(),
						  eta_neurons => $net->[$i]->{'object'}->eta_neurons()
						  };
	}
	foreach my $i (@{$self->{'outputneurons'}}) {
		$retval->[$i]->{'iamanoutput'} = 1;
	}
	return dclone($retval); # Dclone for safety.
}


sub readable {
	my $self = shift;
	my $retval = "This network has ". $self->{'inputcount'} ." inputs and ".
					scalar(@{$self->{'network'}}) ." neurons.\n";
	for (my $i = 0; $i <= $#{$self->{'network'}}; $i++) {
		$retval .= "Neuron $i\n";
		while (my ($k, $v) = each %{$self->{'network'}->[$i]->{'object'}->inputs()}) {
			$retval .= "\tInput from input $k, weight is $v\n";
		}
		while (my ($k, $v) = each %{$self->{'network'}->[$i]->{'object'}->neurons()}) {



( run in 2.599 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )