mirror of
https://github.com/UnickSoft/graphonline.git
synced 2026-02-16 10:40:57 +00:00
first commit
This commit is contained in:
104
script/plugins/ConnectedComponent.js
Normal file
104
script/plugins/ConnectedComponent.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Default handler.
|
||||
* Select using mouse, drag.
|
||||
*
|
||||
*/
|
||||
function FindConnectedComponentNew(graph, app)
|
||||
{
|
||||
BaseAlgorithm.apply(this, arguments);
|
||||
this.connectedComponentNumber = 0;
|
||||
this.component = {};
|
||||
this.selectedObjects = [];
|
||||
}
|
||||
|
||||
|
||||
// inheritance.
|
||||
FindConnectedComponentNew.prototype = Object.create(BaseAlgorithm.prototype);
|
||||
|
||||
|
||||
FindConnectedComponentNew.prototype.getName = function(local)
|
||||
{
|
||||
return local == "ru" ? "Найти компоненты связности" : "Find connected components";
|
||||
}
|
||||
|
||||
FindConnectedComponentNew.prototype.getId = function()
|
||||
{
|
||||
return "OlegSh.ConnectedComponent";
|
||||
}
|
||||
|
||||
// @return message for user.
|
||||
FindConnectedComponentNew.prototype.getMessage = function(local)
|
||||
{
|
||||
return (this.graph.hasDirectEdge() ? g_sickConnectedComponent : g_connectedComponent) + this.connectedComponentNumber;
|
||||
}
|
||||
|
||||
FindConnectedComponentNew.prototype.result = function(resultCallback)
|
||||
{
|
||||
this.connectedComponentNumber = 0;
|
||||
this.component = {};
|
||||
var tempVertexes = this.graph.vertices.slice();
|
||||
connectedVertex = getVertexToVertexArray(this.graph, true);
|
||||
var connectedComponentNumber = 0;
|
||||
|
||||
while (tempVertexes.length > 0)
|
||||
{
|
||||
connectedComponentNumber++;
|
||||
|
||||
var stack = [];
|
||||
stack.push(tempVertexes[0]);
|
||||
|
||||
tempVertexes.splice(0, 1);
|
||||
|
||||
indexInStack = 0;
|
||||
|
||||
for (i = 0; i < stack.length; i++)
|
||||
{
|
||||
var stackElement = stack[i];
|
||||
this.component[stackElement.id] = connectedComponentNumber;
|
||||
stackElement.upText = connectedComponentNumber;
|
||||
|
||||
if (connectedVertex.hasOwnProperty(stackElement.id))
|
||||
{
|
||||
for (j = 0; j < connectedVertex[stackElement.id].length; j++)
|
||||
{
|
||||
var nextVertex = connectedVertex[stackElement.id][j];
|
||||
var connectedEdge = this.graph.FindEdge(stackElement.id, nextVertex.id);
|
||||
if (stack.indexOf(nextVertex) < 0)
|
||||
{
|
||||
stack.push(nextVertex);
|
||||
tempVertexes.splice(tempVertexes.indexOf(nextVertex), 1);
|
||||
if (connectedEdge)
|
||||
{
|
||||
this.component[connectedEdge.id] = connectedComponentNumber;
|
||||
}
|
||||
}
|
||||
else if (connectedEdge && !(connectedEdge.id in this.component))
|
||||
{
|
||||
this.component[connectedEdge.id] = connectedComponentNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.connectedComponentNumber = connectedComponentNumber;
|
||||
var result = {};
|
||||
result["version"] = 1;
|
||||
this.selectedObjects = this.component;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
FindConnectedComponentNew.prototype.getObjectSelectedGroup = function(object)
|
||||
{
|
||||
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
|
||||
}
|
||||
|
||||
|
||||
// Factory for connected components.
|
||||
function CreateConnectedComponetsNew(graph, app)
|
||||
{
|
||||
return new FindConnectedComponentNew(graph)
|
||||
}
|
||||
|
||||
// Gerister connected component.
|
||||
RegisterAlgorithm (CreateConnectedComponetsNew);
|
||||
87
script/plugins/EulerianLoop.js
Normal file
87
script/plugins/EulerianLoop.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Find Eulerian Loop.
|
||||
*
|
||||
*/
|
||||
function FindEulerianLoop(graph, app)
|
||||
{
|
||||
BaseAlgorithmEx.apply(this, arguments);
|
||||
this.message = g_processing;
|
||||
this.selectedObjects = [];
|
||||
}
|
||||
|
||||
|
||||
// inheritance.
|
||||
FindEulerianLoop.prototype = Object.create(BaseAlgorithmEx.prototype);
|
||||
|
||||
|
||||
FindEulerianLoop.prototype.getName = function(local)
|
||||
{
|
||||
return local == "ru" ? "Найти Эйлеров цикл" : "Find Eulerian cycle";
|
||||
}
|
||||
|
||||
FindEulerianLoop.prototype.getId = function()
|
||||
{
|
||||
return "OlegSh.FindEulerianCycle";
|
||||
}
|
||||
|
||||
// @return message for user.
|
||||
FindEulerianLoop.prototype.getMessage = function(local)
|
||||
{
|
||||
return this.message;
|
||||
}
|
||||
|
||||
FindEulerianLoop.prototype.result = function(resultCallback)
|
||||
{
|
||||
this.outResultCallback = function (result ) { resultCallback(result); };
|
||||
self = this;
|
||||
this.CalculateAlgorithm("elloop=cgiInput&report=xml", function (pathObjects, properties, results)
|
||||
{
|
||||
self.resultCallback(pathObjects, properties, results);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FindEulerianLoop.prototype.resultCallback = function(pathObjects, properties, results)
|
||||
{
|
||||
result = results.length > 0 && results[0].value > 0 && results[0].type == 1;
|
||||
|
||||
var outputResult = {};
|
||||
outputResult["version"] = 1;
|
||||
|
||||
this.message = result > 0 ? g_hasEulerianLoop : g_hasNotEulerianLoop;
|
||||
if (result > 0)
|
||||
{
|
||||
var nodesPath = this.GetNodesPath(results, 1, results.length - 1);
|
||||
outputResult["paths"] = [];
|
||||
outputResult["paths"].push(nodesPath);
|
||||
this.selectedObjects = [];
|
||||
|
||||
for (var i = 0; i < pathObjects.length; i++)
|
||||
{
|
||||
this.selectedObjects[pathObjects[i].id] = 1;
|
||||
}
|
||||
|
||||
this.message = this.message + ": ";
|
||||
for (var i = 0; i < nodesPath.length; i++)
|
||||
{
|
||||
this.message = this.message + this.graph.FindVertex(nodesPath[i]).mainText + ((i < nodesPath.length - 1) ? "⇒" : "");
|
||||
}
|
||||
}
|
||||
|
||||
this.outResultCallback(outputResult);
|
||||
}
|
||||
|
||||
FindEulerianLoop.prototype.getObjectSelectedGroup = function(object)
|
||||
{
|
||||
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
|
||||
}
|
||||
|
||||
// Factory for connected components.
|
||||
function CreateFindEulerianLoop(graph, app)
|
||||
{
|
||||
return new FindEulerianLoop(graph, app)
|
||||
}
|
||||
|
||||
// Gerister connected component.
|
||||
RegisterAlgorithm (CreateFindEulerianLoop);
|
||||
152
script/plugins/MinimumSpanningTree.js
Normal file
152
script/plugins/MinimumSpanningTree.js
Normal file
@@ -0,0 +1,152 @@
|
||||
|
||||
function MinimumSpanningTree(graph, app)
|
||||
{
|
||||
BaseAlgorithm.apply(this, arguments);
|
||||
this.isNotConneted = false;
|
||||
this.MST = 0;
|
||||
this.edges = [];
|
||||
}
|
||||
|
||||
|
||||
// inheritance.
|
||||
MinimumSpanningTree.prototype = Object.create(BaseAlgorithm.prototype);
|
||||
|
||||
|
||||
MinimumSpanningTree.prototype.getName = function(local)
|
||||
{
|
||||
return local == "ru" ? "Поиск минимального остовного дерева" : "Search of minimum spanning tree";
|
||||
}
|
||||
|
||||
MinimumSpanningTree.prototype.getId = function()
|
||||
{
|
||||
return "OlegSh.minimalSpanningTree";
|
||||
}
|
||||
|
||||
// @return message for user.
|
||||
MinimumSpanningTree.prototype.getMessage = function(local)
|
||||
{
|
||||
if (!this.isNotConneted )
|
||||
{
|
||||
return local == "ru" ? "Вес минимального оставного дерева равнен " + this.MST : "Weight of minimum spanning tree is " + this.MST;
|
||||
}
|
||||
else
|
||||
{
|
||||
return local == "ru" ? "Граф не является связным" : "Graph is disconnected";
|
||||
}
|
||||
}
|
||||
|
||||
MinimumSpanningTree.prototype.result = function(resultCallback)
|
||||
{
|
||||
this.MST = 0;
|
||||
this.edges = [];
|
||||
this.isNotConneted = true;
|
||||
var tempVertexes = this.graph.vertices.slice();
|
||||
connectedVertex = getVertexToVertexArray(this.graph, false);
|
||||
|
||||
if (!this.graph.hasDirectEdge())
|
||||
{
|
||||
res = this.resultStartedFrom(tempVertexes[0], connectedVertex);
|
||||
this.isNotConneted = res.isNotConneted;
|
||||
if (!this.isNotConneted)
|
||||
{
|
||||
this.MST = res.MST;
|
||||
this.edges = res.edges;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < tempVertexes.length; i++)
|
||||
{
|
||||
res = this.resultStartedFrom(tempVertexes[i], connectedVertex);
|
||||
if (!res.isNotConneted)
|
||||
{
|
||||
this.isNotConneted = res.isNotConneted;
|
||||
if (this.MST == 0 || res.MST < this.MST)
|
||||
{
|
||||
console.log(res);
|
||||
this.MST = res.MST;
|
||||
this.edges = res.edges;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result = {};
|
||||
result["version"] = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MinimumSpanningTree.prototype.resultStartedFrom = function(vertex, connectedVertex)
|
||||
{
|
||||
var res = {};
|
||||
res.MST = 0;
|
||||
res.edges = [];
|
||||
res.isNotConneted = false;
|
||||
|
||||
var inTree = [];
|
||||
inTree.push(vertex);
|
||||
var vertecesInTree = 0;
|
||||
|
||||
// Will break in end of loop
|
||||
while (true)
|
||||
{
|
||||
vertecesInTree++;
|
||||
var minVert = null;
|
||||
var minEdge = null;
|
||||
|
||||
for (i = 0; i < inTree.length; i++)
|
||||
{
|
||||
var element = inTree[i];
|
||||
|
||||
if (connectedVertex.hasOwnProperty(element.id))
|
||||
{
|
||||
for (j = 0; j < connectedVertex[element.id].length; j++)
|
||||
{
|
||||
var connectedElement = connectedVertex[element.id][j];
|
||||
var connectedEdge = this.graph.FindEdge(element.id, connectedElement.id);
|
||||
if (inTree.indexOf(connectedElement) < 0)
|
||||
{
|
||||
if (minEdge == null || minEdge.weight > connectedEdge.weight)
|
||||
{
|
||||
minEdge = connectedEdge;
|
||||
minVert = connectedElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minVert == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.MST = res.MST + Number(minEdge.weight);
|
||||
inTree.push(minVert);
|
||||
res.edges.push(minEdge);
|
||||
}
|
||||
}
|
||||
|
||||
res.isNotConneted = (inTree.length < this.graph.vertices.length);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
MinimumSpanningTree.prototype.getObjectSelectedGroup = function(object)
|
||||
{
|
||||
return this.isNotConneted ? 0 :
|
||||
(object instanceof BaseVertex || this.edges.indexOf(object) >= 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
// Factory for algorithm.
|
||||
function CreateMinimumSpanningTree(graph, app)
|
||||
{
|
||||
return new MinimumSpanningTree(graph)
|
||||
}
|
||||
|
||||
// Register connected component.
|
||||
RegisterAlgorithm (CreateMinimumSpanningTree);
|
||||
|
||||
212
script/plugins/ShortestPath.js
Normal file
212
script/plugins/ShortestPath.js
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Find short path.
|
||||
*
|
||||
*/
|
||||
function FindShortPathNew(graph, app)
|
||||
{
|
||||
BaseAlgorithmEx.apply(this, arguments);
|
||||
this.message = g_selectStartVertexForShortPath;
|
||||
this.selectedObjects = {};
|
||||
}
|
||||
|
||||
|
||||
// inheritance.
|
||||
FindShortPathNew.prototype = Object.create(BaseAlgorithmEx.prototype);
|
||||
// First selected.
|
||||
FindShortPathNew.prototype.firstObject = null;
|
||||
// Second selected.
|
||||
FindShortPathNew.prototype.secondObject = null;
|
||||
// Path
|
||||
FindShortPathNew.prototype.pathObjects = null;
|
||||
|
||||
|
||||
FindShortPathNew.prototype.getName = function(local)
|
||||
{
|
||||
return local == "ru" ? "Найти кратчайший путь" : "Find shortest path";
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.getId = function()
|
||||
{
|
||||
return "OlegSh.FindShortestPath";
|
||||
}
|
||||
|
||||
// @return message for user.
|
||||
FindShortPathNew.prototype.getMessage = function(local)
|
||||
{
|
||||
return this.message;
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.result = function(resultCallback)
|
||||
{
|
||||
if (this.firstObject && this.secondObject)
|
||||
{
|
||||
this.outResultCallback = function (result ) { resultCallback(result); };
|
||||
self = this;
|
||||
this.CalculateAlgorithm("dsp=cgiInput&start=" + this.firstObject.id + "&finish=" + this.secondObject.id + "&report=xml", function (pathObjects, properties, results)
|
||||
{
|
||||
self.resultCallback(pathObjects, properties, results);
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.resultCallback = function(pathObjects, properties, results)
|
||||
{
|
||||
var outputResult = {};
|
||||
outputResult["version"] = 1;
|
||||
|
||||
this.pathObjects = pathObjects;
|
||||
this.properties = properties;
|
||||
|
||||
var bFound = results.length > 0 && results[0].value < 1E5 && (results[0].type == 1 || results[0].type == 2);
|
||||
|
||||
if (bFound)
|
||||
{
|
||||
this.selectedObjects = {};
|
||||
|
||||
for (var i = 0; i < pathObjects.length; i++)
|
||||
{
|
||||
this.selectedObjects[pathObjects[i].id] = 1;
|
||||
}
|
||||
|
||||
this.message = g_shortestPathResult.replace("%d", (results[0].value * 1).toString());
|
||||
|
||||
var nodesPath = this.GetNodesPath(results, 1, results.length - 1);
|
||||
outputResult["paths"] = [];
|
||||
outputResult["paths"].push(nodesPath);
|
||||
|
||||
this.message = this.message + ": ";
|
||||
for (var i = 0; i < nodesPath.length; i++)
|
||||
{
|
||||
this.message = this.message + this.graph.FindVertex(nodesPath[i]).mainText + ((i < nodesPath.length - 1) ? "⇒" : "");
|
||||
}
|
||||
|
||||
this.message = this.message + " <select style=\"float:right\" id=\"enumReport\"></select>";
|
||||
|
||||
this.updateUpText();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.message = g_pathNotExists;
|
||||
}
|
||||
this.secondObject = null;
|
||||
this.firstObject = null;
|
||||
|
||||
this.outResultCallback(outputResult);
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.selectVertex = function(vertex)
|
||||
{
|
||||
this.pathObjects = null;
|
||||
this.shortDist = null;
|
||||
|
||||
if (this.firstObject)
|
||||
{
|
||||
this.message = g_processing;
|
||||
this.secondObject = vertex;
|
||||
this.selectedObjects = [];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.firstObject = vertex;
|
||||
this.secondObject = null;
|
||||
this.selectedObjects = {};
|
||||
this.message = g_selectFinishVertexForShortPath;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.deselectAll = function()
|
||||
{
|
||||
this.firstObject = null;
|
||||
this.secondObject = null;
|
||||
this.selectedObjects = {};
|
||||
this.message = g_selectStartVertexForShortPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.instance = function()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.getObjectSelectedGroup = function(object)
|
||||
{
|
||||
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : ((object == this.firstObject || object == object.secondObject) ? 1 : 0);
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.messageWasChanged = function()
|
||||
{
|
||||
var enumReport = document.getElementById("enumReport");
|
||||
if (enumReport)
|
||||
{
|
||||
var optionFull = document.createElement('option');
|
||||
optionFull.text = g_fullReport;
|
||||
optionFull.value = 0;
|
||||
|
||||
var optionShort = document.createElement('option');
|
||||
optionShort.text = g_shortReport;
|
||||
optionShort.value = 1;
|
||||
|
||||
enumReport.add(optionFull, 0);
|
||||
enumReport.add(optionShort, 1);
|
||||
|
||||
enumReport.selectedIndex = this.app.GetCurrentValue("findShortPathReportType", 1);
|
||||
|
||||
var self = this;
|
||||
enumReport.onchange = function () {
|
||||
self.changedType();
|
||||
self.app.redrawGraph();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FindShortPathNew.prototype.changedType = function()
|
||||
{
|
||||
var enumReport = document.getElementById("enumReport");
|
||||
|
||||
this.app.SetCurrentValue("findShortPathReportType", enumReport.options[enumReport.selectedIndex].value);
|
||||
this.updateUpText();
|
||||
}
|
||||
|
||||
FindShortPathNew.prototype.updateUpText = function()
|
||||
{
|
||||
var reportType = this.app.GetCurrentValue("findShortPathReportType", 1);
|
||||
|
||||
if (reportType == 0)
|
||||
{
|
||||
for (var i = 0; i < this.graph.vertices.length; i++)
|
||||
{
|
||||
var object = this.graph.vertices[i];
|
||||
if (this.properties.hasOwnProperty(object.id))
|
||||
{
|
||||
var propertie = this.properties[object.id];
|
||||
if (propertie.hasOwnProperty('lowestDistance'))
|
||||
{
|
||||
object.upText = g_shortestDistance + (propertie.lowestDistance > 1E5 ? "\u221E" : (propertie.lowestDistance * 1).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < this.graph.vertices.length; i++)
|
||||
{
|
||||
this.graph.vertices[i].upText = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Factory for connected components.
|
||||
function CreateFindShortPathNew(graph, app)
|
||||
{
|
||||
return new FindShortPathNew(graph, app)
|
||||
}
|
||||
|
||||
// Gerister connected component.
|
||||
RegisterAlgorithm (CreateFindShortPathNew);
|
||||
73
script/plugins/VerticesDegree.js
Normal file
73
script/plugins/VerticesDegree.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Algorithm samble.
|
||||
*
|
||||
*/
|
||||
function VerticesDegree(graph, app)
|
||||
{
|
||||
BaseAlgorithm.apply(this, arguments);
|
||||
this.degree = {};
|
||||
this.maxDegree = 0;
|
||||
}
|
||||
|
||||
|
||||
// inheritance.
|
||||
VerticesDegree.prototype = Object.create(BaseAlgorithm.prototype);
|
||||
|
||||
|
||||
VerticesDegree.prototype.getName = function(local)
|
||||
{
|
||||
return local == "ru" ? "Рассчитать степень вершин" : "Calculate vertices degree";
|
||||
}
|
||||
|
||||
VerticesDegree.prototype.getId = function()
|
||||
{
|
||||
return "OlegSh.VertexDegree";
|
||||
}
|
||||
|
||||
// @return message for user.
|
||||
VerticesDegree.prototype.getMessage = function(local)
|
||||
{
|
||||
return (local == "ru" ? "Максимальная степень вершин графа равна " : "The maximum degree of a graph is ") + this.maxDegree;
|
||||
}
|
||||
|
||||
VerticesDegree.prototype.result = function(resultCallback)
|
||||
{
|
||||
this.degree = {};
|
||||
this.maxDegree = 0;
|
||||
|
||||
var result = {};
|
||||
result["version"] = 1;
|
||||
this.degree = getVertexToVertexArray(this.graph, false);
|
||||
var graph = this.graph;
|
||||
|
||||
for (var i = 0; i < graph.vertices.length; i++)
|
||||
{
|
||||
var vertex = graph.vertices[i];
|
||||
var currentDegree = 0;
|
||||
|
||||
if (this.degree.hasOwnProperty(vertex.id))
|
||||
{
|
||||
currentDegree = this.degree[vertex.id].length;
|
||||
this.maxDegree = Math.max(this.maxDegree, currentDegree);
|
||||
}
|
||||
|
||||
vertex.upText = currentDegree;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VerticesDegree.prototype.getObjectSelectedGroup = function(object)
|
||||
{
|
||||
return (this.degree.hasOwnProperty(object.id)) ? this.degree[object.id].length: 0;
|
||||
}
|
||||
|
||||
|
||||
// Factory for connected components.
|
||||
function CreateAlgorithmVerticesDegree(graph, app)
|
||||
{
|
||||
return new VerticesDegree(graph, app)
|
||||
}
|
||||
|
||||
// Gerister connected component.
|
||||
RegisterAlgorithm (CreateAlgorithmVerticesDegree);
|
||||
Reference in New Issue
Block a user