Save control state when form is closed - c#

Hi I am trying to save the color state of this 4x4 grid of buttons created dynamically using a 2D array into an xml document:
However when I press save I keep getting this message:
I can make this work if I use a one dimensional array for the buttons but that will not give me the grid that I want but when I use a 2D array for the buttons it wont work:
What can I change so I can get this to work any suggestion are much appreciated:
This is my code that I have:
FormState class:
public class FormState
{
public string ButtonBackColor { get; set; }
}
Form code:
public partial class Form1 : Form
{
int col = 4;
int row = 4;
Button[,] buttons;
FormState[,] states;
public Form1()
{
InitializeComponent();
buttons = new Button[col, row];
states = new FormState[col, row];
}
public void placeRows()
{
for (int r = 0; r < row; r++)
{
createColumns(r);
}
}
public void createColumns(int r)
{
int s = r * 25; //gap
for (int c = 0; c < col; c++)
{
buttons[r, c] = new Button();
buttons[r, c].SetBounds(75 * c, s, 75, 25);
buttons[r, c].Text = Convert.ToString(c);
buttons[r, c].Click += new EventHandler(grid_Click);
panel1.Controls.Add(buttons[r, c]);
}
}
int count = 0;
//backcolor change
void grid_Click(object sender, EventArgs e)
{
Button button = sender as Button;
if (count == 0)
{
button.BackColor = Color.Red;
count++;
}
else if (count == 1)
{
button.BackColor = Color.Blue;
count--;
}
}
private void Form1_Load(object sender, EventArgs e)
{
placeRows();
if (File.Exists("config.xml"))
{
loadConfig();
}
for (int i = 0; i < col; ++i)
{
for (int j = 0; j < row; ++j)
{
if (states[i,j] != null)
{
buttons[i,j].BackColor = ColorTranslator.FromHtml(states[i,j].ButtonBackColor);
}
}
}
}
//method to load file
private void loadConfig()
{
XmlSerializer ser = new XmlSerializer(typeof(FormState[]));
using (FileStream fs = File.OpenRead("config.xml"))
{
states = (FormState[,])ser.Deserialize(fs);
}
}
private void writeConfig()
{
for (int i = 0; i < col; i++)
{
for (int j = 0; j < row; j++)
{
if (states[i,j] == null)
{
states[i,j] = new FormState();
}
states[i,j].ButtonBackColor = ColorTranslator.ToHtml(buttons[i,j].BackColor);
}
using (StreamWriter sw = new StreamWriter("config.xml"))
{
XmlSerializer ser = new XmlSerializer(typeof(FormState[]));
ser.Serialize(sw, states);
}
}
}
private void btnSave_Click(object sender, EventArgs e)
{
writeConfig();
}
}

