---------------------------------------------------------------------------
-- Frustrated Inhibitive Synapse Learning (FISL)
-- package body
-- Copyright 1994 David W. Croft.  All rights reserved.
-- CompuServe [76600, 102]
-- Internet   CroftDW@Portia.Caltech.Edu
---------------------------------------------------------------------------

package body FISL is
---------------------------------------------------------------------------
---------------------------------------------------------------------------

procedure Initialize (
  Network :    out Network_Type;
  Setup   : in     Setup_Type ) is
---------------------------------------------------------------------------
begin
  if Setup.Forward then
    for Neuron in 1..Setup.Total_Count loop
      for Weight in Neuron..Setup.Total_Count loop
	Network.Weights ( Neuron, Weight ) := Weight_Disconnected;
      end loop;
    end loop;
  end if;
  if Setup.Layered then
    for Neuron in 1..Setup.Input_Count loop
      for Weight in 1..Setup.Input_Count loop
	Network.Weights ( Neuron, Weight ) := Weight_Disconnected;
      end loop;
      if Setup.Total_Count > Setup.Input_Count + Setup.Output_Count then
	for Weight in ( Setup.Total_Count - Setup.Output_Count + 1 )
	  ..Setup.Total_Count loop
	    Network.Weights ( Neuron, Weight ) := Weight_Disconnected;
	end loop;
      end if;
    end loop;
    for Neuron in ( Setup.Input_Count + 1 )
      ..( Setup.Total_Count - Setup.Output_Count ) loop
	for Weight in ( Setup.Input_Count + 1 )
	  ..( Setup.Total_Count - Setup.Output_Count ) loop
	    Network.Weights ( Neuron, Weight ) := Weight_Disconnected;
	end loop;
    end loop;
    for Neuron in ( Setup.Total_Count - Setup.Output_Count + 1 )
      ..Setup.Total_Count loop
	if Setup.Total_Count > Setup.Input_Count + Setup.Output_Count then
	  for Weight in 1..Setup.Input_Count loop
	    Network.Weights ( Neuron, Weight ) := Weight_Disconnected;
	  end loop;
	end if;
	for Weight in ( Setup.Total_Count - Setup.Output_Count + 1 )
	  ..Setup.Total_Count loop
	    Network.Weights ( Neuron, Weight ) := Weight_Disconnected;
	end loop;
    end loop;
  end if;
  if Setup.No_Self then
    for Weight in Network.Weights'range loop
      Network.Weights ( Weight, Weight ) := Weight_Disconnected;
    end loop;
  end if;
end Initialize;

procedure Update (
  Network : in out Network_Type ) is
---------------------------------------------------------------------------
begin
  Update ( Network.Inputs, Network.Transmitters, Network.Weights );
  Update ( Network.Weights, Network.Phases, Network.Transmitters );
  Update ( Network.Transmitters, Network.Phases );
  Update ( Network.Phases, Network.Inputs );
end Update;

procedure Update
  ( Weights        : in out Weights_Type;
    Phases         : in     Phases_Type;
    Transmitters   : in     Transmitters_Type ) is
---------------------------------------------------------------------------
begin
  for Neuron in Phases'range loop
    for Synapse in Transmitters'range ( 2 ) loop
      if Transmitters ( Neuron, Synapse ) > 0.0 then
	if Phases ( Neuron ).Membrane_Voltage < 0.0 then
	  Weights ( Neuron, Synapse ).Excitatory
	    := Weights ( Neuron, Synapse ).Excitatory * 0.9;
	  Weights ( Neuron, Synapse ).Inhibitory
	    := Weights ( Neuron, Synapse ).Inhibitory * 1.1;
	elsif Phases ( Neuron ).Membrane_Voltage > 0.0 then
	  Weights ( Neuron, Synapse ).Excitatory
	    := Weights ( Neuron, Synapse ).Excitatory * 1.1;
	  Weights ( Neuron, Synapse ).Inhibitory
	    := Weights ( Neuron, Synapse ).Inhibitory * 0.9;
	end if;
      end if;
    end loop;
  end loop;
end Update;

procedure Update (
  Phases : in out Phases_Type;
  Inputs : in     Inputs_Type ) is
---------------------------------------------------------------------------
  Threshold : constant float := +1.0;
begin
  for Neuron in Phases'range loop
    if Phases ( Neuron ) = Fire then
      Phases ( Neuron ) := Cold;
    else
      if Inputs ( Neuron ) >= Threshold then
	Phases ( Neuron ) := Fire;
      elsif Inputs ( Neuron ) > 0.0 then
	Phases ( Neuron ) := Ooze;
      else
	Phases ( Neuron ) := Rest;
      end if;
    end if;
  end loop;
end Update;

procedure Update (
  Inputs  :    out Inputs_Type;
  Transmitters   : in     Transmitters_Type;
  Weights : in     Weights_Type ) is
---------------------------------------------------------------------------
  Exc, Inh : float;
begin
  for Neuron in Transmitters'range ( 1 ) loop
    Exc := 0.0;
    Inh := 0.0;
    for Synapse in Transmitters'range ( 2 ) loop
      Exc := Exc + Transmitters ( Neuron, Synapse )
	* Weights ( Neuron, Synapse ).Excitatory;
      Inh := Inh + Transmitters ( Neuron, Synapse )
	* Weights ( Neuron, Synapse ).Inhibitory;
    end loop;
    Inputs ( Neuron ) := Exc / ( 1.0 + Inh );
  end loop;
end Update;

procedure Update (
  Transmitters :    out Transmitters_Type;
  Phases   : in     Phases_Type ) is
---------------------------------------------------------------------------
begin
  for Neuron in Phases'range loop
    for Synapse in Transmitters'range ( 2 ) loop
      if Phases ( Synapse ) = Fire then
	Transmitters ( Neuron, Synapse ) := 1.0;
      else
	Transmitters ( Neuron, Synapse ) := 0.0;
      end if;
    end loop;
  end loop;
end Update;

---------------------------------------------------------------------------
---------------------------------------------------------------------------
end FISL;
