/// <summary> /// Evaluates the similarity between two maps using the graph sampling evaluation of biagioni and eriksson. /// Parameters are hardcoded, based on the ones we used in the corresponding research. /// </summary> /// <param name="GT">The ground truth map</param> /// <param name="CT">the constructed map.</param> /// <param name="amount">the amount of neighbourhood evaluations we average over</param> /// <returns>A precision and recall value indicating the similarity between the maps.</returns> public (float, float) EvalMap(Map GT, Map CT, int amount) { float precision = 0; float recall = 0; for (int k = 0; k < amount; k++) { Coordinate originGT = rand.GetRandomPointOnRoad(rand.GetWeightedRandomRoad(GT)); Coordinate originCT = CT.GetClosestPoint(originGT.location); /* An extra step that is sometimes used in the literature when ground truth map is not pruned. * while (Vector3.Distance(originCT.location, originGT.location) > 50) * { * originGT = rand.GetRandomCoordinate(rand.GetWeightedRandomRoad(GT)); * originCT = CT.GetClosestPoint(originGT.location); * } */ List <Vector3> pointsGT = sampleNeighbourhood.GetNeighbourhood(GT, originGT, 500, 30); List <Vector3> pointsCT = sampleNeighbourhood.GetNeighbourhood(CT, originCT, 500, 30); MaxFlow flow = new MaxFlow(pointsGT.Count + pointsCT.Count + 2); for (int i = 0; i < pointsCT.Count; i++) { flow.AddEdge(0, i + 1, 1); } for (int i = 0; i < pointsCT.Count; i++) { Vector3 pointCT = pointsCT[i]; for (int j = 0; j < pointsGT.Count; j++) { Vector3 pointGT = pointsGT[j]; if (Vector3.Distance(pointCT, pointGT) < 20) { flow.AddEdge(i + 1, j + pointsCT.Count + 1, 1); } } } for (int i = 0; i < pointsGT.Count; i++) { flow.AddEdge(i + pointsCT.Count + 1, 1 + pointsCT.Count + pointsGT.Count, 1); } float matching = flow.FindMaximumFlow(0, 1 + pointsCT.Count + pointsGT.Count).Item1; precision += pointsCT.Count > 0 ? matching / pointsCT.Count : 0; recall += pointsGT.Count > 0 ? matching / pointsGT.Count : 0; } return(precision / amount, recall / amount); }
/// <summary> /// Visualizes and evaluates a single random neighbourhood. /// </summary> /// <param name="GT">Ground truth map</param> /// <param name="CT">contructed map</param> /// <param name="originDistanceCondition"></param> /// <param name="matchDistance"></param> /// <returns></returns> public (float, float) EvalNeighbourhood(Map GT, Map CT) { Coordinate originGT = rand.GetRandomPointOnRoad(rand.GetWeightedRandomRoad(GT)); Coordinate originCT = CT.GetClosestPoint(originGT.location); /* An extra step that is sometimes used in the literature when ground truth map is not pruned. * while (Vector3.Distance(originCT.location, originGT.location) > 50) * { * originGT = rand.GetRandomCoordinate(rand.GetWeightedRandomRoad(GT)); * originCT = CT.GetClosestPoint(originGT.location); * } */ List <Vector3> pointsGT = sampleNeighbourhood.GetNeighbourhood(GT, originGT, 150, 30); List <Vector3> pointsCT = sampleNeighbourhood.GetNeighbourhood(CT, originCT, 150, 30); MaxFlow flow = new MaxFlow(pointsGT.Count + pointsCT.Count + 2); for (int i = 0; i < pointsCT.Count; i++) { flow.AddEdge(0, i + 1, 1); // source edges } for (int i = 0; i < pointsCT.Count; i++) // edges between CT and GT { Vector3 pointCT = pointsCT[i]; for (int j = 0; j < pointsGT.Count; j++) { Vector3 pointGT = pointsGT[j]; if (Vector3.Distance(pointCT, pointGT) < 20) { flow.AddEdge(i + 1, j + pointsCT.Count + 1, 1); } } } for (int i = 0; i < pointsGT.Count; i++) { flow.AddEdge(i + pointsCT.Count + 1, 1 + pointsCT.Count + pointsGT.Count, 1); // sink edges } float matching; int[,] graph; (matching, graph) = flow.FindMaximumFlow(0, 1 + pointsCT.Count + pointsGT.Count); float prec = pointsCT.Count > 0 ? matching / pointsCT.Count : 0; float recall = pointsGT.Count > 0 ? matching / pointsGT.Count : 0; return(prec, recall); }
// このコードはテンプレートとして使えます。 // 0 <= v1 < n1, 0 <= v2 < n2 public static int[][] BipartiteMatching(int n1, int n2, int[][] des) { var sv = n1 + n2; var ev = sv + 1; var mf = new MaxFlow(ev + 1); for (int i = 0; i < n1; ++i) { mf.AddEdge(sv, i, 1); } for (int j = 0; j < n2; ++j) { mf.AddEdge(n1 + j, ev, 1); } foreach (var e in des) { mf.AddEdge(e[0], n1 + e[1], 1); } mf.Dinic(sv, ev); var map = mf.Map; var r = new List <int[]>(); foreach (var se in map[sv]) { if (se.Capacity > 0) { continue; } foreach (var e in map[se.To]) { if (e.Capacity == 0) { r.Add(new[] { se.To, e.To - n1 }); break; } } } return(r.ToArray()); }
static object Solve() { var(h, w, n) = Read3(); var ps = Array.ConvertAll(new bool[n], _ => Read4()); var sv = 400; var ev = sv + 1; var mf = new MaxFlow(ev + 1); for (int i = 0; i < h; i++) { mf.AddEdge(sv, i, 1); } for (int i = 0; i < w; i++) { mf.AddEdge(300 + i, ev, 1); } for (int i = 0; i < n; i++) { var(a, b, c, d) = ps[i]; var ri = 100 + i; var ci = 200 + i; mf.AddEdge(ri, ci, 1); for (int j = a - 1; j < c; j++) { mf.AddEdge(j, ri, 1); } for (int j = b - 1; j < d; j++) { mf.AddEdge(ci, 300 + j, 1); } } return(mf.Dinic(sv, ev)); }
static void Main() { var(n, m) = Read2(); var s = Array.ConvertAll(new bool[n], _ => Console.ReadLine().ToCharArray()); var sv = n * m; var ev = sv + 1; var mf = new MaxFlow(ev + 1); var vs0 = new List <int>(); var vs1 = new HashSet <int>(); // checker board for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (s[i][j] == '#') { continue; } var v = m * i + j; if ((i + j) % 2 == 0) { mf.AddEdge(sv, v, 1); vs0.Add(v); } else { mf.AddEdge(v, ev, 1); vs1.Add(v); } } } foreach (var v in vs0) { if (vs1.Contains(v - m)) { mf.AddEdge(v, v - m, 1); } if (vs1.Contains(v + m)) { mf.AddEdge(v, v + m, 1); } if (v % m != 0 && vs1.Contains(v - 1)) { mf.AddEdge(v, v - 1, 1); } if (v % m != m - 1 && vs1.Contains(v + 1)) { mf.AddEdge(v, v + 1, 1); } } var M = mf.Dinic(sv, ev); var map = mf.Map; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (s[i][j] == '#') { continue; } var v = m * i + j; if ((i + j) % 2 == 0) { var v2 = map[v].FirstOrDefault(e => e.Capacity == 0 && e.To != sv)?.To; if (v2 == null) { continue; } var(i2, j2) = ((int)v2 / m, (int)v2 % m); if (i == i2) { s[i][Math.Min(j, j2)] = '>'; s[i][Math.Max(j, j2)] = '<'; } else { s[Math.Min(i, i2)][j] = 'v'; s[Math.Max(i, i2)][j] = '^'; } } } } Console.WriteLine(M); foreach (var r in s) { Console.WriteLine(new string(r)); } }