Google OR-Tools TSP returning several solution - c#

I've been recently working on finding more than just the optimal route using Google's OR-Tools. I have found an example in the repo, but this only solves for the optimal route, any idea how to generate more than just one solution for a set of points? I'm currently working with the DotNet version of the tool, any solution with any other language would be helpful!
public class tspParams : NodeEvaluator2
{
public static int[,] distanceMatrix =
{
{ 0, 20, 40, 10 },
{ 20, 0, 4, 55 },
{ 40, 4, 0, 2 },
{ 10, 55, 2, 0 }
};
public static int tsp_size
{
get { return distanceMatrix.GetUpperBound(0) + 1; }
}
public static int num_routes
{
get { return 1; }
}
public static int depot
{
get { return 0; }
}
public override long Run(int FromNode, int ToNode)
{
return distanceMatrix[FromNode, ToNode];
}
}
public class TSP
{
public static void PrintSolution(RoutingModel routing, Assignment solution)
{
Console.WriteLine("Distance of the route: {0}", solution.ObjectiveValue());
var index = routing.Start(0);
Console.WriteLine("Route for Vehicle 0:");
while (!routing.IsEnd(index))
{
Console.Write("{0} -> ", routing.IndexToNode(index));
var previousIndex = index;
index = solution.Value(routing.NextVar(index));
}
Console.WriteLine("{0}", routing.IndexToNode(index));
//Console.WriteLine("Calculated optimal route!");
}
public static void Solve()
{
// Create Routing Model
RoutingModel routing = new RoutingModel(
tspParams.tsp_size,
tspParams.num_routes,
tspParams.depot);
// Define weight of each edge
NodeEvaluator2 distanceEvaluator = new tspParams();
//protect callbacks from the GC
GC.KeepAlive(distanceEvaluator);
routing.SetArcCostEvaluatorOfAllVehicles(distanceEvaluator);
// Setting first solution heuristic (cheapest addition).
RoutingSearchParameters searchParameters = RoutingModel.DefaultSearchParameters();
searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc;
Assignment solution = routing.SolveWithParameters(searchParameters);
PrintSolution(routing, solution);
}
}

Use AllSolutionCollector from the underlying CP solver. python code:
solver = routing.solver()
collector = solver.AllSolutionCollector()
for location_idx in range(len(data['time_windows'])):
index = manager.NodeToIndex(location_idx)
time_var = time_dimension.CumulVar(index)
next_var = routing.NextVar(index)
collector.Add(time_var)
collector.Add(next_var)
for v in range(data['num_vehicles']):
index = routing.Start(v)
time_var = time_dimension.CumulVar(index)
next_var = routing.NextVar(index)
collector.Add(time_var)
collector.Add(next_var)
index = routing.End(v)
time_var = time_dimension.CumulVar(index)
collector.Add(time_var)
routing.AddSearchMonitor(collector)
assignment = routing.SolveFromAssignmentWithParameters(initial_solution, search_parameters)
if assignment:
logger.info("solution count: %d", collector.SolutionCount())
for index in range(collector.SolutionCount()):
logger.info("solution index: %d", index)
self.print_solution(data, manager, routing, collector.Solution(index))
logger.info('final solution:')
self.print_solution(data, manager, routing, assignment)
else:
raise OptimizationInternalException("no solution found")

Related

Finding how many times an instance happens in a list

