Aetheria/Assets/Scripts/NIH/MSAGL/GraphmapsWithMesh/DijkstraAlgo.cs
hyperion51 01a956eef6 MSAGL Support
Added new tech tree layout implementation using Microsoft Automatic Graph Layouts
Added some functionality to the database editor tools
2020-04-14 00:42:04 +01:00

564 lines
21 KiB
C#

using System;
using System.Collections.Generic;
using Microsoft.Msagl.Core.DataStructures;
using Microsoft.Msagl.Core.Layout;
namespace Microsoft.Msagl.GraphmapsWithMesh
{
class DijkstraAlgo
{
public List<VertexNeighbor> Edgelist = new List<VertexNeighbor>();
public List<int> ShortestPath = new List<int>();
public double Distance;
public bool PathExists = true;
public Vertex getMin(List<Vertex> q)
{
double m = double.MaxValue;
Vertex temp_vertex = null;
foreach (Vertex w in q)
{
if (m > w.Dist)
{
m = w.Dist;
temp_vertex = w;
}
}
if (temp_vertex == null)
{
Console.WriteLine("Graph is disconnected");
return null;
}
foreach (Vertex w in q)
{
if (w.Id == temp_vertex.Id)
{
q.Remove(temp_vertex);
break;
}
}
return temp_vertex;
}
public void SelectShortestPath(Vertex[] vList, Edge[,] eList, int[] degList, int source, int target, int n)
{
List<Vertex> q = new List<Vertex>();
vList[source].Dist = 0;
q.Add(vList[source]);
for (int i = 1; i <= n; i++)
{
if (vList[i].Id != vList[source].Id)
{
vList[i].Dist = double.MaxValue;
q.Add(vList[i]);
}
vList[i].Parent = null;
vList[i].Visited = false;
}
Edgelist.Clear();
Distance = 0;
while (q.Count > 0)
{
Vertex u = getMin(q);
if (u.Visited) continue;
else u.Visited = true;
for (int neighb = 1; neighb <= degList[u.Id]; neighb++)
{
var neighbor = eList[u.Id, neighb].NodeId;
int discourage = 0;
if (eList[u.Id, neighb].Selected == 0) discourage = 1000;//continue;
if (vList[eList[u.Id, neighb].NodeId].Weight > 0 &&
eList[u.Id, neighb].NodeId != vList[target].Id) continue;
var temp = u.Dist + eList[u.Id, neighb].GetEDist(vList, u.Id, eList[u.Id, neighb].NodeId) + discourage;
if (temp < vList[neighbor].Dist)
{
vList[neighbor].Dist = temp;
vList[neighbor].Parent = u;
//Update(q, vList[neighbor]);
}
}
if (u.Id == vList[target].Id)
break;
}
Vertex route = vList[target];
//Console.WriteLine();
//Console.WriteLine("Source,Target" + source + " " + target);
while (route.Parent != null)
{
//Console.Write(route.Id+" ");
for (int neighb = 1; neighb <= degList[route.Id]; neighb++)
if (eList[route.Id, neighb].NodeId == route.Parent.Id)
{
Edgelist.Add(new VertexNeighbor(route.Id, neighb));
Distance += Math.Sqrt((route.XLoc - route.Parent.XLoc) * (route.XLoc - route.Parent.XLoc) + (route.YLoc - route.Parent.YLoc) * (route.YLoc - route.Parent.YLoc));
break;
}
for (int neighb = 1; neighb <= degList[route.Parent.Id]; neighb++)
if (eList[route.Parent.Id, neighb].NodeId == route.Id)
{
Edgelist.Add(new VertexNeighbor(route.Parent.Id, neighb));
break;
}
route = route.Parent;
}
//Console.Write(route.Id + " ");
if (route.Id != vList[source].Id) Console.WriteLine("path not found");
}
public List<int> MSAGLAstarShortestPath(Vertex[] vList, Edge[,] eList, int[] degList, int source, int target, int n)
{
var q = new BinaryHeapPriorityQueue(n);
vList[source].Dist = 0;
vList[source].Weight = vList[source].Dist +
MsaglUtilities.EucledianDistance(
vList[source].XLoc, vList[source].YLoc,
vList[target].XLoc, vList[target].YLoc);
q.Enqueue(source, vList[source].Weight);
for (int i = 0; i < n; i++)
{
if (vList[i].Id != source)
{
vList[i].Dist = double.MaxValue;
vList[i].Weight = double.MaxValue;
q.Enqueue(i, vList[i].Weight);
}
vList[i].Parent = null;
vList[i].Visited = false;
}
Edgelist.Clear();
ShortestPath.Clear();
Distance = 0;
while (q.Count > 0)
{
var deq = q.Dequeue();
Vertex u = vList[deq];
u.Visited = true;
if (u == null || u.Invalid) return new List<int>();
for (int neighb = 0; neighb < degList[u.Id]; neighb++)
{
var neighborId = eList[u.Id, neighb].NodeId;
int discourage = 0;
if (eList[u.Id, neighb].Selected == 1) discourage = 1000;//continue;
if (eList[u.Id, neighb].NodeId == source || eList[u.Id, neighb].NodeId == target) discourage = 0;
if (u.Id == source || u.Id == target) discourage = 0;
Vertex neighbor = vList[neighborId];
double edist = MsaglUtilities.EucledianDistance(u.XLoc, u.YLoc, neighbor.XLoc, neighbor.YLoc);
var tempDist = u.Dist + edist + discourage;
if (tempDist >= neighbor.Dist) continue;
neighbor.Dist = tempDist;
var tempWeight = neighbor.Dist + MsaglUtilities.EucledianDistance(vList[target].XLoc, vList[target].YLoc, neighbor.XLoc, neighbor.YLoc);
neighbor.Weight = tempWeight;
neighbor.Parent = u;
if (neighbor.Visited)
{
neighbor.Visited = false;
q.Enqueue(neighbor.Id, neighbor.Weight);
}
else q.DecreasePriority(neighbor.Id, neighbor.Weight);
}
if (u.Id == target)
break;
}
Vertex route = vList[target];
int zoomlevel = Math.Max(vList[source].ZoomLevel, vList[target].ZoomLevel);
while (route.Parent != null)
{
ShortestPath.Add(route.Id);
for (int neighb = 0; neighb < degList[route.Id]; neighb++)
if (eList[route.Id, neighb].NodeId == route.Parent.Id)
{
SetUsed(vList, eList, degList, route.Id, eList[route.Id, neighb].NodeId, zoomlevel);
Edgelist.Add(new VertexNeighbor(route.Id, neighb));
Distance += Math.Sqrt((route.XLoc - route.Parent.XLoc) * (route.XLoc - route.Parent.XLoc) + (route.YLoc - route.Parent.YLoc) * (route.YLoc - route.Parent.YLoc));
break;
}
route = route.Parent;
}
ShortestPath.Add(route.Id);
if (route.Id != source) Console.WriteLine("path not found");
return ShortestPath;
}
public void MSAGLGreedy(Vertex[] vList, Edge[,] eList, int[] degList, int source, int target, int n)
{
for (int i = 0; i < n; i++)
{
vList[i].Parent = null;
vList[i].Visited = false;
}
Edgelist.Clear();
ShortestPath.Clear();
Distance = 0;
Vertex currentVertex = vList[source];
int bestN;
double bestD, temp, discourage=0;
while (true)
{
if (currentVertex == null || currentVertex.Invalid) return;
currentVertex.Visited = true;
bestD = Double.MaxValue;
bestN = -1;
for (int neighb = 0; neighb < degList[currentVertex.Id]; neighb++)
{
var neighbor = eList[currentVertex.Id, neighb].NodeId;
if (vList[neighbor].Visited) continue;
if (eList[currentVertex.Id, neighb].Selected == 1) discourage = 1000; //continue;
else discourage = 0;
temp = MsaglUtilities.EucledianDistance(vList[neighbor].XLoc, vList[neighbor].YLoc,
vList[target].XLoc, vList[target].YLoc) + discourage;
if (temp < bestD)
{
bestD = temp;
bestN = neighbor;
}
}
if (currentVertex.Id == target)
break;
if (bestN == -1)
{
MSAGLAstarShortestPath(vList, eList, degList, source, target, n);
//Console.Write('*');
return;
}
vList[bestN].Parent = currentVertex;
currentVertex = vList[bestN];
}
Vertex route = vList[target];
int zoomlevel = Math.Max(vList[source].ZoomLevel, vList[target].ZoomLevel);
while (route.Parent != null)
{
ShortestPath.Add(route.Id);
for (int neighb = 0; neighb < degList[route.Id]; neighb++)
if (eList[route.Id, neighb].NodeId == route.Parent.Id)
{
SetUsed(vList, eList, degList, route.Id, eList[route.Id, neighb].NodeId, zoomlevel);
Edgelist.Add(new VertexNeighbor(route.Id, neighb));
break;
}
route = route.Parent;
}
ShortestPath.Add(route.Id);
if (route.Id != source) Console.WriteLine("path not found");
return;
}
public void MSAGLAstarSSSP(Vertex[] vList, Edge[,] eList, int[] degList, int source, Dictionary<Node, int> nodeId, GeometryGraph _mainGeometryGraph,
int NofNodesBeforeDetour, int n, Tiling g, Tiling g1)
{
var q = new BinaryHeapPriorityQueue(n);
vList[source].Dist = 0;
q.Enqueue(source, vList[source].Dist);
for (int i = 0; i < n; i++)
{
if (vList[i].Id != source)
{
vList[i].Dist = double.MaxValue;
q.Enqueue(i, vList[i].Dist);
}
vList[i].Parent = null;
vList[i].Visited = false;
}
Distance = 0;
while (q.Count > 0)
{
var deq = q.Dequeue();
Vertex u = vList[deq];
u.Visited = true;
if (u == null || u.Invalid) return;
for (int neighb = 0; neighb < degList[u.Id]; neighb++)
{
var neighborId = eList[u.Id, neighb].NodeId;
int discourage = 0;
if (u.Id < NofNodesBeforeDetour && u.Id != source) discourage = 1000;
Vertex neighbor = vList[neighborId];
double edist = MsaglUtilities.EucledianDistance(u.XLoc, u.YLoc, neighbor.XLoc, neighbor.YLoc);
var tempDist = u.Dist + edist + discourage;
if (tempDist >= neighbor.Dist) continue;
neighbor.Dist = tempDist;
neighbor.Parent = u;
if (neighbor.Visited)
{
neighbor.Visited = false;
q.Enqueue(neighbor.Id, neighbor.Dist);
}
else q.DecreasePriority(neighbor.Id, neighbor.Dist);
}
}
foreach (var node in _mainGeometryGraph.Nodes)
{
int target = nodeId[node];
if (target == source) continue;
Vertex route = vList[target];
int zoomlevel = Math.Max(vList[source].ZoomLevel, vList[target].ZoomLevel);
Edgelist.Clear();
while (route.Parent != null)
{
ShortestPath.Add(route.Id);
for (int neighb = 0; neighb < degList[route.Id]; neighb++)
if (eList[route.Id, neighb].NodeId == route.Parent.Id)
{
SetUsed(vList, eList, degList, route.Id, eList[route.Id, neighb].NodeId, zoomlevel);
Edgelist.Add(new VertexNeighbor(route.Id, neighb));
break;
}
route = route.Parent;
}
if (route.Id != source) Console.WriteLine("path not found");
foreach (VertexNeighbor vn in Edgelist)
g1.AddEdge(vn.A, g.EList[vn.A, vn.Neighbor].NodeId, g.EList[vn.A, vn.Neighbor].Selected, g.EList[vn.A, vn.Neighbor].Used);
}
return;
}
public void MSAGLSelectShortestPath(Vertex[] vList, Edge[,] eList, int[] degList, int source, int target, int n)
{
List<Vertex> q = new List<Vertex>();
vList[source].Dist = 0;
q.Add(vList[source]);
for (int i = 0; i < n; i++)
{
if (vList[i].Id != source)
{
vList[i].Dist = double.MaxValue;
q.Add(vList[i]);
}
vList[i].Parent = null;
vList[i].Visited = false;
}
Edgelist.Clear();
Distance = 0;
while (q.Count > 0)
{
Vertex u = getMin(q);
if (u == null) return;
if (u.Visited) continue;
else u.Visited = true;
for (int neighb = 0; neighb < degList[u.Id]; neighb++)
{
var neighbor = eList[u.Id, neighb].NodeId;
if (vList[neighbor].Visited) continue;
int discourage = 0;
if (eList[u.Id, neighb].Selected == 1) discourage = 1000;//continue;
if (eList[u.Id, neighb].NodeId == source || eList[u.Id, neighb].NodeId == target) discourage = 0;
if (u.Id == source || u.Id == target) discourage = 0;
var temp = u.Dist + eList[u.Id, neighb].GetEDist(vList, u.Id, eList[u.Id, neighb].NodeId) + discourage;
if (temp < vList[neighbor].Dist)
{
vList[neighbor].Dist = temp;
vList[neighbor].Parent = u;
//Update(q, vList[neighbor]);
}
}
if (u.Id == target)
break;
}
Vertex route = vList[target];
//Console.WriteLine();
//Console.WriteLine("Source,Target" + source + " " + target);
while (route.Parent != null)
{
//Console.Write(route.Id+" ");
for (int neighb = 0; neighb < degList[route.Id]; neighb++)
if (eList[route.Id, neighb].NodeId == route.Parent.Id)
{
SetUsed(vList, eList, degList, route.Id, eList[route.Id, neighb].NodeId, 1);
Edgelist.Add(new VertexNeighbor(route.Id, neighb));
Distance += Math.Sqrt((route.XLoc - route.Parent.XLoc) * (route.XLoc - route.Parent.XLoc) + (route.YLoc - route.Parent.YLoc) * (route.YLoc - route.Parent.YLoc));
break;
}
/*
for (int neighb = 0; neighb < degList[route.Parent.Id]; neighb++)
if (eList[route.Parent.Id, neighb].NodeId == route.Id)
{
SetUsed(vList, eList, degList, route.Parent.Id, eList[route.Parent.Id, neighb].NodeId);
Edgelist.Add(new VertexNeighbor(route.Parent.Id, neighb));
break;
}
* */
route = route.Parent;
}
//Console.Write(route.Id + " ");
if (route.Id != source) Console.WriteLine("path not found");
}
public void SetUsed(Vertex[] vList, Edge[,] eList, int[] degList, int a, int b, int zoomlevel)
{
for (int index = 0; index < degList[a]; index++)
{
if (eList[a, index].NodeId == b)
{
if (eList[a, index].Used > 0) return;
else eList[a, index].Used = zoomlevel;
}
}
for (int index = 0; index < degList[b]; index++)
{
if (eList[b, index].NodeId == a)
{
if (eList[b, index].Used > 0) return;
else eList[b, index].Used = zoomlevel;
}
}
}
/*
public void SelectShortestPath(Vertex [] vList, Edge [,] eList, int [] degList, int source, int target,int n){
PriorityQueue<double, Vertex> q = new PriorityQueue<double, Vertex>();
vList[source].Dist = 0;
q.Enqueue(vList[source].Dist, vList[source]);
for (int i = 1; i <= n; i++)
{
if ( vList[i].Id != vList[source].Id)
{
vList[i].Dist = double.MaxValue;
q.Enqueue(vList[i].Dist, vList[i]);
}
vList[i].Parent = null;
vList[i].Visited = false;
}
Edgelist.Clear();
Distance = 0;
while (q.Count > 0)
{
Vertex u = q.Dequeue().Value;
if (u.Visited) continue;
else u.Visited = true;
for (int neighb = 1; neighb <= degList[u.Id]; neighb++)
{
var neighbor = eList[u.Id,neighb].NodeId;
int discourage = 0;
if (eList[u.Id, neighb].Selected == 0) discourage = 10000;//continue;
if (vList[eList[u.Id, neighb].NodeId].Weight> 0 &&
eList[u.Id, neighb].NodeId != target) continue;
var temp = u.Dist + eList[u.Id, neighb].getEDist(vList, u.Id, eList[u.Id, neighb].NodeId) + discourage;
if (temp < vList[neighbor].Dist)
{
vList[neighbor].Dist = temp;
vList[neighbor].Parent = u;
q.Enqueue(vList[neighbor].Dist, vList[neighbor]);
}
}
if (u.Id ==vList[target].Id)
break;
}
Vertex route = vList[target];
while (route.Parent != null)
{
for (int neighb = 1; neighb <= degList[route.Id]; neighb++)
if (eList[route.Id, neighb].NodeId == route.Parent.Id){
//eList[route.ID, neighb].selected = 1;
Edgelist.Add(new VertexNeighbor(route.Id, neighb));
Distance += Math.Sqrt((route.XLoc - route.Parent.XLoc) * (route.XLoc - route.Parent.XLoc) + (route.YLoc - route.Parent.YLoc) * (route.YLoc - route.Parent.YLoc));
//encourage reusing of path by decreasing weight
//if (eList[route.ID, neighb].weight == 1) eList[route.ID, neighb].weight /= 2;
break;
}
for (int neighb = 1; neighb <= degList[route.Parent.Id]; neighb++)
if (eList[route.Parent.Id, neighb].NodeId == route.Id)
{
//eList[route.parent.ID, neighb].selected = 1;
Edgelist.Add(new VertexNeighbor(route.Parent.Id, neighb));
//encourage reusing of path by decreasing weight
//if (eList[route.parent.ID, neighb].weight == 1) eList[route.parent.ID, neighb].weight /= 2;
break;
}
route = route.Parent;
}
if(route.Id != source) Console.WriteLine("path not found");
}
*/
}
public class VertexNeighbor
{
public int A;
public int Neighbor;
public VertexNeighbor(int p, int q)
{
A = p; Neighbor = q;
}
}
}