using System;
using SharpUtils;
using System.Collections;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
namespace Neural_Net_Library
{
/// <summary>
/// Most of the functionality for the adaline node comes from the Basic node that it inherits from.
/// </summary>
public class AdalineNode : BasicNode
{
private DebugLevel debugLevel;
private Logger log;
public AdalineNode( Logger log ) : base( log )
{
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
}
public AdalineNode( Logger log, double dLearningRate ) : base( log, 2, 1 )
{
this.NodeValues[ Values.LearningRate ] = dLearningRate;
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
}
public AdalineNode( Logger log, int nNodeValueSize, int nNodeErrorSize ) : base( log, nNodeValueSize, nNodeErrorSize )
{
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
}
public AdalineNode( Logger log, double nLearningRate, int nNodeValueSize, int nNodeErrorSize ) : base( log, nNodeValueSize, nNodeErrorSize )
{
this.NodeValues[ Values.LearningRate ] = nLearningRate;
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
}
/// <summary>
/// go through the weights for each node and if the total value is
/// less than 0 return -1 else return 1 in the transfer function
/// then store this value in the node values array.
/// </summary>
/// <param name="nID">position in the array of the data neuron.Node.Values.nodeValue ( See values in basic.cs )</param>
public override void Run( int nID )
{
if( debugLevel.TestDebugLevel( DebugLevelSet.Progress ) == true )
{
log.Log( DebugLevelSet.Progress, "Run function called with a value of " + nID.ToString(), ClassName );
}
double dTotal = 0.0;
int nCount = this.InputLinks.Count;
for( int i=0; i<nCount; i++ )
{
dTotal += ( ( BasicLink )this.InputLinks[ i ] ).WeightedInputValue( nID );
}
this.NodeValues[ nID ] = TransferFunction( dTotal );
}
/// <summary>
/// run function with bias
/// </summary>
/// <param name="nID"></param>
/// <param name="dBias"></param>
public override void Run( int nID, double dBias )
{
if( debugLevel.TestDebugLevel( DebugLevelSet.Progress ) == true )
{
log.Log( DebugLevelSet.Progress, "Run function called with a value of " + nID.ToString() + " and a bias of " + dBias.ToString(), ClassName );
}
double dTotal = 0.0;
int nCount = this.InputLinks.Count;
for( int i=0; i<nCount; i++ )
{
dTotal += ( ( BasicLink )this.InputLinks[ i ] ).WeightedInputValue( nID );
}
this.NodeValues[ nID ] = TransferFunction( dTotal, dBias );
}
/// <summary>
/// Threshold transfer function
/// </summary>
/// <param name="dValue"></param>
/// <returns></returns>
protected virtual double TransferFunction( double dValue )
{
if( debugLevel.TestDebugLevel( DebugLevelSet.Progress ) == true )
{
log.Log( DebugLevelSet.Progress, "Transfer function called with a value of " + dValue.ToString(), ClassName );
}
if( dValue < 0 )
return -1.0;
return 1.0;
}
protected virtual double TransferFunction( double dValue, double dBias )
{
if( debugLevel.TestDebugLevel( DebugLevelSet.Progress ) == true )
{
log.Log( DebugLevelSet.Progress, "Transfer function with bias called with a value of " + dValue.ToString(), ClassName );
}
dValue += dBias;
if( dValue < 0 )
return -1;
return 1.0;
}
/// <summary>
/// learn function for the adaline network
/// </summary>
public virtual void Learn()
{
if( debugLevel.TestDebugLevel( DebugLevelSet.Progress ) == true )
{
log.Log( DebugLevelSet.Progress, "learn called for adaline ", ClassName );
}
NodeErrors[ Values.NodeError ] = ( ( double )NodeValues[ Values.NodeValue ] )*-2.0;
BasicLink link;
int nCount = InputLinks.Count;
double dDelta;
for( int i=0; i<nCount; i++ )
{
link = ( BasicLink )InputLinks[ i ];
/// delta rule
dDelta = ( ( double )NodeValues[ Values.LearningRate ] ) * ( ( double )link.InputValue( Values.NodeValue ) ) * ( ( double )NodeErrors[ Values.NodeError ] );
link.UpdateWeight( dDelta );
}
}
public new string ClassName
{
get
{
return this.ToString();
}
}
/// <summary>
/// save the current node
/// </summary>
/// <param name="xmlWriter"></param>
public override void Save( XmlWriter xmlWriter )
{
xmlWriter.WriteStartElement( "AdalineNode" );
base.Save( xmlWriter );
xmlWriter.WriteEndElement();
}
/// <summary>
/// load the node
/// </summary>
/// <param name="xmlReader"></param>
public override void Load( XmlReader xmlReader )
{
bool bBreak = false;
for( ;; )
{
xmlReader.Read();
switch( xmlReader.Name )
{
case "BasicNode": base.Load( xmlReader ); bBreak = true; break;
}
if( bBreak == true )
break;
}
}
}
/// <summary>
/// adaline link class
/// </summary>
public class AdalineLink : BasicLink
{
/// <summary>
/// pass constructor call back to the default constructor
/// </summary>
/// <param name="log"></param>
public AdalineLink( Logger log ) : base( log )
{
arrayLinkValues[ Values.Weight ] = Values.Random( -1, 1 );
}
/// <summary>
/// constructor added to simplify bam inheritance
/// </summary>
/// <param name="log">logger</param>
/// <param name="valueMin">minimum random value</param>
/// <param name="valueMax">maximum random value</param>
public AdalineLink( Logger log, double valueMin, double valueMax ) : base( log )
{
if( valueMin == 0 && valueMax == 0 )
{
arrayLinkValues[ Values.Weight ] = 0;
}
else
arrayLinkValues[ Values.Weight ] = Values.Random( valueMin, valueMax );
}
/// <summary>
/// save the current object
/// </summary>
/// <param name="xmlWriter"></param>
public override void Save( XmlWriter xmlWriter )
{
xmlWriter.WriteStartElement( "AdalineLink" );
base.Save( xmlWriter );
xmlWriter.WriteEndElement();
}
/// <summary>
/// reload the current object
/// </summary>
/// <param name="xmlReader"></param>
public override void Load( XmlReader xmlReader )
{
bool bBreak = false;
/// reader is on an adaline node
for( ;; )
{
xmlReader.Read();
switch( xmlReader.Name )
{
case "BasicLink": base.Load( xmlReader ); bBreak = true; break;
}
if( bBreak == true )
break;
}
}
/// <summary>
/// get the class name
/// </summary>
public new string ClassName
{
get
{
return this.ToString();
}
}
}
/// <summary>
/// implement the basic neuron class
/// </summary>
public class AdalineNeuron : BasicNeuron
{
private AdalineNode adalineNode;
protected ArrayList arrayLinks;
private DebugLevel debugLevel;
private Logger log;
public AdalineNode Node
{
get
{
return adalineNode;
}
set
{
adalineNode = value;
}
}
public ArrayList Links
{
get
{
return arrayLinks;
}
}
/// <summary>
/// constructor
/// </summary>
/// <param name="basicNodeInputNodeOne"></param>
/// <param name="basicNodeInputNodeTwo"></param>
/// <param name="biasNodeBias"></param>
/// <param name="adalineNode"></param>
public AdalineNeuron( Logger log, BasicNode basicNodeInputNodeOne, BasicNode basicNodeInputNodeTwo, AdalineNode adalineNode ) : base( log, basicNodeInputNodeOne, basicNodeInputNodeTwo )
{
Node = adalineNode;
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
arrayLinks = new ArrayList();
for( int i=0; i<2; i++ )
arrayLinks.Add( new AdalineLink( log ) );
BuildLinks();
}
public AdalineNeuron( Logger log, BasicNode basicNodeInputNodeOne, BasicNode basicNodeInputNodeTwo ) : base( log, basicNodeInputNodeOne, basicNodeInputNodeTwo )
{
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
}
/// <summary>
/// build the adaline neuron links
/// </summary>
public override void BuildLinks()
{
/// create the connections
this.InputNodeOne.CreateLink( ( BasicNode )this.Node, ( BasicLink )this.Links[ 0 ] );
this.InputNodeTwo.CreateLink( ( BasicNode )this.Node, ( BasicLink )this.Links[ 1 ] );
}
public new string ClassName
{
get
{
return this.ToString();
}
}
/// <summary>
/// return current information as a string
/// </summary>
public new string Data
{
get
{
StringBuilder strString = new StringBuilder();
strString.Append( base.Data );
strString.Append( " AdalineNode values: Node Values = " );
for( int i=0; i<adalineNode.NodeValues.Count; i++ )
{
strString.Append( " value " + i.ToString() + " = " + adalineNode.NodeValues[ i ].ToString() );
}
strString.Append( " : Node Errors = " );
for( int i=0; i<adalineNode.NodeErrors.Count; i++ )
{
strString.Append( " value " + i.ToString() + " = " + adalineNode.NodeErrors[ i ].ToString() );
}
strString.Append( " : Node Input Links = " );
for( int i=0; i<adalineNode.InputLinks.Count; i++ )
{
strString.Append( " value " + i.ToString() + " = " + adalineNode.InputLinks[ i ].ToString() );
}
strString.Append( " : Node Output Links = " );
for( int i=0; i<adalineNode.OutputLinks.Count; i++ )
{
strString.Append( " value " + i.ToString() + " = " + adalineNode.OutputLinks[ i ].ToString() );
}
return strString.ToString();
}
}
/// <summary>
/// save the current neuron
/// </summary>
/// <param name="xmlWriter"></param>
public override void Save( XmlWriter xmlWriter )
{
xmlWriter.WriteStartElement( "AdalineNeuron" );
base.Save( xmlWriter );
adalineNode.Save( xmlWriter );
for( int i=0; i<arrayLinks.Count; i++ )
( ( AdalineLink )arrayLinks[ i ] ).Save( xmlWriter );
xmlWriter.WriteEndElement();
}
/// <summary>
/// load a saved neuron
/// </summary>
public override void Load( XmlReader xmlReader )
{
bool bBreak = false;
while( xmlReader.Read() == true )
{
switch( xmlReader.NodeType )
{
case XmlNodeType.Element:
{
switch( xmlReader.Name )
{
case "BasicNeuron" : base.Load( xmlReader ); break;
case "AdalineNode" : adalineNode.Load( xmlReader ); break;
case "AdalineLink" :
{
/// load the three adaline links
for( int i=0; i<arrayLinks.Count; i++ )
{
bBreak = false;
( ( AdalineLink )arrayLinks[ i ] ).Load( xmlReader );
/// move the reader to the start of the next one
for( ;; )
{
switch( xmlReader.NodeType )
{
case XmlNodeType.Element:
{
switch( xmlReader.Name )
{
case "AdalineLink" : bBreak = true; break;
}
} break;
}
/// escape after done final one
if( bBreak == true || i+1 == arrayLinks.Count )
break;
xmlReader.Read();
}
}
}break;
}
}break;
}
}
BuildLinks();
}
}
/// <summary>
/// adaline pattern class
/// </summary>
public class AdalinePattern : Pattern
{
private DebugLevel debugLevel;
private Logger log;
/// <summary>
/// constructor
/// </summary>
public AdalinePattern( Logger log ) : base( log )
{
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
}
/// <summary>
/// constructor taking the input and the output sizes
/// </summary>
/// <param name="nInSize"></param>
/// <param name="nOutSize"></param>
public AdalinePattern( Logger log, int nInSize, int nOutSize ) : base( log, nInSize, nOutSize )
{
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
}
public AdalinePattern( Logger log, ArrayList arrayInSet, ArrayList arrayOutSet ) : base( log, arrayInSet, arrayOutSet )
{
debugLevel = new DebugLevel( DebugLevel.currentLevel );
this.log = log;
}
public new string ClassName()
{
return this.ToString();
}
public string Data()
{
StringBuilder strString = new StringBuilder();
strString.Append( "Pattern ID = " + this.PatternID.ToString() );
for( int n=0; n<this.InputSize(); n++ )
strString.Append( " Input Value " + n.ToString() + " = " + this.InSet[ n ].ToString() + " " );
for( int n=0; n<this.OutputSize(); n++ )
strString.Append( " Output Value " + n.ToString() + " = " + this.OutSet[ n ].ToString() + " " );
return strString.ToString();
}
}
}