I have a list and my goal is to determine how many times the values in that list goes above a certain value.
For instance if my list is:
List = {0, 0, 3, 3, 4, 0, 4, 4, 4}
Id like to know that there were two instances where my values in the list were greater than 2 and stayed above 2. So in this case there were 2 instances, since it dropped below 2 at one point and went above it again.
private void Report_GeneratorButton_Click(object sender, EventArgs e)
{
//Lists
var current = _CanDataGraph._DataPoints[CanDataGraph.CurveTag.Current].ToList();
var SOC = _CanDataGraph._DataPoints[CanDataGraph.CurveTag.Soc].ToList();
var highcell = _CanDataGraph._DataPoints[CanDataGraph.CurveTag.HighestCell].ToList();
var lowcell = _CanDataGraph._DataPoints[CanDataGraph.CurveTag.LowestCell].ToList();
//Seperates current list into charging, discharging, and idle
List<double> charging = current.FindAll(i => i > 2);
List<double> discharging = current.FindAll(i => i < -2);
List<double> idle = current.FindAll(i => i < 2 && i > -2);
//High cell
List<double> overcharged = highcell.FindAll(i => i > 3.65);
int ov = overcharged.Count;
if (ov > 1)
{
Console.WriteLine("This Battery has gone over Voltage!");
}
else
{
Console.WriteLine("This battery has never been over Voltage.");
}
//Low cell
List<double> overdischarged = lowcell.FindAll(i => i > 3.65);
int lv = overdischarged.Count;
if (lv > 1)
{
Console.WriteLine("This Battery has been overdischarged!");
}
else
{
Console.WriteLine("This battery has never been overdischarged.");
}
//Each value is 1 second
int chargetime = charging.Count;
int dischargetime = discharging.Count;
int idletime = idle.Count;
Console.WriteLine("Charge time: " + chargetime + "s" + "\n" + "Discharge time: " + dischargetime + "s" + "\n" + "Idle time: " + idletime);
}
My current code is this and outputs:
This battery has never been over Voltage.
This battery has never been overdischarged.
Charge time: 271s
Discharge time: 0s
Idle time: 68
There are a great many ways to solve this problem; my suggestion is that you break it down into a number of smaller problems and then write a simple method that solves each problem.
Here's a simpler problem: given a sequence of T, give me back a sequence of T with "doubled" items removed:
public static IEnumerable<T> RemoveDoubles<T>(
this IEnumerable<T> items)
{
T previous = default(T);
bool first = true;
foreach(T item in items)
{
if (first || !item.Equals(previous)) yield return item;
previous = item;
first = false;
}
}
Great. How is this helpful? Because the solution to your problem is now:
int count = myList.Select(x => x > 2).RemoveDoubles().Count(x => x);
Follow along.
If you have myList as {0, 0, 3, 3, 4, 0, 4, 4, 4} then the result of the Select is {false, false, true, true, true, false, true, true, true}.
The result of the RemoveDoubles is {false, true, false, true}.
The result of the Count is 2, which is the desired result.
Try to use off-the-shelf parts when you can. If you cannot, try to solve a simple, general problem that gets you what you need; now you have a tool you can use for other tasks that require you to remove duplicates in a sequence.
This solution should achieve the desired result.
List<int> lsNums = new List<int>() {0, 0, 3, 3, 4, 0, 4, 4, 4} ;
public void MainFoo(){
int iChange = GetCritcalChangeNum(lsNums, 2);
Console.WriteLine("Critical change = %d", iChange);
}
public int GetCritcalChangeNum(List<int> lisNum, int iCriticalThreshold) {
int iCriticalChange = 0;
int iPrev = 0;
lisNum.ForEach( (int ele) => {
if(iPrev <= iCriticalThreshold && ele > iCriticalThreshold){
iCriticalChange++;
}
iPrev = ele;
});
return iCriticalChange;
}
You can create an extension method as shown below.
public static class ListExtensions
{
public static int InstanceCount(this List<double> list, Predicate<double> predicate)
{
int instanceCount = 0;
bool instanceOccurring = false;
foreach (var item in list)
{
if (predicate(item))
{
if (!instanceOccurring)
{
instanceCount++;
instanceOccurring = true;
}
}
else
{
instanceOccurring = false;
}
}
return instanceCount;
}
}
And use your newly created method like this
current.InstanceCount(p => p > 2)
public static int CountOverLimit(IEnumerable<double> items, double limit)
{
int overLimitCount = 0;
bool isOverLimit = false;
foreach (double item in items)
{
if (item > limit)
{
if (!isOverLimit)
{
overLimitCount++;
isOverLimit = true;
}
}
else if (isOverLimit)
{
isOverLimit = false;
}
}
return overLimitCount;
}
Here's a fairly concise and readable solution. Hopefully this helps. If the limit is variable, just put it in a function and take the list and the limit as parameters.
int [] array = new int [9]{0, 0, 3, 1, 4, 0, 4, 4, 4};
List<int> values = array.ToList();
int overCount = 0;
bool currentlyOver2 = false;
for (int i = 0; i < values.Count; i++)
{
if (values[i] > 2)
{
if (!currentlyOver2)
overCount++;
currentlyOver2 = true;
}
else
currentlyOver2 = false;
}
Another way to do this using System.Linq is to walk through the list, selecting both the item itself and it's index, and return true for each item where the item is greater than value and the previous item is less than or equal to value, and then select the number of true results. Of course there's a special case for index 0 where we don't check the previous item:
public static int GetSpikeCount(List<int> items, int threshold)
{
return items?
.Select((item, index) =>
index == 0
? item > threshold
: item > threshold && items[index - 1] <= threshold)
.Count(x => x == true) // '== true' is here for readability, but it's not necessary
?? 0; // return '0' if 'items' is null
}
Sample usage:
private static void Main()
{
var myList = new List<int> {0, 0, 3, 3, 4, 0, 4, 4, 4};
var count = GetSpikeCount(myList, 2);
// count == 2
}