This may not be an ideal solution (and I haven't tried it, so it may not even work), but you could create a nested array instead of a 2-D array. Something like
FormStates[][] states = new FormStates[row][];
for(Int32 i = 0; i < row; i++)
{
states[i] = new FormStates[col];
}
Instead of indexing using states[i, j], you would use states[i][j]. Since 1-D arrays are serializable, this might work.
Edit
Slightly longer example, based on your code:
public partial class Form1 : Form
{
int col = 4;
int row = 4;
Button[][] buttons;
FormState[][] states;
public Form1()
{
InitializeComponent();
buttons = new Button[col][];
states = new FormState[col][];
for(Int32 c = 0; c < col; c++)
{
buttons[c] = new Button[row];
states[c] = new FormState[row];
}
}
public void createColumns(int r)
{
int s = r * 25; //gap
for (int c = 0; c < col; c++)
{
buttons[r][c] = new Button();
buttons[r][c].SetBounds(75 * c, s, 75, 25);
buttons[r][c].Text = Convert.ToString(c);
buttons[r][c].Click += new EventHandler(grid_Click);
panel1.Controls.Add(buttons[r][c]);
}
}
}
This should be enough to give you the syntax to change the rest of your code.
You will also want to change your XmlSerializer declarations to use typeof(FormState[][]) instead of just typeof(FormState[]).

Admittedly I haven't put much thought into this but as per comments you cant serialize multi dimensional arrays so you might:
[Serializable]
public class FormState
{
public int RowIndex { get; set; }
public int ColIndex { get; set; }
public string BackColor { get; set; }
}
[Serializable]
public class Layout : Collection<FormState> {
public Layout(){}
}
..
public void SomeCallingMethod() {
Layout l = new Layout();
foreach (FormState fs in l) {
buttons[fs.RowIndex, fs.ColIndex].BackColor = ColorTranslator.FromHtml(fs.BackColor);
}
}
Or use a List if necessary and serialize that.

Related

How do you create buttons on a form through a method created in a class?

I'm trying to create a grid of buttons based on what number of rows and columns the user enters and my method that creates the grid isn't working. When I call it the grid doesn't get created.
The method is inside my TileClass and I'm trying to call it in my GameBoard form. I feel like I'm not using the class properly. I don't think I'm calling the method correctly because I'm thinking this should work.
This is what the form looks like
class TileClass : Button
{
public const int LEFT = 20;
public const int WIDTH = 50;
public const int HEIGHT = 50;
public const int TOP = 50;
public const int VGAP = 30;
public int x;
public int y;
public int column;
public int row;
private int incomingRow;
private int incomingColumn;
public int IncomingRow { get => incomingRow; set => incomingRow = value; }
public int IncomingColumn { get => incomingColumn; set => incomingColumn = value; }
public TileClass()
{
}
public void CreateGrid()
{
x = LEFT;
y = TOP;
column = IncomingColumn;
row = IncomingRow;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
Button b = new Button();
b.Left = x;
b.Top = y;
b.Width = WIDTH;
b.Height = HEIGHT;
b.Text = j.ToString();
x += VGAP + HEIGHT;
this.Controls.Add(b);
}
}
}
}
Gameboard Form
public partial class GameBoard : Form
{
TileClass tileClass = new TileClass();
public GameBoard()
{
InitializeComponent();
}
private void txtEnter_Click(object sender, EventArgs e)
{
tileClass.IncomingColumn = int.Parse(txtColumn.Text);
tileClass.IncomingRow = int.Parse(txtRow.Text);
tileClass.CreateGrid();
}
There's a lot to do to make it happen:
class TileClass : Panel
{
...
public int IncomingRow {get; set;}
public int IncomingColumn { get; set; }
...
}
and remove:
private int incomingRow;
private int incomingColumn;
and the ideal approach would be using ResumeLayout before adding buttons and let the Gameboard form to be redrawn by calling Invalidate. What does invalidate method do?
note: try col=100, row=100 with and without ResumeLayout&Invalidate
public partial class GameBoard : Form
{
public GameBoard ()
{
InitializeComponent();
tileClass.Dock = DockStyle.Fill;
this.Controls.Add(tileClass);
}
TileClass tileClass = new TileClass();
private void txtEnter_Click(object sender, EventArgs e)
{
tileClass.IncomingColumn = int.Parse(txtColumn.Text);
tileClass.IncomingRow = int.Parse(txtRow.Text);
this.ResumeLayout(); //Important
tileClass.CreateGrid();
this.Invalidate(); // Important
}
}
and you can set more properties like, it needs more than this:
//tileClass.Location = new Point(10, 10); // not sure
tileClass.Dock = DockStyle.Fill;
//tileClass.Size = new Size(200, 200); // not sure
and instead of j < 5 you should use col and row:
for (int i = 0; i < row; i++)
{
for (int j = 0; j < column; j++)
{
Button b = new Button();
b.Left = x;
b.Top = y;
b.Width = WIDTH;
b.Height = HEIGHT;
b.Text = string.Format("({0},{1})" , i, j);
x += VGAP + HEIGHT;
this.Controls.Add(b);
}
x = LEFT; // not sure, plz calculate!
y += Top * (i+1); // not sure, plz calculate!
}

Suggestions for non-working Radial Basis Function Neural Network

I'm creating a small C# application to help investigate different designs of Multilayer Perceptron and Radial Basis Function Neural Networks. The MLP is working adequately, but I can't manage to get the RBF Net to work at all.
I've checked and double checked and triple checked the algorithms to see if they match the algorithms that are available online and in papers and books and it seems like they do. I've also checked a colleagues (working) code and compared it to mine to see if there is anything I'd done wrong or left out and found nothing.
So I was hoping some extra eyes and opinions might help me root out the problem, as I've run out of ideas of what to try or where to look. If you want to have a look at or download the entire project you can find it at https://bitbucket.org/floofykh/gameai-coursework
I'll also post here the RBF specific code.
This is the Windows Form which allows the user to input the design of the RBF net and train it.
public partial class RBFForm : Form
{
private const double X_MAX = Math.PI * 2;
private const double X_MIN = 0;
private const double INTERVAL = Math.PI / 90d;
private double m_numPlotPoints;
private double m_noiseValue = 0;
public double StopThreshold { get { return m_stopThreshold; } }
private double m_stopThreshold;
private string m_function = "";
private List<double> m_inputs, m_targets;
private List<RadialBasisFunctionData> m_rbfsData;
private RadialBasisFunctionNetwork m_rbf;
private int m_numRBFs = 1;
private double m_rbfWidth = 1d, m_rbfOffset = 0d, m_rbfSeperation = 0d;
private bool m_changed = true;
private const int testCases = 180;
public RBFForm()
{
InitializeComponent();
ChartArea functionArea = m_functionGraph.ChartAreas.Add("function");
functionArea.AxisX.Maximum = X_MAX;
functionArea.AxisX.Minimum = X_MIN;
functionArea.AxisY.Maximum = 1.5;
functionArea.AxisY.Minimum = -1.5;
ChartArea rbfArea = m_rbfGraph.ChartAreas.Add("RBFs");
rbfArea.AxisX.Maximum = X_MAX;
rbfArea.AxisX.Minimum = X_MIN;
rbfArea.AxisY.Maximum = 1;
rbfArea.AxisY.Minimum = 0;
m_functionGraph.Series.Add("Neural Network");
m_functionGraph.Series.Add("Function");
m_functionGraph.Series.Add("Points");
m_rbfGraph.Series.Add("RBFs");
Neuron.LearningRate = ((double)(m_learningRateSelector).Value);
m_numRBFs = ((int)(m_numRBFsInput).Value);
m_rbfOffset = ((double)(m_rbfOffsetController).Value);
m_rbfSeperation = ((double)(m_rbfOffsetController).Value);
m_rbfWidth = ((double)(m_rbfWidthController).Value);
m_rbf = new RadialBasisFunctionNetwork(this);
}
private void InitialiseFunctionGraph()
{
Series func = m_functionGraph.Series.FindByName("Function");
func.Points.Clear();
func.ChartType = SeriesChartType.Line;
func.Color = Color.Green;
func.BorderWidth = 1;
for (double x = X_MIN; x < X_MAX; x += INTERVAL)
{
double y = 0;
switch (m_function)
{
case "Sin":
y = Math.Sin(x);
break;
case "Cos":
y = Math.Cos(x);
break;
};
func.Points.AddXY(x, y);
}
}
private void InitialiseRBFs()
{
m_rbfsData = new List<RadialBasisFunctionData>();
Series rbfs = m_rbfGraph.Series.FindByName("RBFs");
rbfs.Points.Clear();
rbfs.ChartType = SeriesChartType.Line;
rbfs.Color = Color.IndianRed;
rbfs.BorderWidth = 1;
for(int i=0; i<m_numRBFs; i++)
{
double centre = X_MIN + m_rbfOffset + m_rbfSeperation * i;
RadialBasisFunctionData data = new RadialBasisFunctionData();
data.Centre = centre;
data.Width = m_rbfWidth;
m_rbfsData.Add(data);
DrawRBF(centre, m_rbfWidth, rbfs.Points);
}
}
private void DrawRBF(double centre, double width, DataPointCollection points)
{
if(width > 0)
{
IActivationFunction function = new RadialBasisFunction(centre, width);
for (double x = X_MIN; x < X_MAX; x += INTERVAL)
{
double y = function.Function(x);
points.AddXY(x, y);
}
}
}
private void InitialiseInputPoints()
{
m_inputs = new List<double>();
m_targets = new List<double>();
Series points = m_functionGraph.Series.FindByName("Points");
points.Points.Clear();
points.ChartType = SeriesChartType.Point;
points.Color = Color.Blue;
points.BorderWidth = 1;
double interval = 0d;
if (m_numPlotPoints > 1)
interval = (X_MAX - X_MIN) / (m_numPlotPoints - 1);
for (int point = 0; point < m_numPlotPoints; point++)
{
double x = X_MIN + point * interval;
double y = 0;
switch (m_function)
{
case "Sin":
y = Math.Sin(x);
break;
case "Cos":
y = Math.Cos(x);
break;
};
y += (Program.rand.NextDouble() - 0.5d) * 2d * m_noiseValue;
m_targets.Add(y);
m_inputs.Add(x);
points.Points.AddXY(x, y);
}
}
public void SetNumEpochs(int num)
{
m_numEpochLabel.Text = num.ToString();
}
public void SetNumEpochsAsync(int num)
{
try
{
if (m_numEpochLabel.InvokeRequired)
{
m_numEpochLabel.Invoke((MethodInvoker)delegate
{
m_numEpochLabel.Text = num.ToString();
});
}
}
catch (Exception) { }
}
private void m_rbfSeperationController_ValueChanged(object sender, EventArgs e)
{
double value = ((double)((NumericUpDown)sender).Value);
m_rbfSeperation = value;
InitialiseRBFs();
m_changed = true;
}
private void m_numRBFsInput_ValueChanged(object sender, EventArgs e)
{
int value = ((int)((NumericUpDown)sender).Value);
m_numRBFs = value;
InitialiseRBFs();
m_changed = true;
}
private void m_rbfWidthController_ValueChanged(object sender, EventArgs e)
{
double value = ((double)((NumericUpDown)sender).Value);
m_rbfWidth = value;
InitialiseRBFs();
m_changed = true;
}
private void m_rbfOffsetController_ValueChanged(object sender, EventArgs e)
{
double value = ((double)((NumericUpDown)sender).Value);
m_rbfOffset = value;
InitialiseRBFs();
m_changed = true;
}
private void m_learningRateSelector_ValueChanged(object sender, EventArgs e)
{
double value = ((double)((NumericUpDown)sender).Value);
Neuron.LearningRate = value;
m_changed = true;
}
private void m_momentumController_ValueChanged(object sender, EventArgs e)
{
double value = ((double)((NumericUpDown)sender).Value);
Neuron.MomentumAlpha = value;
m_changed = true;
}
private void m_thresholdController_ValueChanged(object sender, EventArgs e)
{
double value = ((double)((NumericUpDown)sender).Value);
m_stopThreshold = value;
m_changed = true;
}
private void m_functionSelector_SelectedIndexChanged(object sender, EventArgs e)
{
m_function = ((ComboBox)sender).SelectedItem.ToString();
InitialiseFunctionGraph();
m_changed = true;
}
private void m_plotPointsController_ValueChanged(object sender, EventArgs e)
{
double value = ((double)((NumericUpDown)sender).Value);
m_numPlotPoints = value;
InitialiseInputPoints();
m_changed = true;
}
private void m_noiseController_ValueChanged(object sender, EventArgs e)
{
double value = ((double)((NumericUpDown)sender).Value);
m_noiseValue = value;
InitialiseInputPoints();
m_changed = true;
}
private void m_trainButton_Click(object sender, EventArgs e)
{
if (m_rbf != null)
{
if (RadialBasisFunctionNetwork.Running)
{
RadialBasisFunctionNetwork.Running = false;
}
else
{
if (m_changed)
{
m_rbf.Initialise(1, m_rbfsData, 1);
m_changed = false;
}
RadialBasisFunctionNetwork.ErrorStopThreshold = m_stopThreshold;
List<List<double>> inputPatterns = new List<List<double>>();
List<List<double>> targetPatterns = new List<List<double>>();
for (int i = 0; i < m_inputs.Count; i++)
{
List<double> newInputPattern = new List<double>();
newInputPattern.Add(m_inputs[i]);
List<double> newTargetPattern = new List<double>();
newTargetPattern.Add(m_targets[i]);
inputPatterns.Add(newInputPattern);
targetPatterns.Add(newTargetPattern);
}
m_rbf.Train(inputPatterns, targetPatterns);
}
}
}
public void TestAndPresent()
{
List<double> finalData = new List<double>();
for (double x = X_MIN; x < X_MAX; x += INTERVAL)
{
List<double> input = new List<double>();
input.Add(x);
finalData.AddRange(m_rbf.Test(input));
}
PlotNeuralOutput(finalData);
}
public void TestAndPresentAsync()
{
List<double> finalData = new List<double>();
for (double x = X_MIN; x < X_MAX; x += INTERVAL)
{
List<double> input = new List<double>();
input.Add(x);
finalData.AddRange(m_rbf.Test(input));
}
PlotNeuralOutputAsync(finalData);
}
public void PlotNeuralOutput(List<double> output)
{
Series network = m_functionGraph.Series["Neural Network"];
network.Points.Clear();
network.ChartType = SeriesChartType.Line;
network.Color = Color.Red;
network.BorderWidth = 3;
double x = 0;
for (int i = 0; i < output.Count; i++)
{
network.Points.AddXY(x, output[i]);
x += INTERVAL;
}
}
public void PlotNeuralOutputAsync(List<double> output)
{
try
{
if (m_functionGraph.InvokeRequired)
{
m_functionGraph.Invoke((MethodInvoker)delegate
{
Series network = m_functionGraph.Series["Neural Network"];
network.Points.Clear();
network.ChartType = SeriesChartType.Line;
network.Color = Color.Red;
network.BorderWidth = 3;
double x = 0;
for (int i = 0; i < output.Count; i++)
{
network.Points.AddXY(x, output[i]);
x += INTERVAL;
}
});
}
}
catch (Exception) { }
}
}
Here is the RadialBasisFunction class where most of the RBF algorithm takes place, specificaly in FeedForward().
class RadialBasisFunctionNetwork
{
private NeuronLayer m_inputLayer;
private NeuronLayer m_radialFunctions;
private NeuronLayer m_outputLayer;
private int m_numRadialFunctions = 0;
public static bool Running = false;
public static double ErrorStopThreshold {get; set;}
private static int m_epoch = 0;
public static int Epoch { get { return m_epoch; } }
private RBFForm m_RBFForm = null;
public RadialBasisFunctionNetwork(RBFForm RBFForm)
{
m_RBFForm = RBFForm;
m_inputLayer = new NeuronLayer();
m_radialFunctions = new NeuronLayer();
m_outputLayer = new NeuronLayer();
}
public void Initialise(int numInputs, List<RadialBasisFunctionData> radialFunctions, int numOutputs)
{
ErrorStopThreshold = 0d;
m_epoch = 0;
m_numRadialFunctions = radialFunctions.Count;
m_inputLayer.Neurons.Clear();
//Add bias neuron
/*Neuron inputBiasNeuron = new Neuron(1d);
inputBiasNeuron.Initialise(m_numRadialFunctions);
m_inputLayer.Neurons.Add(inputBiasNeuron);*/
for(int i=0; i<numInputs; i++)
{
Neuron newNeuron = new Neuron();
newNeuron.Initialise(m_numRadialFunctions);
m_inputLayer.Neurons.Add(newNeuron);
}
m_outputLayer.Neurons.Clear();
for (int i = 0; i < numOutputs; i++)
{
Neuron newNeuron = new Neuron();
m_outputLayer.Neurons.Add(newNeuron);
}
m_radialFunctions.Neurons.Clear();
//Add bias neuron
/* Neuron outputBiasNeuron = new Neuron(1d);
outputBiasNeuron.Initialise(numOutputs);
outputBiasNeuron.ActivationFunction = new ConstantActivationFunction();
m_radialFunctions.Neurons.Add(outputBiasNeuron);*/
for (int i = 0; i < m_numRadialFunctions; i++)
{
Neuron newNeuron = new Neuron();
newNeuron.Initialise(numOutputs);
newNeuron.ActivationFunction = new RadialBasisFunction(radialFunctions[i].Centre, radialFunctions[i].Width);
m_radialFunctions.Neurons.Add(newNeuron);
}
}
public void Train(List<List<double>> inputs, List<List<double>> targets)
{
Running = true;
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(
delegate(object o, DoWorkEventArgs args)
{
while (Running)
{
TrainPatterns(inputs, targets);
m_RBFForm.SetNumEpochsAsync(m_epoch);
m_RBFForm.TestAndPresentAsync();
}
});
bw.RunWorkerAsync();
}
private void TrainPatterns(List<List<double>> inputs, List<List<double>> targets)
{
Queue<int> randomIndices = GenRandomNonRepNumbers(inputs.Count, 0, inputs.Count, Program.rand);
bool trained = true;
while(randomIndices.Count > 0)
{
int index = randomIndices.Dequeue();
TrainPattern(inputs[index], targets[index]);
foreach(Neuron neuron in m_outputLayer.Neurons)
{
if (Math.Abs(neuron.Error) > ErrorStopThreshold)
trained = false;
}
}
m_epoch++;
if (trained)
Running = false;
}
public void TrainPattern(List<double> inputs, List<double> targets)
{
InitialisePatternSet(inputs, targets);
FeedForward();
}
public List<double> Test(List<double> inputs)
{
InitialisePatternSet(inputs, null);
FeedForward();
return GetOutput();
}
public void FeedForward()
{
//Feed from input
for(int i=0; i<m_radialFunctions.NumNeurons; i++)
{
Neuron radialFunctionNeuron = m_radialFunctions.Neurons[i];
radialFunctionNeuron.Output = 0d;
for(int j=0; j<m_inputLayer.NumNeurons; j++)
{
Neuron inputNeuron = m_inputLayer.Neurons[j];
radialFunctionNeuron.Output += radialFunctionNeuron.ActivationFunction.Function(inputNeuron.Output);
}
}
//Feed to output
for (int i = 0; i < m_outputLayer.NumNeurons; i++)
{
Neuron outputNeuron = m_outputLayer.Neurons[i];
outputNeuron.Output = 0d;
for (int j = 0; j < m_radialFunctions.NumNeurons; j++)
{
Neuron radialFunctionNeuron = m_radialFunctions.Neurons[j];
outputNeuron.Output += radialFunctionNeuron.Weight(i) * radialFunctionNeuron.Output;
}
outputNeuron.Error = (outputNeuron.Target - outputNeuron.Output);
}
//Update weights
for (int i = 0; i < m_radialFunctions.NumNeurons; i++)
{
Neuron radialFunctionNeuron = m_radialFunctions.Neurons[i];
for (int j = 0; j < m_outputLayer.NumNeurons; j++)
{
Neuron outputNeuron = m_outputLayer.Neurons[j];
if(Math.Abs(outputNeuron.Error) > m_RBFForm.StopThreshold)
radialFunctionNeuron.m_weights[j] += Neuron.LearningRate * outputNeuron.Error * radialFunctionNeuron.Output;
}
}
}
public List<double> GetOutput()
{
List<double> output = new List<double>();
for (int i = 0; i < m_outputLayer.NumNeurons; i++)
{
output.Add(m_outputLayer.Neurons[i].Output);
}
return output;
}
private void InitialisePatternSet(List<double> inputs, List<double> targets)
{
m_inputLayer.SetInputs(inputs, false);
if(targets != null)
{
m_outputLayer.SetTargets(targets);
}
}
private Queue<int> GenRandomNonRepNumbers(int num, int min, int max, Random generator)
{
if (max - min < num)
return null;
Queue<int> numbers = new Queue<int>(num);
for (int i = 0; i < num; i++)
{
int randNum = 0;
do
{
randNum = generator.Next(min, max);
} while (numbers.Contains(randNum));
numbers.Enqueue(randNum);
}
return numbers;
}
}
This is the Radial Basis Function I am using as an activation function
class RadialBasisFunction : IActivationFunction
{
private double m_centre = 0d, m_width = 0d;
public RadialBasisFunction(double centre, double width)
{
m_centre = centre;
m_width = width;
}
double IActivationFunction.Function(double activation)
{
double dist = activation - m_centre;
return Math.Exp(-(dist * dist) / (2 * m_width * m_width));
//return Math.Exp(-Math.Pow(dist / (2 * m_width), 2d));
//return Math.Exp(-Math.Pow(dist, 2d));
}
}
The NeuronLayer class is really just a wrapper around a List of Neurons, and isn't entirely necessary anymore, but I've been focussing on getting everything working rather than keeping my code clean and well designed.
class NeuronLayer
{
public int NumNeurons { get { return Neurons.Count; } }
public List<Neuron> Neurons { get; set; }
public NeuronLayer ()
{
Neurons = new List<Neuron>();
}
public void SetInputs(List<double> inputs, bool skipBias)
{
for (int i = 0; i < Neurons.Count; i++)
{
if(skipBias)
{
if (i != 0)
Neurons[i].Input = inputs[i-1];
}
else
{
Neurons[i].Input = inputs[i];
}
}
}
public void SetTargets(List<double> targets)
{
for (int i = 0; i < Neurons.Count; i++)
{
Neurons[i].Target = targets[i];
}
}
}
And finally the Neuron class. This class was made while I was coding the MLP and while I was still trying to figure out exactly how Neural Nets work. So unfortunately a lot of the code in it is specific to MLPs. I hope to change this once I've got everything working and can start cleaning everything and make the application more user-friendly. I'm going to add all the functions for completeness, but I've checked and double checked and I shouldn't be using any of the MLP specific code of Neuron anywhere in my RBF network. The MLP specific stuff is WithinThreshold, and all the functions after Weight(int).
class Neuron
{
private IActivationFunction m_activationFunction = null;
public IActivationFunction ActivationFunction { get { return m_activationFunction; } set { m_activationFunction = value; } }
public double Input { get { return Output; } set { Output = value; } }
public double Output { get; set; }
public double Error { get; set; }
public double Target { get; set; }
private double m_activation = 0d;
public bool WithinThreshold { get { return Math.Abs(Error) < MultilayerPerceptron.ErrorStopThreshold; } }
public static double LearningRate { get; set; }
public static double MomentumAlpha { get; set; }
public List<double> m_weights;
private List<double> m_deltaWeights;
public Neuron()
{
Output = 0d;
m_weights = new List<double>();
m_deltaWeights = new List<double>();
m_activationFunction = new TanHActFunction();
}
public Neuron(double input)
{
Input = input;
Output = input;
m_weights = new List<double>();
m_deltaWeights = new List<double>();
m_activationFunction = new TanHActFunction();
}
public void Initialise(int numWeights)
{
for(int i=0; i<numWeights; i++)
{
m_weights.Add(Program.rand.NextDouble()*2d - 1d);
}
}
public double Weight(int index)
{
if (m_weights != null && m_weights.Count > index)
return m_weights[index];
return 0d;
}
public void Feed(NeuronLayer layer, int neuronIndex)
{
List<Neuron> inputNeurons = layer.Neurons;
m_activation = 0;
for (int j = 0; j < layer.NumNeurons; j++)
{
m_activation += inputNeurons[j].Output * inputNeurons[j].Weight(neuronIndex);
}
Output = m_activationFunction.Function(m_activation);
}
public void CalculateError(NeuronLayer successor, bool outputLayer)
{
if(outputLayer)
{
Error = (Target - Output) * ActivationFunction.FunctionDeriv(Output);
}
else
{
Error = 0d;
for(int i=0; i<successor.NumNeurons; i++)
{
Neuron neuron = successor.Neurons[i];
Error += (neuron.Error * m_weights[i] * ActivationFunction.FunctionDeriv(Output));
}
}
}
public void UpdateWeights(NeuronLayer successor)
{
if (MomentumAlpha != 0)
{
for (int i = 0; i < successor.NumNeurons; i++)
{
var neuron = successor.Neurons[i];
if (m_deltaWeights.Count <= i)
{
double deltaWeight = LearningRate * neuron.Error * Output;
m_weights[i] += deltaWeight;
m_deltaWeights.Add(deltaWeight);
}
else
{
double deltaWeight = /*(1 - MomentumAlpha)*/LearningRate * neuron.Error * Output + MomentumAlpha * m_deltaWeights[i];
m_weights[i] += deltaWeight;
m_deltaWeights[i] = deltaWeight;
}
}
}
else
{
for (int i = 0; i < successor.NumNeurons; i++)
{
var neuron = successor.Neurons[i];
double deltaWeight = LearningRate * neuron.Error * Output;
m_weights[i] += deltaWeight;
}
}
}
}
I hope some extra eyes and opinions helps find my problem.
PS If you do download the source code from the repository and try run the application, please be aware that it will break if you don't set all necessary values before training, or if you press the reset button. I should get rid of the reset button, but I haven't yet. Sorry!
I found where the problem was.
I was updating the weights inside the FeedForward method. However, that method is called both when training and testing the network. So I was updating weights when I shouldn't have been, while testing the network.

Multiple List Object only can add single item to preceding lists? First list works

Multiple List Object only can add single item to preceding lists. Only adds last item for second list and of course I need all of them not just the last one.
Here is my Code:
public class MyListData
{
public List<HeaderItem> HeaderItems { get; set; }
public List<MatrixItem> MatrixItems { get; set; }
}
public MyListData GetSchedule()
{
MyListData objTab = new MyListData();
objTab.HeaderItems = new List<HeaderItem>();
//Header loop works perfectly
for(int x=0; x < 7;x++)
{
HeaderItem objItem = new HeaderItem();
objItem.strHeadName = x;
objTab.HeaderItems.Add(objItem);
}
objTab.MatrixItems = new List<MatrixItem>();
for(int x=0; x < 7;x++)
{
MatrixItem objItem = new MatrixItem();
objItem.nHRJobID = x;
objTab.MatrixItems.Add(objItem);
}
//Only adds the last one Need ALL
return objTab;
}
If I need to create a new object then how would I combine say objTab and objMatrix?
Seems to add all seven values for both HeaderItem and MatrixItem, based on the code you shared.
If you want to combine the header and Matrix item into a single list you might use a Tuple<> instead of a nested class. I've created a sample of what that would look like and included the code I used to test your sample code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace listadd
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Original GetSchedule:");
MyListData mld = GetSchedule();
for (int i = 0; i < mld.HeaderItems.Count; i++)
{
Console.WriteLine(string.Format("HeaderItem: {0}, MatrixItem: {1}", mld.HeaderItems[i].strHeadName, mld.MatrixItems[i].nHRJobID));
}
Console.WriteLine();
Console.WriteLine("Tuple GetSchedule:");
var list = GetScheduleCombined();
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(string.Format("HeaderItem: {0}, MatrixItem: {1}", list[i].Item1.strHeadName, list[i].Item2.nHRJobID));
}
Console.WriteLine();
Console.WriteLine("combined GetSchedule:");
var clist = GetScheduleCombined2();
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(string.Format("HeaderItem: {0}, MatrixItem: {1}", clist[i].hdrItm.strHeadName, clist[i].mtxItm.nHRJobID));
}
Console.ReadKey();
}
public static List<Tuple<HeaderItem, MatrixItem>> GetScheduleCombined()
{
List<Tuple<HeaderItem, MatrixItem>> list = new List<Tuple<HeaderItem, MatrixItem>>();
for (int x = 0; x < 7; x++)
{
var h = new HeaderItem();
h.strHeadName = x;
var m = new MatrixItem();
m.nHRJobID = x;
list.Add(new Tuple<HeaderItem, MatrixItem>(h, m));
}
return list;
}
public class MyCombined
{
public MyCombined()
{
hdrItm = new HeaderItem();
mtxItm = new MatrixItem();
}
public HeaderItem hdrItm { get; set; }
public MatrixItem mtxItm { get; set; }
}
public static List<MyCombined> GetScheduleCombined2()
{
List<MyCombined> list = new List<MyCombined>();
for (int x = 0; x < 7; x++)
{
var item = new MyCombined();
item.hdrItm.strHeadName = x;
item.mtxItm.nHRJobID = x;
list.Add(item);
}
return list;
}
//----- begin original sample code from question -----
public class MyListData
{
public List<HeaderItem> HeaderItems { get; set; }
public List<MatrixItem> MatrixItems { get; set; }
}
public static MyListData GetSchedule()
{
MyListData objTab = new MyListData();
objTab.HeaderItems = new List<HeaderItem>();
//Header loop works perfectly
for (int x = 0; x < 7; x++)
{
HeaderItem objItem = new HeaderItem();
objItem.strHeadName = x;
objTab.HeaderItems.Add(objItem);
}
objTab.MatrixItems = new List<MatrixItem>();
for (int x = 0; x < 7; x++)
{
MatrixItem objItem = new MatrixItem();
objItem.nHRJobID = x;
objTab.MatrixItems.Add(objItem);
}
//Only adds the last one Need ALL
return objTab;
}
// ---- End original sample code ----
}
}

