I have a program which builds a very large tree from input data and traverses it, both by recursion. I have tested the program on smaller inputs (and thus smaller trees) and it functions as intended. However when the input data is much larger i run into 'Process is terminated due to StackOverflowException'. I assume this is due to the stack running out of space. Is there any way to prevent this or do I have to switch to building the tree via iteration instead? Or perhaps I am missing a case of infinite recursion somewhere?
Here is the code:
class Program
{
static int[] tileColors;
static Color[] colors;
static int totalTiles;
static void Main(string[] args)
{
Stopwatch s = new Stopwatch();
s.Start();
string[] data = File.ReadAllLines("colors.txt");
totalTiles = int.Parse(data[0].Split(' ')[0]);
int totalColors = int.Parse(data[0].Split(' ')[1]);
string[] colorsRaw = data[1].Split(' ');
tileColors = new int[totalTiles];
for (int i = 0; i < totalTiles; i++)
{
tileColors[i] = int.Parse(colorsRaw[i]) - 1;
}
colors = new Color[totalColors];
for (int i = 3; i < data.Length; i++)
{
string[] raw = data[i].Split(' ');
int[] pair = new int[] { int.Parse(raw[0]) - 1, int.Parse(raw[1]) - 1 };
if (colors[pair[0]] == null)
colors[pair[0]] = new Color(pair[1]);
else
colors[pair[0]].pairs.Add(pair[1]);
if (colors[pair[1]] == null)
colors[pair[1]] = new Color(pair[0]);
else
colors[pair[1]].pairs.Add(pair[0]);
}
Tree t = new Tree();
t.root = new Node(0);
PopulateTree(t.root);
long ans = t.CountMatchingLeaves(t.root, totalTiles - 1) % 1000000007;
Console.WriteLine(ans);
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
}
static void PopulateTree(Node root)
{
for (int i = root.tile + 1; i < totalTiles; i++)
{
if (colors[tileColors[i]] == null) continue;
if (colors[tileColors[i]].Compatible(tileColors[root.tile]))
{
var node = new Node(i);
root.children.Add(node);
PopulateTree(node);
}
}
}
}
class Color
{
public List<int> pairs = new List<int>();
public Color(int pair)
{
pairs.Add(pair);
}
public bool Compatible(int c)
{
return pairs.Contains(c);
}
}
class Node
{
public List<Node> children = new List<Node>();
public int tile;
public Node(int tile)
{
this.tile = tile;
}
}
class Tree
{
public Node root;
public List<Node> GetMatchingLeaves(Node root, int match)
{
if (root.children.Count == 0)
{
if (root.tile == match)
{
return new List<Node>() { root };
}
return new List<Node>();
}
List<Node> list = new List<Node>();
foreach(var c in root.children)
{
list.AddRange(GetMatchingLeaves(c, match));
}
return list;
}
public long CountMatchingLeaves(Node root, int match)
{
if (root.children.Count == 0)
{
if (root.tile == match)
{
return 1;
}
return 0;
}
long count = 0;
foreach (var c in root.children)
{
count += CountMatchingLeaves(c, match);
}
return count;
}
}
You can always rewrite recursion as iteration, usually by using a stack class rather than rely on your thread's stack. For your code it would look like this:
static void PopulateTree(Node start)
{
var nodes = new Stack<Node>();
nodes.Push(start);
while(nodes.Count != 0)
{
var root = nodes.Pop();
for (int i = root.tile + 1; i < totalTiles; i++)
{
if (colors[tileColors[i]] == null) continue;
if (colors[tileColors[i]].Compatible(tileColors[root.tile]))
{
var node = new Node(i);
root.children.Add(node);
nodes.Push(node);
}
}
}
}
The while loop checking for more items is the equivalent of your terminating condition in recursion.
I want to understand the A* algorithm. I wrote by examples, but often it gets into an infinite loop.
What is the problem?
Please forgive me for the English language.
Path Search Code:
public Node GetPath(Vector2 goal,Vector2 start) {
List<Node> OpenNodes = new List<Node>(); //список с не просмотренными узлами
List<Node> ClosedNodes = new List<Node>(); //список с не просмотренными узлами
OpenNodes.Add(new Node
{
pos = start,
parent = null,
DistStart = 0,
DistOnGoal = GetDistOnGoal(Vector2.zero, goal)
});
while (OpenNodes.Count > 0) {
var FirstNode = OpenNodes.OrderBy(node => node.FullDist).First();
ClosedNodes.Add(FirstNode);
OpenNodes.Remove(FirstNode);
if (FirstNode.pos == goal) {
Debug.Log("путь есть");
return FirstNode;
}
foreach (Node n in NighBours(FirstNode, goal)) {
var chanel = false;
foreach (Node d in ClosedNodes) {
if (n == d) {
chanel = true;
continue;
}
}
if (chanel)
{
chanel = false;
continue;
}
var opennod = OpenNodes.FirstOrDefault(node => node.pos == n.pos);
if (opennod == null)
{
OpenNodes.Add(n);
}
else {
if (opennod.DistStart >n.DistStart) {
opennod.DistStart = n.DistStart;
opennod.parent = FirstNode;
}
}
}
}
return null;
}
public float GetDistOnGoal(Vector2 n, Vector2 goal) {//дистанция до цели
return Mathf.Abs((goal - n).magnitude);
}
public List<Node> NighBours(Node n,Vector2 goal)//соседи
{
var Point = new Vector2[4];
var Nodes = new List<Node>();
Point[0] = new Vector2(n.pos.x - 1, n.pos.y);
Point[1] = new Vector2(n.pos.x + 1, n.pos.y);
Point[2] = new Vector2(n.pos.x, n.pos.y + 1);
Point[3] = new Vector2(n.pos.x, n.pos.y - 1);
for (var i = 0; i < Point.Length; i++)
{
if (Point[i].x > 1 && Point[i].x < map.GetLength(0) - 2 && Point[i].y > 1 && Point[i].y < map.GetLength(1) - 2)
{
if (map[(int)Point[i].x, (int)Point[i].y] == 0)
{
Nodes.Add(
new Node
{
pos = Point[i],
parent = n,
DistStart = n.DistStart + 1,
DistOnGoal = GetDistOnGoal(Point[i],goal),
});
}
}
}
return Nodes;
}
public class Node {
public Vector2 pos;
public Node parent;
public float DistStart;
public float DistOnGoal;
public float FullDist
{
get
{
return DistStart + DistOnGoal;
}
}
}
This is the node code.
The function never returned null, although an example of this implies.
Debug also can't because Unity hangs tight
Im using xamarin.forms.maps and successfully getting the polyline but I want to get some patterns on it as here and not able to achieve it.
Can anyone please help me in solving this issue and my code is as below :
formsMap.DrawPolyLine = () =>
{
if (nativeMaps == null)
{
nativeMaps = Control as MKMapView;
}
nativeMaps.OverlayRenderer = GetOverlayRenderer;
CLLocationCoordinate2D[] coords = new CLLocationCoordinate2D[IOSMapViewModel.DeviceTrackData.Count];
int index = 0;
foreach (var position in IOSMapViewModel.DeviceTrackData)
{
coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude);
index++;
}
routeOverlay = MKGeodesicPolyline.FromCoordinates(coords);
if (nativeMap.Overlays != null)
nativeMaps.RemoveOverlays(nativeMap.Overlays);
IMKOverlay overlay = routeOverlay;
nativeMaps.AddOverlay(routeOverlay, MKOverlayLevel.AboveLabels);
};
nativeMap.GetViewForAnnotation = GetViewForAnnotation;
nativeMap.CalloutAccessoryControlTapped += OnCalloutAccessoryControlTapped;
}
}
MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlayWrapper)
{
if (polylineRenderer == null && !Equals(overlayWrapper, null))
{
var overlay = Runtime.GetNSObject(overlayWrapper.Handle) as IMKOverlay;
Foundation.NSNumber[] dashValues = { 3, 6 };
polylineRenderer = new MKPolylineRenderer(overlay as MKGeodesicPolyline)
{
FillColor = UIColor.Orange,
StrokeColor = UIColor.Orange,
LineWidth = 3,
Alpha = 1f,
LineDashPattern = dashValues
};
//polylineRenderer.CreatePath();
}
return polylineRenderer;
}
I am trying to learn BOW object categorization. I have tried to implement the example given in the book "Practical OpenCV, Samarth Brahmbhatt" Chapter 8 (page 148)
When I save the SVM's to file on the training stage and read them on the categorization stage, the result is comletely different. (If the line
svm = notFromFile[category]; is removed, the results are wrong; if not, it is successful with the dataset provided by the book.)
When I try this code with some larger datasets, I sometimes get this exception: System.AccessViolationException' in Emgu.CV.World.dll for the line bowDescriptorExtractor.Compute(frame_g, kp, img); and the application closes. It cannot be handled.
I have tried many things but could not figure them out. Any suggestions why these are happening, and how to solve, is very appreciated.
I am using emgucv-windesktop 3.1.0.2504
My implementation:
internal class Categorizer3 : ICategorizer
{
public string Name
{
get
{
return "Categorizer3";
}
}
public bool Train()
{
try
{
initDir();
Feature2D descriptorExtractor;
Feature2D featureDetector;
List<Mat> templates;
BOWKMeansTrainer bowtrainer;
BOWImgDescriptorExtractor bowDescriptorExtractor;
init(out descriptorExtractor, out featureDetector, out templates, out bowtrainer, out bowDescriptorExtractor);
List<Tuple<string, Mat>> train_set;
List<string> category_names;
make_train_set(out train_set, out category_names);
Mat vocab;
build_vocab(descriptorExtractor, featureDetector, templates, bowtrainer, out vocab);
bowDescriptorExtractor.SetVocabulary(vocab);
Dictionary<string, Mat> positive_data;
Dictionary<string, Mat> negative_data;
make_pos_neg(train_set, bowDescriptorExtractor, featureDetector, category_names, out positive_data, out negative_data);
this.train_classifiers(category_names, positive_data, negative_data);
return true;
}
catch (Exception)
{
return false;
}
}
public event TrainedEventHandler Trained;
protected void OnTrained(string fn)
{
if (this.Trained != null)
this.Trained(fn);
}
public Categorizer3()
{
}
private Feature2D create_FeatureDetector()
{
return new SURF(500);
//return new KAZE();
//return new SIFT();
//return new Freak();
}
private BOWImgDescriptorExtractor create_bowDescriptorExtractor(Feature2D descriptorExtractor)
{
LinearIndexParams ip = new LinearIndexParams();
SearchParams sp = new SearchParams();
var descriptorMatcher = new FlannBasedMatcher(ip, sp);
return new BOWImgDescriptorExtractor(descriptorExtractor, descriptorMatcher);
}
private void init(out Feature2D descriptorExtractor, out Feature2D featureDetector, out List<Mat> templates, out BOWKMeansTrainer bowtrainer, out BOWImgDescriptorExtractor bowDescriptorExtractor)
{
int clusters = 1000;
featureDetector = create_FeatureDetector();
MCvTermCriteria term = new MCvTermCriteria(10000, 0.0001d);
term.Type = TermCritType.Iter | TermCritType.Eps;
bowtrainer = new BOWKMeansTrainer(clusters, term, 5, Emgu.CV.CvEnum.KMeansInitType.PPCenters);//****
BFMatcher matcher = new BFMatcher(DistanceType.L1);//****
descriptorExtractor = featureDetector;//******
bowDescriptorExtractor = create_bowDescriptorExtractor(descriptorExtractor);
templates = new List<Mat>();
string TEMPLATE_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\templates";
//string TEMPLATE_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\train_images";
foreach (var filename in Directory.GetFiles(TEMPLATE_FOLDER, "*", SearchOption.AllDirectories))
{
templates.Add(GetMat(filename, true));
this.OnTrained(filename);
}
}
void make_train_set(out List<Tuple<string, Mat>> train_set, out List<string> category_names)
{
string TRAIN_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\train_images";
category_names = new List<string>();
train_set = new List<Tuple<string, Mat>>();
foreach (var dir in Directory.GetDirectories(TRAIN_FOLDER))
{
// Get category name from name of the folder
string category = new DirectoryInfo(dir).Name;
category_names.Add(category);
foreach (var filename in Directory.GetFiles(dir))
{
train_set.Add(new Tuple<string, Mat>(category, GetMat(filename, true)));
this.OnTrained(filename);
}
}
}
void build_vocab(Feature2D descriptorExtractor, Feature2D featureDetector, List<Mat> templates, BOWKMeansTrainer bowtrainer, out Mat vocab)
{
Mat vocab_descriptors = new Mat();
foreach (Mat templ in templates)
{
Mat desc = new Mat();
VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(templ));
descriptorExtractor.Compute(templ, kp, desc);
vocab_descriptors.PushBack(desc);
}
bowtrainer.Add(vocab_descriptors);
vocab = new Mat();
bowtrainer.Cluster(vocab);
string fn = getVocabularyFileName();
using (FileStorage fs = new FileStorage(fn, FileStorage.Mode.Write))
{
fs.Write(vocab, "vocab");
fs.ReleaseAndGetString();
}
}
void make_pos_neg(List<Tuple<string, Mat>> train_set, BOWImgDescriptorExtractor bowDescriptorExtractor, Feature2D featureDetector, List<string> category_names,
out Dictionary<string, Mat> positive_data, out Dictionary<string, Mat> negative_data)
{
positive_data = new Dictionary<string, Mat>();
negative_data = new Dictionary<string, Mat>();
foreach (var tu in train_set)
{
string category = tu.Item1;
Mat im = tu.Item2;
Mat feat = new Mat();
VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(im));
bowDescriptorExtractor.Compute(im, kp, feat);
for (int cat_index = 0; cat_index < category_names.Count; cat_index++)
{
string check_category = category_names[cat_index];
if (check_category.CompareTo(category) == 0)
{
if (!positive_data.ContainsKey(check_category))
positive_data[check_category] = new Mat();
positive_data[check_category].PushBack(feat);
}
else
{
if (!negative_data.ContainsKey(check_category))
negative_data[check_category] = new Mat();
negative_data[check_category].PushBack(feat);
}
}
}
}
void train_classifiers(List<string> category_names, Dictionary<string, Mat> positive_data, Dictionary<string, Mat> negative_data)
{
for (int i = 0; i < category_names.Count; i++)
{
string category = category_names[i];
// Postive training data has labels 1
Mat train_data = positive_data[category];
Mat train_labels = new Mat(train_data.Rows, 1, DepthType.Cv32S, 1);
{
for (int col = 0; col < train_labels.Cols; col++)
for (int row = 0; row < train_labels.Rows; row++)
train_labels.SetValue(row, col, (int)1);
train_labels.SetTo(new MCvScalar(1));
// Negative training data has labels 0
train_data.PushBack(negative_data[category]);
Mat m = new Mat(negative_data[category].Rows, 1, DepthType.Cv32S, 1);
{
for (int col = 0; col < m.Cols; col++)
for (int row = 0; row < m.Rows; row++)
m.SetValue(row, col, (int)0);
m.SetTo(new MCvScalar(0));
train_labels.PushBack(m);
}
SVM svm = new SVM();
svm.C = 312.5;
svm.Gamma = 0.50625000000000009;
svm.SetKernel(SVM.SvmKernelType.Rbf);
svm.Type = SVM.SvmType.CSvc;
svm.Train(train_data, Emgu.CV.ML.MlEnum.DataLayoutType.RowSample, train_labels);
var fn = getSVMFileName(category);
svm.SaveSVMToFile(fn);
notFromFile[category] = svm;
}
}
}
Dictionary<string, SVM> notFromFile = new Dictionary<string, SVM>();//****
private void initDir()
{
var dir = getSaveDir();
if (Directory.Exists(dir))
foreach (var fn in Directory.GetFiles(dir))
File.Delete(fn);
}
private string getSaveDir()
{
string dir = Path.Combine(Path.GetTempPath(), "Dece", "SVMS");
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
return dir;
}
private string getSVMFileName(string category)
{
return Path.Combine(getSaveDir(), category + ".svm");
}
private string getVocabularyFileName()
{
return Path.Combine(getSaveDir(), "vocabulary.voc");
}
//[HandleProcessCorruptedStateExceptions]
public IEnumerable<ImageInfo> Categorize(IEnumerable<string> imageFileNames)
{
var featureDetector = create_FeatureDetector();
var bowDescriptorExtractor = create_bowDescriptorExtractor(featureDetector);
Mat vocab = new Mat();
using (var fs = new FileStorage(getVocabularyFileName(), FileStorage.Mode.Read))
fs["vocab"].ReadMat(vocab);
bowDescriptorExtractor.SetVocabulary(vocab);
Dictionary<string, string> svms = new Dictionary<string, string>();
foreach (var xml in Directory.GetFiles(getSaveDir(), "*.svm"))
svms.Add(Path.GetFileNameWithoutExtension(xml), xml);
Dictionary<string, SVM> dic = new Dictionary<string, SVM>();
foreach (var fn in imageFileNames)
{
string scoreTxt = Environment.NewLine;
float score = float.MaxValue;
//float score = float.MinValue;
string cat = "";
try
{
using (Mat frame_g = GetMat(fn, false))
{
using (Mat img = new Mat())
{
VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(frame_g));
bowDescriptorExtractor.Compute(frame_g, kp, img);
foreach (var category in svms.Keys)
{
SVM svm = null;
if (!dic.ContainsKey(category))
{
string svmFn = svms[category];
svm = new SVM();
svm.LoadSVMFromFile(svmFn);
dic[category] = svm;
}
else
svm = dic[category];
svm = notFromFile[category];//*************
float classVal = svm.Predict(img, null);
float scoreVal = svm.Predict(img, null, 1);
//float signMul = (classVal < 0) == (scoreVal < 0) ? 1f : -1f;
//float score1 = signMul * scoreVal;
scoreTxt += string.Format("{0}-{1}: {2}{3}", category, classVal.ToString(), scoreVal.ToString("N3"), Environment.NewLine);
if (scoreVal < score)
{
score = scoreVal;
cat = category;
}
}
}
}
}
catch (Exception)
{
score = 0f;
cat = "hata";
}
if (string.IsNullOrEmpty(cat))
score = 0f;
yield return new ImageInfo(fn, cat, scoreTxt);
}
}
private static object matLocker = new object();
public Mat GetMat(string fn, bool train)
{
lock (matLocker)
{
var mat = new Mat(fn, ImreadModes.Color);
var mat2 = new Mat();
mat.ConvertTo(mat2, DepthType.Cv8U);
return mat2;
}
}
}
How can I compute the minimum bipartite vertex cover in C#? Is there a code snippet to do so?
EDIT: while the problem is NP-complete for general graphs, it is solvable in polynomial time for bipartite graphs. I know that it's somehow related to maximum matching in bipartite graphs (by Konig's theorem) but I can't understand the theorem correctly to be able to convert the result of maximum bipartite matching to vertex cover.
I could figure it out:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class VertexCover
{
static void Main(string[] args)
{
var v = new VertexCover();
v.ParseInput();
v.FindVertexCover();
v.PrintResults();
}
private void PrintResults()
{
Console.WriteLine(String.Join(" ", VertexCoverResult.Select(x => x.ToString()).ToArray()));
}
private void FindVertexCover()
{
FindBipartiteMatching();
var TreeSet = new HashSet<int>();
foreach (var v in LeftVertices)
if (Matching[v] < 0)
DepthFirstSearch(TreeSet, v, false);
VertexCoverResult = new HashSet<int>(LeftVertices.Except(TreeSet).Union(RightVertices.Intersect(TreeSet)));
}
private void DepthFirstSearch(HashSet<int> TreeSet, int v, bool left)
{
if (TreeSet.Contains(v))
return;
TreeSet.Add(v);
if (left) {
foreach (var u in Edges[v])
if (u != Matching[v])
DepthFirstSearch(TreeSet, u, true);
} else if (Matching[v] >= 0)
DepthFirstSearch(TreeSet, Matching[v], false);
}
private void FindBipartiteMatching()
{
Bicolorate();
Matching = Enumerable.Repeat(-1, VertexCount).ToArray();
var cnt = 0;
foreach (var i in LeftVertices) {
var seen = new bool[VertexCount];
if (BipartiteMatchingInternal(seen, i)) cnt++;
}
}
private bool BipartiteMatchingInternal(bool[] seen, int u)
{
foreach (var v in Edges[u]) {
if (seen[v]) continue;
seen[v] = true;
if (Matching[v] < 0 || BipartiteMatchingInternal(seen, Matching[v])) {
Matching[u] = v;
Matching[v] = u;
return true;
}
}
return false;
}
private void Bicolorate()
{
LeftVertices = new HashSet<int>();
RightVertices = new HashSet<int>();
var colors = new int[VertexCount];
for (int i = 0; i < VertexCount; ++i)
if (colors[i] == 0 && !BicolorateInternal(colors, i, 1))
throw new InvalidOperationException("Graph is NOT bipartite.");
}
private bool BicolorateInternal(int[] colors, int i, int color)
{
if (colors[i] == 0) {
if (color == 1) LeftVertices.Add(i);
else RightVertices.Add(i);
colors[i] = color;
} else if (colors[i] != color)
return false;
else
return true;
foreach (var j in Edges[i])
if (!BicolorateInternal(colors, j, 3 - color))
return false;
return true;
}
private int VertexCount;
private HashSet<int>[] Edges;
private HashSet<int> LeftVertices;
private HashSet<int> RightVertices;
private HashSet<int> VertexCoverResult;
private int[] Matching;
private void ReadIntegerPair(out int x, out int y)
{
var input = Console.ReadLine();
var splitted = input.Split(new char[] { ' ' }, 2);
x = int.Parse(splitted[0]);
y = int.Parse(splitted[1]);
}
private void ParseInput()
{
int EdgeCount;
ReadIntegerPair(out VertexCount, out EdgeCount);
Edges = new HashSet<int>[VertexCount];
for (int i = 0; i < Edges.Length; ++i)
Edges[i] = new HashSet<int>();
for (int i = 0; i < EdgeCount; i++) {
int x, y;
ReadIntegerPair(out x, out y);
Edges[x].Add(y);
Edges[y].Add(x);
}
}
}
As you can see, this code solves the problem in polynomial time.
Its probably best to just go ahead and pick a node at random. For each node, either it goes in the vertex cover, or all of its neighbors do (since you need to include that edge). The end-result of the whole thing will be a set of vertex covers, and you pick the smallest one. I"m not going to sit here and code it out, though, since if I remember correctly, its NP complete.
private void DepthFirstSearch(HashSet TreeSet, int v, bool left)
{
if (TreeSet.Contains(v))
return;
TreeSet.Add(v);
if (left) {
foreach (var u in Edges[v])
if (u != Matching[v])
DepthFirstSearch(TreeSet, u, true);
} else if (Matching[v] >= 0)
DepthFirstSearch(TreeSet, Matching[v], false);
}
when the if(left) will execute i am figuring that it's value is always will be false.