How to use recursion with ALEA Library in C#

I am trying to convert a recursive algorithm from CPU to GPU using ALEA Library. I get the following errors if I build the code :
"Fody/Alea.CUDA: AOTCompileServer exited unexpectly with exit code -1073741571"
public class GPUModule : ILGPUModule
{
public GPUModule (GPUModuleTarget target) : base(target)
{
}
[Kernel] //Same Error whether RecursionTest is another Kernel or not.
public void RecursionTest(deviceptr<int> a)
{
...
RecursionTest(a);
}
[Kernel]
public MyKernel(deviceptr<int> a, ...)
{
...
var a = __shared__.Array<int>(10);
RecursionTest(Intrinsic.__array_to_ptr<int>(a)); //Error here
}
...
}
I will appreciate if you provide any documentation or link for recursion examples in C# using ALEA Library.
Thanks in advance
You are using Alea GPU 2.x, the newest version is Alea GPU 3.x. (see www.aleagpu.com). With 3.0, I made a test and it works:
using Alea;
using Alea.CSharp;
using NUnit.Framework;
public static void RecursionTestFunc(deviceptr<int> a)
{
if (a[0] == 0)
{
a[0] = -1;
}
else
{
a[0] -= 1;
RecursionTestFunc(a);
}
}
public static void RecursionTestKernel(int[] a)
{
var tid = threadIdx.x;
var ptr = DeviceFunction.AddressOfArray(a);
ptr += tid;
RecursionTestFunc(ptr);
}
[Test]
public static void RecursionTest()
{
var gpu = Gpu.Default;
var host = new[] {1, 2, 3, 4, 5};
var length = host.Length;
var dev = gpu.Allocate(host);
gpu.Launch(RecursionTestKernel, new LaunchParam(1, length), dev);
var actual = Gpu.CopyToHost(dev);
var expected = new[] {-1, -1, -1, -1, -1};
Assert.AreEqual(expected, actual);
Gpu.Free(dev);
}

Having trouble with my code on searching for an element of an array in C#

I've been struggling with this bit of code for a while, I can't seem to find out where I'm going wrong. Basically I want to search through an Array using an Integer and if it matches an element inside that array, it returns a bool variant as true. It's quite self explanatory but can't for the life of me figure it out! Any ideas?
Here is the code;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ArrayProject
{
class ArrayProgram
{
public bool ElementAt(int[] intArray, int valueToBeFound)
{
bool intAt = false;
int numberTofind;
Console.WriteLine("Please enter the number you wish to search for within the array: ");
numberTofind = Convert.ToInt32(Console.ReadLine());
foreach (int x in intArray)
{
if (x == numberTofind)
{
intAt = true;
}
else
{
intAt = false;
}
}
if (intAt == true)
{
Console.WriteLine("{0} is in the array!", numberTofind);
}
else
{
Console.WriteLine("{0} is not in the array.", numberTofind);
}
return intAt;
}
public void RunProgram()
{
int[] intArray = { 20, 30, 40, 50, 60, 50, 40, 30, 20, 10 };
int numberTofind = 0;
ElementAt(intArray, numberTofind);
} // end RunProgram()
static void Main(string[] args)
{
ArrayProgram myArrayProgram = new ArrayProgram();
myArrayProgram.RunProgram();
Console.WriteLine("\n\n===============================");
Console.WriteLine("ArrayProgram: Press any key to finish");
Console.ReadKey();
}
}
}
int[] intArray = { 20, 30, 40, 50, 60, 50, 40, 30, 20, 10 };
int numberToFind = 0;
//variant 1 (using System.Linq):
bool bInside1 = intArray.Contains(numberToFind);
//variant2
bool bInside2 = Array.IndexOf(intArray, numberToFind) >= 0;
And if you want to write your own function:
bool IsInside(int[] arrToSearch, int nToSearch)
{
foreach (int n in arrToSearch)
{
if (n == nToSearch)
return true;
}
return false; //not found
}
The problem is that your loop continues checking elements and updating intAt even if it finds the element you're looking for.
If the array was {1, 2, 3, 4} and your code was searching for 1, it would first check index 0. This is a match, so intAt becomes true. Next it will try index 1. This one isn't a match, so it sets intAt to be false. Then it will try indices 2, 3, etc. never finding the match.
You could do this pretty easy with Linq.
using System.Linq;
public static string test(int[] numberArray, int find)
{
bool s = false;
numberArray.ToList().ForEach(x => { if (x == find) s = true; });
return s ? "It contains it." : "Can't find it.";
}
However there is a method for this. You can use .Contains with an array as a person said above me.
If you want to keep your implementation, try this:
class ArrayProgram
{
public bool ElementAt(int[] intArray, int valueToBeFound)
{
foreach (int x in intArray)
if (x == valueToBeFound) // if you found your value in the array
return true; // you return true
return false; // otherwise, by this point the foreach has looped through all the elements and hasn't once entered in the above if (so it hasn't found your value) = you return false
}
public void RunProgram()
{
int[] intArray = { 20, 30, 40, 50, 60, 50, 40, 30, 20, 10,99 };
int numberTofind;
// I noticed that you're not using the numberTofind value either, so:
Console.Write("Please enter the number you wish to search for within the array: ");
numberTofind = Convert.ToInt32(Console.ReadLine());
// and since you made a function that returns true if your value has been found, you might as well use it like this
if(ElementAt(intArray, numberTofind)) // if the function returns true
Console.WriteLine("{0} is in the array!", numberTofind);
else
Console.WriteLine("{0} is not in the array.", numberTofind);
} // end RunProgram()
static void Main(string[] args)
{
ArrayProgram myArrayProgram = new ArrayProgram();
myArrayProgram.RunProgram();
Console.WriteLine("\n\n===============================");
Console.WriteLine("ArrayProgram: Press any key to finish");
Console.ReadKey();
}
}