Adding data to a list inside a class

I want to fill a list<int> inside a class I can't get it to work.
(Some / Most of the code is from here
The class:
class Fiu
{
public int feleseg { get; set; }
public List<int> preferencia { get; set; }
public Fiu (int _feleseg) : this()
{
feleseg = _feleseg;
}
public Fiu()
{
this.preferencia = new List<int>();
}
}
The code:
for (int i = 1; i < 4; i++)
{
Fiu ujfiu = new Fiu(0);
for (int j = 1; j < 4; j++)
{
ujfiu.preferencia[j-1] = 1;
}
}
The main goal would be filling it from excel, but right now it doesn't even put 1-s in. I don't know what's wrong.
I get a "Argument out of range exception unhandled" error.
Replace This:
ujfiu.preferencia[j-1] = 1;
With This:
ujfiu.preferencia.Add(1);

How to fire mouse click event for a user controls in a table layout panel

I got a problem to fire a mouse click event for user controls in a table layout panel. I created a user control with this class.
public partial class ComputerControl : UserControl
{
private int computerId;
public int ComputerId
{
get { return computerId; }
set { computerId = value; }
}
private String computerName;
public String ComputerName
{
get { return computerName; }
set { computerName = value; }
}
private String computerIp;
public String ComputerIp
{
get { return computerIp; }
set { computerIp = value; }
}
private String computerMacAddress;
public String ComputerMacAddress
{
get { return computerMacAddress; }
set { computerMacAddress = value; }
}
private Image computerPicture;
public Image ComputerPicture
{
get { return computerPicture; }
set { computerPicture = value; }
}
private RightClikControl rightClick = new RightClikControl();
public RightClikControl RightClick
{
get { return rightClick; }
set { rightClick = value; }
}
public ComputerControl(int computerId, String computerName, String computerIp, String computerMacAddress, Image computerPicture)
{
InitializeComponent();
ComputerId = computerId;
ComputerName = computerName;
ComputerIp = computerIp;
ComputerMacAddress = computerMacAddress;
ComputerPicture = computerPicture;
labelComputerState.Text = ComputerName;
pictureBoxComputer.Image = ComputerPicture;
}
private void ComputerControl_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
RightClick.Show();
}
}
}
I added more than one controls to table layout panel with this method.
private void InsertComputers()
{
int i, j;
tableLayoutPanelComputers.Visible = false;
tableLayoutPanelComputers.Controls.Clear();
tableLayoutPanelComputers.RowStyles.Clear();
tableLayoutPanelComputers.ColumnStyles.Clear();
tableLayoutPanelComputers.ColumnCount = tableLayoutPanelComputers.Size.Width / 130;
tableLayoutPanelComputers.RowCount = tableLayoutPanelComputers.Size.Height / 100;
for (i = 0; i < tableLayoutPanelComputers.RowCount; i++)
{
tableLayoutPanelComputers.RowStyles.Add(new RowStyle(SizeType.Absolute, 100));
}
for (j = 0; j < tableLayoutPanelComputers.ColumnCount; j++)
{
tableLayoutPanelComputers.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 130));
}
int clientCount = 0;
for (i = 0; i < tableLayoutPanelComputers.RowCount && clientConf.Count > clientCount; i++)
{
for (j = 0; j < tableLayoutPanelComputers.ColumnCount && clientConf.Count > clientCount; j++)
{
ComputerControl cc = new ComputerControl(clientConf[clientCount].ClientId, clientConf[clientCount].ClientName, clientConf[clientCount].ClientIp, clientConf[clientCount].ClientMacAddress,Images.Pc_PowerOff);
tableLayoutPanelComputers.Controls.Add(cc, j, i);
clientCount++;
}
}
tableLayoutPanelComputers.Visible = true;
}
So, when I clicked the right mouse button on a user control in a table layout panel cell any thing fire up.
What I'm coding wrong?

Categories