Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed yesterday.
Improve this question
For expert in algorithm and C#.
The goal is to divide the 50 people into 10 tables. So 5 people per table. Each person has 2 minutes to introduce themselves to the 4 others. Once everyone has introduced themselves, everyone changes tables. And that in 10 rounds. Two people cannot meet twice
Here's the code I have done :
internal class Program
{
private static void Main(string[] args)
{
int biggestNumberOfGroupCreated = 0;
List<Group> biggestGroupes = new List<Group>();
Start:
// Créer une liste de toutes les personnes
List<int> people = new List<int>();
List<Group> groups = new List<Group>();
List<PersonAlreadyUsed> PeopleAlreadyUsed = CreateListPersonAlreadyUsed();
// Generate person name from 1 to 50
for (int i = 0; i < 50; i++)
{
people.Add(i);
}
List<Couple> couples = new();
GenerateCouples(couples);
//Generate 10 rounds
for (int round = 0; round < 10; round++)
{
ResetAlreadyUsedPeople(PeopleAlreadyUsed);
for (int table = 0; table < 9; table++)
{
Group groupe = new();
for (int chair = 0; chair < 5; chair++)
{
if (chair == 0)
{
int randomElement = GetRandomElement(PeopleAlreadyUsed);
groupe.users[chair] = people[randomElement];
Console.WriteLine($"First seated person {people[randomElement]} for round : {round} in table : {table}");
var alreadyUsed = PeopleAlreadyUsed.FirstOrDefault(x => x.Person == randomElement);
alreadyUsed.AlreadyUsed = true;
}
else
{
bool CanBeAdd = false;
int MemoUser = 0;
int u = 0;
int cptInWhileLoop = 0;
while (!CanBeAdd)
{
bool ret = false;
//Check if the new people can be added
for (int c = 0; c < chair; c++)
{
MemoUser = u;
ret = CheckedIfCanBeAdd(u, groupe.users[c], couples);
if (ret == false)
{
break;
}
}
CanBeAdd = ret;
u = GetUnusedPerson(PeopleAlreadyUsed, cptInWhileLoop);
if (u == -1)
{
Console.WriteLine($"All person already used {groups.Count}");
if (groups.Count > biggestNumberOfGroupCreated)
{
biggestNumberOfGroupCreated = groups.Count;
biggestGroupes = new();
foreach (var g in groups)
{
biggestGroupes.Add(g);
}
}
goto Start;
}
cptInWhileLoop++;
}
if (CanBeAdd == true)
{
groupe.users[chair] = MemoUser;
var personAlreadyUsed = PeopleAlreadyUsed.FirstOrDefault(x => x.Person == MemoUser);
personAlreadyUsed.AlreadyUsed = true;
}
}
}
groups.Add(groupe);
}
}
}
private static void GenerateCouples(List<Couple> couples)
{
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 50; j++)
{
if (i != j)
{
couples.Add(new Couple { x = i, y = j, Affected = false });
}
}
}
}
private static int GetUnusedPerson(List<PersonAlreadyUsed> personneDejUtilisees, int cptInWhileLoop)
{
var unusedPeople = personneDejUtilisees.Where(x=>x.AlreadyUsed==false).ToList();
if (unusedPeople.Count==0)
{
return -1;
}
// Retrieve a random element from the list using the random index
try
{
var randomPerson = unusedPeople[cptInWhileLoop];
return randomPerson.Person;
}
catch (Exception)
{
return -1;
}
}
private static void ResetAlreadyUsedPeople(List<PersonAlreadyUsed> personAlreadyUsed)
{
for (int i = 0; i < 50; i++)
{
personAlreadyUsed[i].AlreadyUsed = false;
}
}
private static List<PersonAlreadyUsed> CreateListPersonAlreadyUsed()
{
List < PersonAlreadyUsed > people = new();
for (int i = 0; i < 50; i++)
{
PersonAlreadyUsed dejUtilisee = new() { Person = i, AlreadyUsed = false };
people.Add(dejUtilisee);
}
return people;
}
private static bool CheckedIfCanBeAdd(int p, int v, List<Couple> couples)
{
bool ret = false;
if (p != v)
{
var comb1 = couples.FirstOrDefault(c => c.x == p && c.y == v);
var comb2 = couples.FirstOrDefault(c => c.x == v && c.y == p);
if (comb1.Affected == false && comb2.Affected == false)
{
ret = true;
comb1.Affected = true;
comb2.Affected = true;
}
}
return ret;
}
private static int GetRandomElement(List<PersonAlreadyUsed> personAlreadyUsed)
{
Random rand = new Random();
var peronStillAvailble = personAlreadyUsed.Where(x=>x.AlreadyUsed==false).ToList();
int randomIndex = rand.Next(peronStillAvailble.Count);
int randomElement = peronStillAvailble[randomIndex].Person;
return randomElement;
}
private static void AddCouple(Group groupe, List<Couple> couples)
{
foreach (var u1 in groupe.users)
{
foreach (var u2 in groupe.users)
{
if (u1 != u2)
{
var comb1 = couples.FirstOrDefault(c => c.x == u1 && c.y == u2);
var comb2 = couples.FirstOrDefault(c => c.x == u2 && c.y == u1);
comb1.Affected = true;
comb2.Affected = true;
}
}
}
}
}
public class PersonAlreadyUsed
{
public int Person { get; set; } =0;
public bool AlreadyUsed { get; set; }=false;
}
public class Couple
{
public int x { get; set; }
public int y { get; set; }
public bool Affected { get; set; }
}
public class Group
{
public int[] users { get; set; } = new int[5];
}
It seems that there is no solution.
Do you confirm?
I'm trying to build a class to create Aroon series. But it seems I don't understand the steps well. I'm not sure about for what purpose I have to use the period parameter.
Here is my first attempt:
/// <summary>
/// Aroon
/// </summary>
public class Aroon : IndicatorCalculatorBase
{
public override List<Ohlc> OhlcList { get; set; }
public int Period { get; set; }
public Aroon(int period)
{
this.Period = period;
}
/// <summary>
/// Aroon up: {((number of periods) - (number of periods since highest high)) / (number of periods)} x 100
/// Aroon down: {((number of periods) - (number of periods since lowest low)) / (number of periods)} x 100
/// </summary>
/// <see cref="http://www.investopedia.com/ask/answers/112814/what-aroon-indicator-formula-and-how-indicator-calculated.asp"/>
/// <returns></returns>
public override IIndicatorSerie Calculate()
{
AroonSerie aroonSerie = new AroonSerie();
int indexToProcess = 0;
while (indexToProcess < this.OhlcList.Count)
{
List<Ohlc> tempOhlc = this.OhlcList.Skip(indexToProcess).Take(Period).ToList();
indexToProcess += tempOhlc.Count;
for (int i = 0; i < tempOhlc.Count; i++)
{
int highestHighIndex = 0, lowestLowIndex = 0;
double highestHigh = tempOhlc.Min(x => x.High), lowestLow = tempOhlc.Max(x => x.Low);
for (int j = 0; j < i; j++)
{
if (tempOhlc[j].High > highestHigh)
{
highestHighIndex = j;
highestHigh = tempOhlc[j].High;
}
if (tempOhlc[j].Low < lowestLow)
{
lowestLowIndex = j;
lowestLow = tempOhlc[j].Low;
}
}
int up = ((this.Period - (i - highestHighIndex)) / this.Period) * 100;
aroonSerie.Up.Add(up);
int down = ((this.Period - (i - lowestLowIndex)) / this.Period) * 100;
aroonSerie.Down.Add(down);
}
}
return aroonSerie;
}
}
Is there anyone else tried to do that before?
Here is the csv file I use:
https://drive.google.com/file/d/0Bwv_-8Q17wGaRDVCa2FhMWlyRUk/view
But the result sets for Aroon up and down don't match with the results of aroon function in TTR package for R.
table <- read.csv("table.csv", header = TRUE, sep = ",")
trend <- aroon(table[,c("High", "Low")], n=5)
View(trend)
Screenshot of R result:
Thanks in advance,
#anilca,
for full Disclosure, I learned alot of things to answer your question(i knew nothing in the Finetec...). Thank you! it was an interesting experience!
There are several problems in your implementation:
In the statements:
i - highestHighIndex
and
i - lowestLowIndex
the variable "i" is less or equal to highestHighIndex, lowestLowIndex
so statements:
this.Period - (i - highestHighIndex)
and
this.Period - (i - lowestLowIndex)
will returns the wrong values (most of the time...)
Aroon up and down both of them are percentage, therefore "int" is a wrong data structure.
Because all variables in:
(this.Period - (i - highestHighIndex)) / this.Period)
and
((this.Period - (i - lowestLowIndex)) / this.Period)
are integers you won't recieve the right value.
one more thing the numbers in your excel are sorted from the newest to the oldest.(it effects on the R package)
I've implemented the algorithm based on your code(and your data order...)
public class Aroon : IndicatorCalculatorBase
{
public override List<OhlcSample> OhlcList { get; set; }
private readonly int _period;
public int Period
{
get { return _period; }
}
public Aroon(int period)
{
_period = period;
}
public override IIndicatorSerie Calculate()
{
var aroonSerie = new AroonSerie();
for (var i = _period; i < OhlcList.Count; i++)
{
var aroonUp = CalculateAroonUp(i);
var aroonDown = CalculateAroonDown(i);
aroonSerie.Down.Add(aroonDown);
aroonSerie.Up.Add(aroonUp);
}
return aroonSerie;
}
private double CalculateAroonUp(int i)
{
var maxIndex = FindMax(i - _period, i);
var up = CalcAroon(i - maxIndex);
return up;
}
private double CalculateAroonDown(int i)
{
var minIndex = FindMin(i - _period, i);
var down = CalcAroon(i - minIndex);
return down;
}
private double CalcAroon(int numOfDays)
{
var result = ((_period - numOfDays)) * ((double)100 / _period);
return result;
}
private int FindMin(int startIndex, int endIndex)
{
var min = double.MaxValue;
var index = startIndex;
for (var i = startIndex; i <= endIndex; i++)
{
if (min < OhlcList[i].Low)
continue;
min = OhlcList[i].Low;
index = i;
}
return index;
}
private int FindMax(int startIndex, int endIndex)
{
var max = double.MinValue;
var index = startIndex;
for (var i = startIndex; i <= endIndex; i++)
{
if (max > OhlcList[i].High)
continue;
max = OhlcList[i].High;
index = i;
}
return index;
}
}
public abstract class IndicatorCalculatorBase
{
public abstract List<OhlcSample> OhlcList { get; set; }
public abstract IIndicatorSerie Calculate();
}
public interface IIndicatorSerie
{
List<double> Up { get; }
List<double> Down { get; }
}
internal class AroonSerie : IIndicatorSerie
{
public List<double> Up { get; private set; }
public List<double> Down { get; private set; }
public AroonSerie()
{
Up = new List<double>();
Down = new List<double>();
}
}
public class OhlcSample
{
public double High { get; private set; }
public double Low { get; private set; }
public OhlcSample(double high, double low)
{
High = high;
Low = low;
}
}
Use this test method for debugging:
private Aroon _target;
[TestInitialize]
public void TestInit()
{
_target=new Aroon(5)
{
OhlcList = new List<OhlcSample>
{
new OhlcSample(166.90, 163.65),
new OhlcSample(165.00, 163.12),
new OhlcSample(165.91, 163.21),
new OhlcSample(167.29, 165.11),
new OhlcSample(169.99, 166.84),
new OhlcSample(170.92, 167.90),
new OhlcSample(168.47, 165.90),
new OhlcSample(167.75, 165.75),
new OhlcSample(166.14, 161.89),
new OhlcSample(164.77, 161.44),
new OhlcSample(163.19, 161.49),
new OhlcSample(162.50, 160.95),
new OhlcSample(163.25, 158.84),
new OhlcSample(159.20, 157.00),
new OhlcSample(159.33, 156.14),
new OhlcSample(160.00, 157.00),
new OhlcSample(159.35, 158.07),
new OhlcSample(160.70, 158.55),
new OhlcSample(160.90, 157.66),
new OhlcSample(164.38, 158.45),
new OhlcSample(167.75, 165.70),
new OhlcSample(168.93, 165.60),
new OhlcSample(165.73, 164.00),
new OhlcSample(167.00, 164.66),
new OhlcSample(169.35, 165.01),
new OhlcSample(168.12, 164.65),
new OhlcSample(168.89, 165.79),
new OhlcSample(168.65, 165.57),
new OhlcSample(170.85, 166.00),
new OhlcSample(171.61, 169.10)
}
};
}
[TestMethod]
public void JustToHelpYou()
{
var result = _target.Calculate();
var expectedUp = new List<double>()
{
100,80,60,40,20,0,0,0, 0,0,40,20,0,100,100,100,100,80, 60,100,80,60,40,100,100
};
var expectedDown = new List<double>
{
20,0,0,100,100,80,100,100,100,100,80,60,40,20,0,0,40,20,0,0,40,20,0,40,20
};
Assert.IsTrue( result.Up.SequenceEqual(expectedUp));
Assert.IsTrue( result.Down.SequenceEqual(expectedDown));
}
Just Add implementation of method HighestBarNum and LowestBarnum from your code
public class Aroon
{
public bool AroonDown
{
get;
set;
}
public double Period
{
get;
set;
}
public Aroon()
{
}
public IList<double> Execute(IList<double> src)
{
if (!this.AroonDown)
{
return this.ExecuteUp(src);
}
return this.ExecuteDown(src);
}
public IList<double> ExecuteDown(IList<double> src)
{
double[] period = new double[src.Count];
for (int i = 1; i < src.Count; i++)
{
double num = LowestBarNum(src, i, Period);
period[i] = 100 * (Period - num) / Period;
}
return period;
}
public IList<double> ExecuteUp(IList<double> src)
{
double[] period = new double[src.Count];
for (int i = 1; i < src.Count; i++)
{
double num = HighestBarNum(src, i, Period);
period[i] = 100 * ((Period - num) / Period;
}
return period;
}}
class AroonData
{
public double AroonUp;
public double AroonDown;
}
Calculation Class:
class AroonCalculationData
{
public double PeriodHigh;
public double PeriodLow;
public double SetAroonUp(List<MarketData> period, double lastHigh)
{
/*reverse the set so we can look at it from the current tick
on back, and ticksSinceHigh will set correctly*/
period.Reverse();
int ticksSinceHigh = 0;
double high = 0.0;//Set 0 so anything will be higher
for (int i = 0; i < period.Count; i++)
{
if (period[i].high > high)
{
high = period[i].high;
ticksSinceHigh = i;
}
}
/*This bit if for if the high just ticked out
of List<MarketData>.
Including the current tick (i = 0), List<MarketData> period
only looks back (period - 1) days.
This Checks to see if the last high is still in the set. if it's
not, and is still the high for the period, then ticksSinceHigh
is set to (period)*/
PeriodHigh = high;
if (PeriodHigh < lastHigh)
{
ticksSinceHigh = period.Count;
}
/*Aroon-Up Formula*/
return (double)(period.Count - ticksSinceHigh ) / (double)period.Count * 100.0;
}
//ASIDE FROM LOOKING FOR LOWS INSTEAD OF HIGHS, SAME AS AROON-UP
public double SetAroonDown(List<MarketData> period, double lastLow)
{
period.Reverse();
int daysSinceLow = 0;
double low = double.MaxValue;//Set max so anything will be lower
for (int i = 0; i < period.Count; i++)
{
if (period[i].low < low)
{
low = period[i].low;
daysSinceLow = i;
}
}
PeriodLow = low;
if (PeriodLow > lastLow)
{
daysSinceLow = period.Count;
}
return (double)(period.Count - daysSinceLow) / (double)period.Count * 100.0;
}
}
Calling code:
public AroonData[] Aroon(List<MarketData> marketData, int period)
{
AroonCalculationData[] calculationData = new AroonCalculationData[marketData.Count]
AroonData[] aroon= new AroonData[marketData.Count]
for (int i = period; i < marketData.Count; i++)
{
/*GetRange(i - period + 1, period) add 1 so that the current tick is
included in look back.
For example, if (period = 10) the first loop (i = 10) then (i -
period + 1) = 1 the set will be marketData 1 - 10.*/
/*calculationData[i - 1].PeriodHigh and calculationData[i - 1].PeriodLow
are for looking back at the last tick's look back period high and
low*/
data[i].AroonUp = calculationData[i].SetAroonUp(marketData.GetRange(i - period + 1, period), calculationData[i - 1].PeriodHigh);
data[i].AroonDown = calculationData[i].SetAroonDown(marketData.GetRange(i - period + 1, period), calculationData[i - 1].PeriodLow);
}
}
Side note:
One problem I had was comparing my data to TD Ameritrades Aroon, until i figured out their period is really period-1, so if you're comparing to TD keep that in mind.
Update 1/6/2014: I've updated the question so that I'm trying to solve a non-linear equation. As many of you pointed out I didn't need the extra complexity (hidden-layer, sigmoid function, etc) in order to solve a non-linear problem.
Also, I realize I could probably solve even non-linear problems like this using other means besides neural networks. I'm not trying to write the most efficient code or the least amount of code. This is purely for me to better learn neural networks.
I've created my own implementation of back propagated neural network.
It is working fine when trained to solve simple XOR operations.
However now I want to adapt it & train it to solve Y = X * X + B type formulas, but I'm not getting expected results. After training the network does not calculate the correct answers. Are neural networks well-suited for solving algebra equations like this? I realize my example is trivial I'm just trying to learn more about neural networks and their capabilities.
My hidden layer is using a sigmoid activation function and my output layer is using an identity function.
If you could analyze my code and point out any errors I'd be grateful.
Here is my full code (C# .NET):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NeuralNetwork
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Training Network...");
Random r = new Random();
var network = new NeuralNetwork(1, 5, 1);
for (int i = 0; i < 100000; i++)
{
int x = i % 15;
int y = x * x + 10;
network.Train(x);
network.BackPropagate(y);
}
//Below should output 20, but instead outputs garbage
Console.WriteLine("0 * 0 + 10 = " + network.Compute(0)[0]);
//Below should output 110, but instead outputs garbage
Console.WriteLine("10 * 10 + 10 = " + network.Compute(10)[0]);
//Below should output 410, but instead outputs garbage
Console.WriteLine("20 * 20 + 10 = " + network.Compute(20)[0]);
}
}
public class NeuralNetwork
{
public double LearnRate { get; set; }
public double Momentum { get; set; }
public List<Neuron> InputLayer { get; set; }
public List<Neuron> HiddenLayer { get; set; }
public List<Neuron> OutputLayer { get; set; }
static Random random = new Random();
public NeuralNetwork(int inputSize, int hiddenSize, int outputSize)
{
LearnRate = .9;
Momentum = .04;
InputLayer = new List<Neuron>();
HiddenLayer = new List<Neuron>();
OutputLayer = new List<Neuron>();
for (int i = 0; i < inputSize; i++)
InputLayer.Add(new Neuron());
for (int i = 0; i < hiddenSize; i++)
HiddenLayer.Add(new Neuron(InputLayer));
for (int i = 0; i < outputSize; i++)
OutputLayer.Add(new Neuron(HiddenLayer));
}
public void Train(params double[] inputs)
{
int i = 0;
InputLayer.ForEach(a => a.Value = inputs[i++]);
HiddenLayer.ForEach(a => a.CalculateValue());
OutputLayer.ForEach(a => a.CalculateValue());
}
public double[] Compute(params double[] inputs)
{
Train(inputs);
return OutputLayer.Select(a => a.Value).ToArray();
}
public double CalculateError(params double[] targets)
{
int i = 0;
return OutputLayer.Sum(a => Math.Abs(a.CalculateError(targets[i++])));
}
public void BackPropagate(params double[] targets)
{
int i = 0;
OutputLayer.ForEach(a => a.CalculateGradient(targets[i++]));
HiddenLayer.ForEach(a => a.CalculateGradient());
HiddenLayer.ForEach(a => a.UpdateWeights(LearnRate, Momentum));
OutputLayer.ForEach(a => a.UpdateWeights(LearnRate, Momentum));
}
public static double NextRandom()
{
return 2 * random.NextDouble() - 1;
}
public static double SigmoidFunction(double x)
{
if (x < -45.0) return 0.0;
else if (x > 45.0) return 1.0;
return 1.0 / (1.0 + Math.Exp(-x));
}
public static double SigmoidDerivative(double f)
{
return f * (1 - f);
}
public static double HyperTanFunction(double x)
{
if (x < -10.0) return -1.0;
else if (x > 10.0) return 1.0;
else return Math.Tanh(x);
}
public static double HyperTanDerivative(double f)
{
return (1 - f) * (1 + f);
}
public static double IdentityFunction(double x)
{
return x;
}
public static double IdentityDerivative()
{
return 1;
}
}
public class Neuron
{
public bool IsInput { get { return InputSynapses.Count == 0; } }
public bool IsHidden { get { return InputSynapses.Count != 0 && OutputSynapses.Count != 0; } }
public bool IsOutput { get { return OutputSynapses.Count == 0; } }
public List<Synapse> InputSynapses { get; set; }
public List<Synapse> OutputSynapses { get; set; }
public double Bias { get; set; }
public double BiasDelta { get; set; }
public double Gradient { get; set; }
public double Value { get; set; }
public Neuron()
{
InputSynapses = new List<Synapse>();
OutputSynapses = new List<Synapse>();
Bias = NeuralNetwork.NextRandom();
}
public Neuron(List<Neuron> inputNeurons) : this()
{
foreach (var inputNeuron in inputNeurons)
{
var synapse = new Synapse(inputNeuron, this);
inputNeuron.OutputSynapses.Add(synapse);
InputSynapses.Add(synapse);
}
}
public virtual double CalculateValue()
{
var d = InputSynapses.Sum(a => a.Weight * a.InputNeuron.Value) + Bias;
return Value = IsHidden ? NeuralNetwork.SigmoidFunction(d) : NeuralNetwork.IdentityFunction(d);
}
public virtual double CalculateDerivative()
{
var d = Value;
return IsHidden ? NeuralNetwork.SigmoidDerivative(d) : NeuralNetwork.IdentityDerivative();
}
public double CalculateError(double target)
{
return target - Value;
}
public double CalculateGradient(double target)
{
return Gradient = CalculateError(target) * CalculateDerivative();
}
public double CalculateGradient()
{
return Gradient = OutputSynapses.Sum(a => a.OutputNeuron.Gradient * a.Weight) * CalculateDerivative();
}
public void UpdateWeights(double learnRate, double momentum)
{
var prevDelta = BiasDelta;
BiasDelta = learnRate * Gradient; // * 1
Bias += BiasDelta + momentum * prevDelta;
foreach (var s in InputSynapses)
{
prevDelta = s.WeightDelta;
s.WeightDelta = learnRate * Gradient * s.InputNeuron.Value;
s.Weight += s.WeightDelta + momentum * prevDelta;
}
}
}
public class Synapse
{
public Neuron InputNeuron { get; set; }
public Neuron OutputNeuron { get; set; }
public double Weight { get; set; }
public double WeightDelta { get; set; }
public Synapse(Neuron inputNeuron, Neuron outputNeuron)
{
InputNeuron = inputNeuron;
OutputNeuron = outputNeuron;
Weight = NeuralNetwork.NextRandom();
}
}
}
you use sigmoid as output funnction which in in the range [0-1]
but you target value is double the range is [ 0 - MAX_INT ], i think it is the basic resaon why you are getting NAN。
i update you code , and try to normalize the value in the range in [0-1],
and I can get ouptut like this which is what I expect
I think I am getting close to the truth,I am not sure why this answer is getting vote down
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NeuralNetwork
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Training Network...");
Random r = new Random();
var network = new NeuralNetwork(1, 3, 1);
for (int k = 0; k < 60; k++)
{
for (int i = 0; i < 1000; i++)
{
double x = i / 1000.0;// r.Next();
double y = 3 * x;
network.Train(x);
network.BackPropagate(y);
}
double output = network.Compute(0.2)[0];
Console.WriteLine(output);
}
//Below should output 10, but instead outputs either a very large number or NaN
/* double output = network.Compute(3)[0];
Console.WriteLine(output);*/
}
}
public class NeuralNetwork
{
public double LearnRate { get; set; }
public double Momentum { get; set; }
public List<Neuron> InputLayer { get; set; }
public List<Neuron> HiddenLayer { get; set; }
public List<Neuron> OutputLayer { get; set; }
static Random random = new Random();
public NeuralNetwork(int inputSize, int hiddenSize, int outputSize)
{
LearnRate = .2;
Momentum = .04;
InputLayer = new List<Neuron>();
HiddenLayer = new List<Neuron>();
OutputLayer = new List<Neuron>();
for (int i = 0; i < inputSize; i++)
InputLayer.Add(new Neuron());
for (int i = 0; i < hiddenSize; i++)
HiddenLayer.Add(new Neuron(InputLayer));
for (int i = 0; i < outputSize; i++)
OutputLayer.Add(new Neuron(HiddenLayer));
}
public void Train(params double[] inputs)
{
int i = 0;
InputLayer.ForEach(a => a.Value = inputs[i++]);
HiddenLayer.ForEach(a => a.CalculateValue());
OutputLayer.ForEach(a => a.CalculateValue());
}
public double[] Compute(params double[] inputs)
{
Train(inputs);
return OutputLayer.Select(a => a.Value).ToArray();
}
public double CalculateError(params double[] targets)
{
int i = 0;
return OutputLayer.Sum(a => Math.Abs(a.CalculateError(targets[i++])));
}
public void BackPropagate(params double[] targets)
{
int i = 0;
OutputLayer.ForEach(a => a.CalculateGradient(targets[i++]));
HiddenLayer.ForEach(a => a.CalculateGradient());
HiddenLayer.ForEach(a => a.UpdateWeights(LearnRate, Momentum));
OutputLayer.ForEach(a => a.UpdateWeights(LearnRate, Momentum));
}
public static double NextRandom()
{
return 2 * random.NextDouble() - 1;
}
public static double SigmoidFunction(double x)
{
if (x < -45.0)
{
return 0.0;
}
else if (x > 45.0)
{
return 1.0;
}
return 1.0 / (1.0 + Math.Exp(-x));
}
public static double SigmoidDerivative(double f)
{
return f * (1 - f);
}
public static double HyperTanFunction(double x)
{
if (x < -10.0) return -1.0;
else if (x > 10.0) return 1.0;
else return Math.Tanh(x);
}
public static double HyperTanDerivative(double f)
{
return (1 - f) * (1 + f);
}
public static double IdentityFunction(double x)
{
return x;
}
public static double IdentityDerivative()
{
return 1;
}
}
public class Neuron
{
public bool IsInput { get { return InputSynapses.Count == 0; } }
public bool IsHidden { get { return InputSynapses.Count != 0 && OutputSynapses.Count != 0; } }
public bool IsOutput { get { return OutputSynapses.Count == 0; } }
public List<Synapse> InputSynapses { get; set; }
public List<Synapse> OutputSynapses { get; set; }
public double Bias { get; set; }
public double BiasDelta { get; set; }
public double Gradient { get; set; }
public double Value { get; set; }
public Neuron()
{
InputSynapses = new List<Synapse>();
OutputSynapses = new List<Synapse>();
Bias = NeuralNetwork.NextRandom();
}
public Neuron(List<Neuron> inputNeurons)
: this()
{
foreach (var inputNeuron in inputNeurons)
{
var synapse = new Synapse(inputNeuron, this);
inputNeuron.OutputSynapses.Add(synapse);
InputSynapses.Add(synapse);
}
}
public virtual double CalculateValue()
{
var d = InputSynapses.Sum(a => a.Weight * a.InputNeuron.Value);// + Bias;
return Value = IsHidden ? NeuralNetwork.SigmoidFunction(d) : NeuralNetwork.IdentityFunction(d);
}
public virtual double CalculateDerivative()
{
var d = Value;
return IsHidden ? NeuralNetwork.SigmoidDerivative(d) : NeuralNetwork.IdentityDerivative();
}
public double CalculateError(double target)
{
return target - Value;
}
public double CalculateGradient(double target)
{
return Gradient = CalculateError(target) * CalculateDerivative();
}
public double CalculateGradient()
{
return Gradient = OutputSynapses.Sum(a => a.OutputNeuron.Gradient * a.Weight) * CalculateDerivative();
}
public void UpdateWeights(double learnRate, double momentum)
{
var prevDelta = BiasDelta;
BiasDelta = learnRate * Gradient; // * 1
Bias += BiasDelta + momentum * prevDelta;
foreach (var s in InputSynapses)
{
prevDelta = s.WeightDelta;
s.WeightDelta = learnRate * Gradient * s.InputNeuron.Value;
s.Weight += s.WeightDelta; //;+ momentum * prevDelta;
}
}
}
public class Synapse
{
public Neuron InputNeuron { get; set; }
public Neuron OutputNeuron { get; set; }
public double Weight { get; set; }
public double WeightDelta { get; set; }
public Synapse(Neuron inputNeuron, Neuron outputNeuron)
{
InputNeuron = inputNeuron;
OutputNeuron = outputNeuron;
Weight = NeuralNetwork.NextRandom();
}
}
}
You really don't need to use a multi-layer network to solve problems of ax + b = y. A single layer perceptron would do the trick.
In fact, for a problem this simple you don't even need to break out the complexity of a real neural network. Check out this blog post:
http://dynamicnotions.blogspot.co.uk/2009/05/linear-regression-in-c.html
I did not analyze your code, it is far too long. But I can give you the answer for the basic question:
Yes, neural networks are well suited for such problems.
In fact, for a f : R -> R in the form of ax+b=y you should use one neuron with linear activation function. No three-layered structure is required, just one neuron is enough. If your code fails in such case, then you have an implementation error, as it is a simple linear regression task solved using gradient descent.
Can I add values to an instance of an object after I have used the constructor?
For instance I have this code. I have to make a list of objects which require a number n, and the time (which are recieved as arguments). The problem is that the time can be anywhere so I can't use it in a constructor.
public List<IAction> Dispatch(string[] arg)
{
int time;
int i = 0;
int j = 0;
List<IAction> t = new List<IAction>(10);
do
{
if (int.Parse(arg[j]) >= 0 && int.Parse(arg[j]) <= 20)
{
t.Add(new ComputeParam(int.Parse(arg[j])));
i++;
j++;
}
else
{
if (arg[i][0] == '/' && arg[i][1] == 't')
{
Options opt = new Options();
j++;
time=opt.Option(arg[i]); //sets the time 0,1000 or 2000
}
}
} while (i != arg.Length);
return t;
}
After finishing making the list can I do something like:
for(int i=0; i<=t.Count; i++)
{
*add time to t[i]*
}
How do I do this?
Thanks in advance!
Edit :
here is the ComputeParam class
public class ComputeParam : IAction
{
int n;
int time;
public ComputeParam()
{
}
public ComputeParam(int n)
{
this.n = n;
}
public void run()
{
Factorial Fact = new Factorial();
Fact.Progression += new Factorial.ProgressEventHandler(Progress);
Console.WriteLine(" ");
Console.Write("\n" + "Partial results : ");
Console.CursorLeft = 35;
Console.Write("Progress : ");
int Result = Fact.CalculateFactorial(n, time);
Console.WriteLine(" ");
Console.WriteLine("The factorial of " + n + " is : " + Result);
Console.WriteLine("Press Enter to continue...");
Console.CursorTop -= 2;
Console.CursorLeft = 0;
Console.ReadLine();
}
public void Progress(ProgressEventArgs e)
{
int result = e.getPartialResult;
int stack_value = e.getValue;
double max = System.Convert.ToDouble(n);
System.Convert.ToDouble(stack_value);
double percent = (stack_value / max) * 100;
Console.CursorLeft = 18;
Console.Write(result + " ");
Console.CursorLeft = 46;
Console.Write(System.Convert.ToInt32(percent) + "% ");
}
}
If the object has a public property, I don't see why not.
Edit: Looks like you need to add a public property to your class. Also note, given that there is a public constructor that takes 0 params, you should also add a property for n.
public class ComputeParam : IAction
{
int _n;
int _time;
public ComputeParam()
{
}
public ComputeParam(int n)
{
this._n = n;
}
public int Time
{
get { return this._time; }
set { this._time = value; }
}
public int N
{
get { return this._n; }
set { this._n = value; }
}
for(int i = 0; i < t.Count; i++)
{
((ComputeParam)t[i]).Time = 6;
}
In my application, i need to show made calls to the user. The user can arrange some filters, according to what they want to see. The problem is that i find it quite hard to filter the calls without losing performance. This is what i am using now :
private void ProcessFilterChoice()
{
_filteredCalls = ServiceConnector.ServiceConnector.SingletonServiceConnector.Proxy.GetAllCalls().ToList();
if (cboOutgoingIncoming.SelectedIndex > -1)
GetFilterPartOutgoingIncoming();
if (cboInternExtern.SelectedIndex > -1)
GetFilterPartInternExtern();
if (cboDateFilter.SelectedIndex > -1)
GetFilteredCallsByDate();
wbPdf.Source = null;
btnPrint.Content = "Pdf preview";
}
private void GetFilterPartOutgoingIncoming()
{
if (cboOutgoingIncoming.SelectedItem.ToString().Equals("Outgoing"))
for (int i = _filteredCalls.Count - 1; i > -1; i--)
{
if (_filteredCalls[i].Caller.E164.Length > 4 || _filteredCalls[i].Caller.E164.Equals("0"))
_filteredCalls.RemoveAt(i);
}
else if (cboOutgoingIncoming.SelectedItem.ToString().Equals("Incoming"))
for (int i = _filteredCalls.Count - 1; i > -1; i--)
{
if (_filteredCalls[i].Called.E164.Length > 4 || _filteredCalls[i].Called.E164.Equals("0"))
_filteredCalls.RemoveAt(i);
}
}
private void GetFilterPartInternExtern()
{
if (cboInternExtern.SelectedItem.ToString().Equals("Intern"))
for (int i = _filteredCalls.Count - 1; i > -1; i--)
{
if (_filteredCalls[i].Called.E164.Length > 4 || _filteredCalls[i].Caller.E164.Length > 4 || _filteredCalls[i].Caller.E164.Equals("0"))
_filteredCalls.RemoveAt(i);
}
else if (cboInternExtern.SelectedItem.ToString().Equals("Extern"))
for (int i = _filteredCalls.Count - 1; i > -1; i--)
{
if ((_filteredCalls[i].Called.E164.Length < 5 && _filteredCalls[i].Caller.E164.Length < 5) || _filteredCalls[i].Called.E164.Equals("0"))
_filteredCalls.RemoveAt(i);
}
}
private void GetFilteredCallsByDate()
{
DateTime period = DateTime.Now;
switch (cboDateFilter.SelectedItem.ToString())
{
case "Today":
period = DateTime.Today;
break;
case "Last week":
period = DateTime.Today.Subtract(new TimeSpan(7, 0, 0, 0));
break;
case "Last month":
period = DateTime.Today.AddMonths(-1);
break;
case "Last year":
period = DateTime.Today.AddYears(-1);
break;
default:
return;
}
for (int i = _filteredCalls.Count - 1; i > -1; i--)
{
if (_filteredCalls[i].Start < period)
_filteredCalls.RemoveAt(i);
}
}
_filtered calls is a list of "calls". Calls is a class that looks like this :
[DataContract]
public class Call
{
private User caller, called;
private DateTime start, end;
private string conferenceId;
private int id;
private bool isNew = false;
[DataMember]
public bool IsNew
{
get { return isNew; }
set { isNew = value; }
}
[DataMember]
public int Id
{
get { return id; }
set { id = value; }
}
[DataMember]
public string ConferenceId
{
get { return conferenceId; }
set { conferenceId = value; }
}
[DataMember]
public DateTime End
{
get { return end; }
set { end = value; }
}
[DataMember]
public DateTime Start
{
get { return start; }
set { start = value; }
}
[DataMember]
public User Called
{
get { return called; }
set { called = value; }
}
[DataMember]
public User Caller
{
get { return caller; }
set { caller = value; }
}
Can anyone direct me to a better solution or make some suggestions.
Try using a foreach loop instead of an explicit for loop with an iterator variable. If _filteredCalls is a List, then _filteredCalls[i] will take O(n) time. Using a foreach will use the built in iterator of the list and will likely get you a speed increase.
Edit: I see you are actually looping backward through _filteredCalls, and also modifying the list.
So something like this would be better:
_filteredCalls = _filteredCalls.Where(c => c.Caller.E164.Length > 4 || c.Caller.E164.Equals("0"))