NeuronDotNet: why does my function return different outputs to the in-built one?

I am using NeuronDotNet for neural networks in C#. In order to test the network (as well as train it), I wrote my own function to get the sum squared error. However, when I tested this function by running it on the training data and comparing it to the MeanSquaredError of the Backpropagation network, the results were different.
I discovered the reason for the different error is that the network is returning different outputs when I run to when its run in the learning phase. I run it for each TrainingSample using:
double[] output = xorNetwork.Run(sample.InputVector);
In the learning phase its using:
xorNetwork.Learn(trainingSet, cycles);
...with a delegate to trap the end sample event:
xorNetwork.EndSampleEvent +=
delegate(object network, TrainingSampleEventArgs args)
{
double[] test = xorNetwork.OutputLayer.GetOutput();
debug.addSampleOutput(test);
};
I tried doing this using the XOR problem, to keep it simple, and the outputs are still different. For example, at the end of the first epoch, the outputs from the EndSampleEvent delegate vs those from my function are:
Input: 01, Expected: 1, my_function: 0.703332, EndSampleEvent 0.734385
Input: 00, Expected: 0, my_function: 0.632568, EndSampleEvent 0.649198
Input: 10, Expected: 1, my_function: 0.650141, EndSampleEvent 0.710484
Input: 11, Expected: 0, my_function: 0.715175, EndSampleEvent 0.647102
Error: my_function: 0.280508, EndSampleEvent 0.291236
Its not something as simple as it being captured at a different phase in the epoch, the outputs are not identical to those in the next/previous epoch.
I've tried debugging, but I am not an expert in Visual Studio and I'm struggling a bit with this. My project references the NeuronDotNet DLL. When I put breakpoints into my code, it won't step into the code from the DLL. I've looked elsewhere for advice on this and tried several solutions and got nowhere.
I don't think its due to the 'observer effect', i.e. the Run method in my function causing the network to change. I have examined the code (in the project that makes the DLL) and I don't think Run changes any of the weights. The errors from my function tend to be lower than those from the EndSampleEvent by a factor which exceeds the decrease in error from a typical epoch, i.e. its as if the network is getting ahead of itself (in terms of training) temporarily during my code.
Neural networks are stochastic in the sense that they adjust their functions during training. However, the output should be deterministic. Why is it that the two sets of outputs are different?
EDIT: Here is the code I am using.
/***********************************************************************************************
COPYRIGHT 2008 Vijeth D
This file is part of NeuronDotNet XOR Sample.
(Project Website : http://neurondotnet.freehostia.com)
NeuronDotNet is a free software. You can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.
NeuronDotNet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with NeuronDotNet.
If not, see <http://www.gnu.org/licenses/>.
***********************************************************************************************/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using NeuronDotNet.Core;
using NeuronDotNet.Core.Backpropagation;
using ZedGraph;
namespace NeuronDotNet.Samples.XorSample
{
public partial class MainForm : Form
{
private BackpropagationNetwork xorNetwork;
private double[] errorList;
private int cycles = 5000;
private int neuronCount = 3;
private double learningRate = 0.25d;
public MainForm()
{
InitializeComponent();
}
private void Train(object sender, EventArgs e)
{
EnableControls(false);
if (!int.TryParse(txtCycles.Text.Trim(), out cycles)) { cycles = 5000; }
if (!double.TryParse(txtLearningRate.Text.Trim(), out learningRate)) { learningRate = 0.25d; }
if (!int.TryParse(txtNeuronCount.Text.Trim(), out neuronCount)) { neuronCount = 3; }
if (cycles < 1) { cycles = 1; }
if (learningRate < 0.01) { learningRate = 0.01; }
if (neuronCount < 1) { neuronCount = 1; }
txtNeuronCount.Text = neuronCount.ToString();
txtCycles.Text = cycles.ToString();
txtLearningRate.Text = learningRate.ToString();
errorList = new double[cycles];
InitGraph();
LinearLayer inputLayer = new LinearLayer(2);
SigmoidLayer hiddenLayer = new SigmoidLayer(neuronCount);
SigmoidLayer outputLayer = new SigmoidLayer(1);
new BackpropagationConnector(inputLayer, hiddenLayer);
new BackpropagationConnector(hiddenLayer, outputLayer);
xorNetwork = new BackpropagationNetwork(inputLayer, outputLayer);
xorNetwork.SetLearningRate(learningRate);
TrainingSet trainingSet = new TrainingSet(2, 1);
trainingSet.Add(new TrainingSample(new double[2] { 0d, 0d }, new double[1] { 0d }));
trainingSet.Add(new TrainingSample(new double[2] { 0d, 1d }, new double[1] { 1d }));
trainingSet.Add(new TrainingSample(new double[2] { 1d, 0d }, new double[1] { 1d }));
trainingSet.Add(new TrainingSample(new double[2] { 1d, 1d }, new double[1] { 0d }));
Console.WriteLine("mse_begin,mse_end,output,outputs,myerror");
double max = 0d;
Console.WriteLine(NNDebug.Header);
List < NNDebug > debugList = new List<NNDebug>();
NNDebug debug = null;
xorNetwork.BeginEpochEvent +=
delegate(object network, TrainingEpochEventArgs args)
{
debug = new NNDebug(trainingSet);
};
xorNetwork.EndSampleEvent +=
delegate(object network, TrainingSampleEventArgs args)
{
double[] test = xorNetwork.OutputLayer.GetOutput();
debug.addSampleOutput(args.TrainingSample, test);
};
xorNetwork.EndEpochEvent +=
delegate(object network, TrainingEpochEventArgs args)
{
errorList[args.TrainingIteration] = xorNetwork.MeanSquaredError;
debug.setMSE(xorNetwork.MeanSquaredError);
double[] test = xorNetwork.OutputLayer.GetOutput();
GetError(trainingSet, debug);
max = Math.Max(max, xorNetwork.MeanSquaredError);
progressBar.Value = (int)(args.TrainingIteration * 100d / cycles);
//Console.WriteLine(debug);
debugList.Add(debug);
};
xorNetwork.Learn(trainingSet, cycles);
double[] indices = new double[cycles];
for (int i = 0; i < cycles; i++) { indices[i] = i; }
lblTrainErrorVal.Text = xorNetwork.MeanSquaredError.ToString("0.000000");
LineItem errorCurve = new LineItem("Error Dynamics", indices, errorList, Color.Tomato, SymbolType.None, 1.5f);
errorGraph.GraphPane.YAxis.Scale.Max = max;
errorGraph.GraphPane.CurveList.Add(errorCurve);
errorGraph.Invalidate();
writeOut(debugList);
EnableControls(true);
}
private const String pathFileName = "C:\\Temp\\NDN_Debug_Output.txt";
private void writeOut(IEnumerable<NNDebug> data)
{
using (StreamWriter streamWriter = new StreamWriter(pathFileName))
{
streamWriter.WriteLine(NNDebug.Header);
//write results to a file for each load combination
foreach (NNDebug debug in data)
{
streamWriter.WriteLine(debug);
}
}
}
private void GetError(TrainingSet trainingSet, NNDebug debug)
{
double total = 0;
foreach (TrainingSample sample in trainingSet.TrainingSamples)
{
double[] output = xorNetwork.Run(sample.InputVector);
double[] expected = sample.OutputVector;
debug.addOutput(sample, output);
int len = output.Length;
for (int i = 0; i < len; i++)
{
double error = output[i] - expected[i];
total += (error * error);
}
}
total = total / trainingSet.TrainingSampleCount;
debug.setMyError(total);
}
private class NNDebug
{
public const String Header = "output(00->0),output(01->1),output(10->1),output(11->0),mse,my_output(00->0),my_output(01->1),my_output(10->1),my_output(11->0),my_error";
public double MyErrorAtEndOfEpoch;
public double MeanSquaredError;
public double[][] OutputAtEndOfEpoch;
public double[][] SampleOutput;
private readonly List<TrainingSample> samples;
public NNDebug(TrainingSet trainingSet)
{
samples =new List<TrainingSample>(trainingSet.TrainingSamples);
SampleOutput = new double[samples.Count][];
OutputAtEndOfEpoch = new double[samples.Count][];
}
public void addSampleOutput(TrainingSample mySample, double[] output)
{
int index = samples.IndexOf(mySample);
SampleOutput[index] = output;
}
public void addOutput(TrainingSample mySample, double[] output)
{
int index = samples.IndexOf(mySample);
OutputAtEndOfEpoch[index] = output;
}
public void setMyError(double error)
{
MyErrorAtEndOfEpoch = error;
}
public void setMSE(double mse)
{
this.MeanSquaredError = mse;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (double[] arr in SampleOutput)
{
writeOut(arr, sb);
sb.Append(',');
}
sb.Append(Math.Round(MeanSquaredError,6));
sb.Append(',');
foreach (double[] arr in OutputAtEndOfEpoch)
{
writeOut(arr, sb);
sb.Append(',');
}
sb.Append(Math.Round(MyErrorAtEndOfEpoch,6));
return sb.ToString();
}
}
private static void writeOut(double[] arr, StringBuilder sb)
{
bool first = true;
foreach (double d in arr)
{
if (first)
{
first = false;
}
else
{
sb.Append(',');
}
sb.Append(Math.Round(d, 6));
}
}
private void EnableControls(bool enabled)
{
btnTrain.Enabled = enabled;
txtCycles.Enabled = enabled;
txtNeuronCount.Enabled = enabled;
txtLearningRate.Enabled = enabled;
progressBar.Value = 0;
btnTest.Enabled = enabled;
txtTestInput.Enabled = enabled;
}
private void LoadForm(object sender, EventArgs e)
{
InitGraph();
txtCycles.Text = cycles.ToString();
txtLearningRate.Text = learningRate.ToString();
txtNeuronCount.Text = neuronCount.ToString();
}
private void InitGraph()
{
GraphPane pane = errorGraph.GraphPane;
pane.Chart.Fill = new Fill(Color.AntiqueWhite, Color.Honeydew, -45F);
pane.Title.Text = "Back Propagation Training - Error Graph";
pane.XAxis.Title.Text = "Training Iteration";
pane.YAxis.Title.Text = "Sum Squared Error";
pane.XAxis.MajorGrid.IsVisible = true;
pane.YAxis.MajorGrid.IsVisible = true;
pane.YAxis.MajorGrid.Color = Color.LightGray;
pane.XAxis.MajorGrid.Color = Color.LightGray;
pane.XAxis.Scale.Max = cycles;
pane.XAxis.Scale.Min = 0;
pane.YAxis.Scale.Min = 0;
pane.CurveList.Clear();
pane.Legend.IsVisible = false;
pane.AxisChange();
errorGraph.Invalidate();
}
private void Test(object sender, EventArgs e)
{
if (xorNetwork != null)
{
lblTestOutput.Text = xorNetwork.Run(
new double[] {double.Parse(txtTestInput.Text.Substring(2,4)),
double.Parse(txtTestInput.Text.Substring(8,4))})[0].ToString("0.000000");
}
}
}
}
Its not to do with normalisation, as the mapping between the two sets of outputs is not monotonic. For example, the output in {0,1} is higher in EndSampleEvent but in {1,1} it is lower. Normalisation would be a simple linear function.
Its not to do with jitter either, as I've tried turning that off, and the results are still different.
I have received an answer from my professor. The problem lies in the LearnSample method from the BackpropagationNetwork class which is called for each training sample every iteration.
The order of relevant events in this method is ….
1) Add to the MeanSquaredError which is calculated using only the output layer and desired output
2) Backpropagate errors to all earlier layer; this has no effect on the network.
3) Finally recalculate biases for each layer; this affects the network.
(3) is the last thing that occurs in the LearnSample method and happens after the calculation of the output error for each training instance. For the XOR example this means that the network is changed 4 times from the state is was in when the MSE calculation was made.
In theory, if you want to compare training and test errors then you should do a manual calculation (like my GetError function) and run it twice: once for each data set. However, in reality it might not be necessary to go to all this trouble as the values are not that different.

Cycle enumeration of a directed graph with multi edges [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
How can I find all cyles in a directed graph with multi edges?
Graph example 1:
Cycles:
1-2-6
1-2-3-4
1-2-3-4-5-6
1-2-6-5-3-4
3-4-5
5-6
Graph example 2 (multi-edge 4/5):
Cycles:
1-2-3
1-4
1-5
Notes:
I don't want to detect a cycle (boolean result), I want to list all cycles.
Any Strongly connected component algorithm is not sufficient for my problem (it would find only one component in both examples).
I'm using the QuickGraph implementation in C#, but I would be happy to see an algorithm in any language.
I had fun with this question, thanks! :P
I have a solution in C#. The algorithm to find the cycles is very short(~10 lines), but there is a lot of clutter around it(implementations of the classes Node and Edge for instance).
I've used the variable naming convention that the letter "e" represents an edge, the letter "a" the node where the edge start, and "b" the node it links to. With those conventions, this is the algorithm:
public static IEnumerable<Cycle> FindAllCycles()
{
HashSet<Node> alreadyVisited = new HashSet<Node>();
alreadyVisited.Add(Node.AllNodes[0]);
return FindAllCycles(alreadyVisited, Node.AllNodes[0]);
}
private static IEnumerable<Cycle> FindAllCycles(HashSet<Node> alreadyVisited, Node a)
{
for (int i = 0; i < a.Edges.Count; i++)
{
Edge e = a.Edges[i];
if (alreadyVisited.Contains(e.B))
{
yield return new Cycle(e);
}
else
{
HashSet<Node> newSet = i == a.Edges.Count - 1 ? alreadyVisited : new HashSet<Node>(alreadyVisited);
newSet.Add(e.B);
foreach (Cycle c in FindAllCycles(newSet, e.B))
{
c.Build(e);
yield return c;
}
}
}
}
It has an optimization to reuse some Hashsets, and that might be confusing. I've included the following code, which produces exactly the same results, but this implementation doesn't have optimizations, so you can figure out more easily how it works.
private static IEnumerable<Cycle> FindAllCyclesUnoptimized(HashSet<Node> alreadyVisited, Node a)
{
foreach (Edge e in a.Edges)
if (alreadyVisited.Contains(e.B))
yield return new Cycle(e);
else
{
HashSet<Node> newSet = new HashSet<Node>(alreadyVisited);
newSet.Add(e.B);//EDIT: thnx dhsto
foreach (Cycle c in FindAllCyclesUnoptimized(newSet, e.B))
{
c.Build(e);
yield return c;
}
}
}
This uses the following implementations of Node, Edge and Cycle. They're pretty straightforward, although I did put a lot of thought in making everything immutable and members as least accessible as possible.
public sealed class Node
{
public static readonly ReadOnlyCollection<Node> AllNodes;
internal static readonly List<Node> allNodes;
static Node()
{
allNodes = new List<Node>();
AllNodes = new ReadOnlyCollection<Node>(allNodes);
}
public static void SetReferences()
{//call this method after all nodes have been created
foreach (Edge e in Edge.AllEdges)
e.A.edge.Add(e);
}
//All edges linking *from* this node, not to it.
//The variablename "Edges" it quite unsatisfactory, but I couldn't come up with anything better.
public ReadOnlyCollection<Edge> Edges { get; private set; }
internal List<Edge> edge;
public int Index { get; private set; }
public Node(params int[] nodesIndicesConnectedTo)
{
this.edge = new List<Edge>(nodesIndicesConnectedTo.Length);
this.Edges = new ReadOnlyCollection<Edge>(edge);
this.Index = allNodes.Count;
allNodes.Add(this);
foreach (int nodeIndex in nodesIndicesConnectedTo)
new Edge(this, nodeIndex);
}
public override string ToString()
{
return this.Index.ToString();
}
}
public sealed class Edge
{
public static readonly ReadOnlyCollection<Edge> AllEdges;
static readonly List<Edge> allEdges;
static Edge()
{
allEdges = new List<Edge>();
AllEdges = new ReadOnlyCollection<Edge>(allEdges);
}
public int Index { get; private set; }
public Node A { get; private set; }
public Node B { get { return Node.allNodes[this.bIndex]; } }
private readonly int bIndex;
internal Edge(Node a, int bIndex)
{
this.Index = allEdges.Count;
this.A = a;
this.bIndex = bIndex;
allEdges.Add(this);
}
public override string ToString()
{
return this.Index.ToString();
}
}
public sealed class Cycle
{
public readonly ReadOnlyCollection<Edge> Members;
private List<Edge> members;
private bool IsComplete;
internal void Build(Edge member)
{
if (!IsComplete)
{
this.IsComplete = member.A == members[0].B;
this.members.Add(member);
}
}
internal Cycle(Edge firstMember)
{
this.members = new List<Edge>();
this.members.Add(firstMember);
this.Members = new ReadOnlyCollection<Edge>(this.members);
}
public override string ToString()
{
StringBuilder result = new StringBuilder();
foreach (var member in this.members)
{
result.Append(member.Index.ToString());
if (member != members[members.Count - 1])
result.Append(", ");
}
return result.ToString();
}
}
Then to illustrate how you might use this small API, I have implemented your two examples.
Basically it comes down to, create all the nodes by specifying to which nodes they link, then call SetReferences() to, well.... set some references. After that, calling the publicly accessible FindAllCycles() should return all cycles. I've excluded any code to reset the static members, but that is easily implemented. It should just clear all static lists.
static void Main(string[] args)
{
InitializeExampleGraph1();//or: InitializeExampleGraph2();
Node.SetReferences();
var allCycles = FindAllCycles().ToList();
}
static void InitializeExampleGraph1()
{
new Node(1, 2);//says that the first node(node a) links to b and c.
new Node(2);//says that the second node(node b) links to c.
new Node(0, 3);//says that the third node(node c) links to a and d.
new Node(0);//etc
}
static void InitializeExampleGraph2()
{
new Node(1);
new Node(0, 0, 2);
new Node(0);
}
I must note that the indices of the edges in these examples do NOT correspond to the indices in your images, but that is avoidable with a simple lookup.
The results: allCycles is for the first example:
{3, 2, 0}
{5, 4, 2, 0}
{3, 1}
{5, 4, 1}
allCycles is for the second example:
{1, 0}
{2, 0}
{4, 3, 0}
I hope you are satisfied with this solution and that you use it. I've barely commented on the code, so I know it might be hard to understand. In that case, please ask and I'll comment on it!
What about using Breadth-first search to find all paths between nodes A and B - lets call that function get_all_paths
To find all cycles you just need to:
cycles = []
for x in nodes:
cycles += get_all_paths(x,x)
get_all_paths(x,x) because a cycle is just a path that starts and ends in the same node.
Just an alternative solution - I hope it gives new ideas.
Edit
Another option is to compute all the posible paths and check every time that the first edge starts where the last edge finishes - a cycle.
Here you can see the Python code for it.
def paths_rec(path,edges):
if len(path) > 0 and path[0][0] == path[-1][1]:
print "cycle", path
return #cut processing when find a cycle
if len(edges) == 0:
return
if len(path) == 0:
#path is empty so all edges are candidates for next step
next_edges = edges
else:
#only edges starting where the last one finishes are candidates
next_edges = filter(lambda x: path[-1][1] == x[0], edges)
for edge in next_edges:
edges_recursive = list(edges)
edges_recursive.remove(edge)
#recursive call to keep on permuting possible path combinations
paths_rec(list(path) + [edge], edges_recursive)
def all_paths(edges):
paths_rec(list(),edges)
if __name__ == "__main__":
#edges are represented as (node,node)
# so (1,2) represents 1->2 the edge from node 1 to node 2.
edges = [(1,2),(2,3),(3,4),(4,2),(2,1)]
all_paths(edges)
JBSnorro gave an awesome answer, but still it might seem a little too hardcore. Starting from his solution, i present an easier to follow example, that does not need the definitions of Node, Edge and Cycle, and also works on adjacency matrices. My solution though, repeats some cycles if they are started from a different node.
int[,] Adjacency = new int[6, 6] {
{ 0,1,0,1,0,0 },
{ 0,0,0,1,0,0 },
{ 0,0,0,0,1,0 },
{ 0,1,1,0,0,0 },
{ 0,1,0,0,0,1 },
{ 0,0,1,1,0,0 }};
public void Start()
{
List<List<int>> Out = new List<List<int>>();
FindAllCycles(new List<int>(), Out, 0);
Console.WriteLine("");
foreach (List<int> CurrCycle in Out)
{
string CurrString = "";
foreach (int Currint in CurrCycle) CurrString += Currint + ", ";
Console.WriteLine(CurrString);
}
}
private void FindAllCycles(List<int> CurrentCycleVisited, List<List<int>> Cycles, int CurrNode)
{
CurrentCycleVisited.Add(CurrNode);
for (int OutEdgeCnt = 0; OutEdgeCnt < Adjacency.GetLength(0); OutEdgeCnt++)
{
if (Adjacency[CurrNode, OutEdgeCnt] == 1)//CurrNode Is connected with OutEdgeCnt
{
if (CurrentCycleVisited.Contains(OutEdgeCnt))
{
int StartIndex = CurrentCycleVisited.IndexOf(OutEdgeCnt);
int EndIndex = CurrentCycleVisited.IndexOf(CurrNode);
Cycles.Add(CurrentCycleVisited.GetRange(StartIndex, EndIndex - StartIndex + 1));
}
else
{
FindAllCycles(new List<int>(CurrentCycleVisited), Cycles, OutEdgeCnt);
}
}
}
}

Categories

Resources