Change script location.

Split js code.
Added cache and changed loading mechanism for js sources.
This commit is contained in:
Oleg Sh
2023-11-06 19:16:50 +02:00
parent c29ad15e3c
commit 43a4b44a22
86 changed files with 7738 additions and 3383 deletions

View File

@@ -0,0 +1,35 @@
{
let modulDir = "features/algorithms/";
doInclude ([
include ("model/Algorithms.js", modulDir),
include ("model/BaseTraversal.js", modulDir)
])
function loadAsyncAlgorithms(onFinish) {
let pluginsList = ["BFS.js",
"Coloring.js",
"ConnectedComponent.js",
"DFS.js",
"EulerianLoop.js",
"EulerianPath.js",
"FindAllPatches.js",
"FindLongestPath.js",
"FindShortPatchsFromOne.js",
"Floid.js",
"GraphReorder.js",
"HamiltonianLoop.js",
"HamiltonianPath.js",
"IsomorphismCheck.js",
"MaxClique.js",
"MaxFlow.js",
"MinimumSpanningTree.js",
"ModernGraphStyle.js",
"RadiusAndDiameter.js",
"ShortestPath.js",
"VerticesDegree.js"];
doIncludeAsync (pluginsList.map((plugin) => include ("model/plugins/" + plugin, modulDir)), onFinish);
}
}

View File

@@ -0,0 +1,305 @@
/**
* File for algorithms.
*
*/
// Return list of 'vertex = [connected vertices]'
function getVertexToVertexArray(graph, ignoreDirection)
{
res = {};
for (var i = 0; i < graph.edges.length; i ++)
{
edge = graph.edges[i];
if (!res.hasOwnProperty(edge.vertex1.id))
{
res[edge.vertex1.id] = [];
}
res[edge.vertex1.id].push(edge.vertex2);
if (!edge.isDirect || ignoreDirection)
{
if (!res.hasOwnProperty(edge.vertex2.id))
{
res[edge.vertex2.id] = [];
}
res[edge.vertex2.id].push(edge.vertex1);
}
}
return res;
}
// Global array of all algorithms.
var g_Algorithms = [];
var g_AlgorithmIds = [];
// Call this function to register your factory algorithm.
function RegisterAlgorithm (factory)
{
g_Algorithms.push(factory);
g_AlgorithmIds.push(factory(null).getId());
}
// Base algorithm class.
function BaseAlgorithm (graph, app)
{
this.graph = graph;
this.app = app;
}
// @return name of algorithm. For now we supports only 2 locals: "ru" and "en"
BaseAlgorithm.prototype.getName = function(local)
{
return "unknown_name_" + local;
}
// @return id of algorithm. Please use format: "your id"."algorithm id". Ex. "OlegSh.ConnectedComponent"
BaseAlgorithm.prototype.getId = function()
{
return "unknown.unknown";
}
// @return message for user.
BaseAlgorithm.prototype.getMessage = function(local)
{
return "unknown_message_" + local;
}
// calls when user select vertex.
// @return true if you allow to select this object or false.
BaseAlgorithm.prototype.selectVertex = function(vertex)
{
return false;
}
// calls when user select edge.
// @return true if you allow to select this object or false.
BaseAlgorithm.prototype.selectEdge = function(edge)
{
return false;
}
// user click to workspace.
// @return true if you allow to deselect all
BaseAlgorithm.prototype.deselectAll = function()
{
return true;
}
// get result of algorithm.
// If result if not ready, please return null.
// It will be called after each user action.
// Please return true, if you done.
BaseAlgorithm.prototype.result = function(resultCallback)
{
return null;
}
// If you no need to get feedback from user, return true.
// In this case result will calls once.
BaseAlgorithm.prototype.instance = function()
{
return true;
}
// @return false, if you change up text and do not want to restore it back.
BaseAlgorithm.prototype.needRestoreUpText = function()
{
return true;
}
// @return true, if you change restore graph after use.
BaseAlgorithm.prototype.wantRestore = function()
{
return false;
}
// calls this method if wantRestore return true.
BaseAlgorithm.prototype.restore = function()
{
}
// @return 0, if object is not selected, in other case return groupe of selection.
BaseAlgorithm.prototype.getObjectSelectedGroup = function(object)
{
return 0;
}
// This method is called, when messages was updated on html page.
BaseAlgorithm.prototype.messageWasChanged = function() {}
// Algorithm priority in menu
BaseAlgorithm.prototype.getPriority = function()
{
return 0;
}
// Algorithm support multi graph
BaseAlgorithm.prototype.IsSupportMultiGraph = function()
{
return false;
}
BaseAlgorithm.prototype.getCategory = function()
{
return 0;
}
/**
* Default handler.
* Select using mouse, drag.
*
*/
function BaseAlgorithmEx(graph, app)
{
BaseAlgorithm.apply(this, arguments);
}
// inheritance.
BaseAlgorithmEx.prototype = Object.create(BaseAlgorithm.prototype);
BaseAlgorithmEx.prototype.CalculateAlgorithm = function(algorithmName, otherParams, resultCallback, ignoreSeparateNodes = false)
{
if (location.hostname === "localhost" || location.hostname === "127.0.0.1")
console.log(algorithmName + " " + otherParams);
var graph = this.graph;
var ignoreNodes = {};
if (ignoreSeparateNodes)
for (var i = 0; i < graph.vertices.length; i++)
if (!graph.HasConnectedNodes(graph.vertices[i]))
ignoreNodes[graph.vertices[i].id] = 1;
var creator = new GraphMLCreator(graph.vertices, graph.edges, ignoreNodes);
var pathObjects = [];
var properties = {};
var result = [];
var xml = creator.GetXMLString();
console.log(xml);
var processResult = function (msg) {
console.log(msg);
$('#debug').text(msg);
xmlDoc = $.parseXML( msg );
var $xml = $( xmlDoc );
$results = $xml.find( "result" );
$results.each(function(){
$values = $(this).find( "value" );
$values.each(function(){
var type = $(this).attr('type');
var value = $(this).text();
var res = {};
res.type = type;
res.value = value;
result.push(res);
});
});
$nodes = $xml.find( "node" );
$nodes.each(function(){
var id = $(this).attr('id');
$data = $(this).find("data");
$data.each(function(){
if ("hightlightNode" == $(this).attr('key') && $(this).text() == "1")
{
pathObjects.push(graph.FindVertex(id));
}
else
{
if (!properties[id])
{
properties[id] = {};
}
properties[id][$(this).attr('key')] = $(this).text();
}
});
});
$edges = $xml.find( "edge" );
$edges.each(function(){
var source = $(this).attr('source');
var target = $(this).attr('target');
var edge = graph.FindEdge(source, target);
if (typeof $(this).attr('id') !== 'undefined')
{
edge = graph.FindEdgeById($(this).attr('id'));
}
pathObjects.push(edge);
$data = $(this).find("data");
$data.each(function(){
if (!properties[edge.id])
{
properties[edge.id] = {};
}
properties[edge.id][$(this).attr('key')] = $(this).text();
});
});
console.log(result);
resultCallback(pathObjects, properties, result);
};
if (this.app.isSupportEmscripten()) {
console.log("Use Emscripten");
var delimiter = "<s\\emscript_split\\s>";
var processData = algorithmName + delimiter + xml +
delimiter + "report" + delimiter + "xml";
otherParams.forEach ( (param) => processData += delimiter + param.name + delimiter + param.value);
var res = this.app.processEmscripten(processData);
processResult(res);
} else {
console.log("Use new CGI");
var queryString = algorithmName + "=cgiInput&report=xml";
otherParams.forEach ( (param) => queryString += "&" + param.name + "=" + param.value);
$.ajax({
type: "POST",
url: "/" + SiteDir + "cgi-bin/GraphCGI.exe?" + queryString,
data: xml,
dataType: "text",
})
.done(function( msg )
{
processResult(msg);
});
}
return true;
}
BaseAlgorithmEx.prototype.GetNodesPath = function(array, start, count)
{
var res = [];
for (var index = start; index < start + count; index++)
{
if (array[index].type == 4)
{
res.push(array[index].value);
}
}
return res;
}
BaseAlgorithmEx.prototype.GetNodesEdgesPath = function(array, start, count)
{
var res = [];
for (var index = start; index < start + count; index++)
{
if (array[index].type == 4 || array[index].type == 5)
{
res.push(array[index].value);
}
}
return res;
}

View File

@@ -0,0 +1,56 @@
/**
* Find short path.
*
*/
function BaseTraversal(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.visited = [];
this.edges = [];
this.timer = null;
}
// inheritance.
BaseTraversal.prototype = Object.create(BaseAlgorithmEx.prototype);
// timer interval
BaseTraversal.prototype.timerInterval = 500;
BaseTraversal.prototype.result = function(resultCallback)
{
var result = {};
result["version"] = 1;
return result;
}
BaseTraversal.prototype.selectVertex = function(vertex)
{
this.visited = [];
this.edges = [];
if (this.timer)
clearTimeout(this.timer);
this.timer = null;
this.visited.push(vertex);
var context = this;
this.timer = setInterval(function()
{
context.step();
}, this.timerInterval);
this.message = this.getMainMessage();
return true;
}
BaseTraversal.prototype.getObjectSelectedGroup = function(object)
{
return (this.visited.includes(object) ? 1 : (this.edges.includes(object) ? 1 : 0));
}
BaseTraversal.prototype.instance = function()
{
return false;
}

View File

@@ -0,0 +1,125 @@
/**
* Find short path.
*
*/
function BFSAlgorithm(graph, app)
{
BaseTraversal.apply(this, arguments);
this.message = g_startTraversal;
}
// inheritance.
BFSAlgorithm.prototype = Object.create(BaseTraversal.prototype);
// timer interval
BFSAlgorithm.prototype.timerInterval = 500;
BFSAlgorithm.prototype.getName = function(local)
{
return g_BFSName;// local == "ru" ? "Поиск в ширину" : "Breadth-first search";
}
BFSAlgorithm.prototype.getId = function()
{
return "OlegSh.BFSAlgorithm";
}
// @return message for user.
BFSAlgorithm.prototype.getMessage = function(local)
{
return this.message;
}
BFSAlgorithm.prototype.getCategory = function()
{
return 1;
}
BFSAlgorithm.prototype.result = function(resultCallback)
{
var result = {};
result["version"] = 1;
return result;
}
BFSAlgorithm.prototype.getMainMessage = function()
{
var message = g_traversalOrder;
// calculate.
var tempVisited = this.visited.slice();
var tempEdge = [];
var oldLength = 0;
while (oldLength < tempVisited.length)
{
oldLength = tempVisited.length;
for (var i = 0; i < tempVisited.length; i++)
{
if (this.bfs(tempVisited[i], tempVisited, tempEdge))
break;
}
}
// Format message
for (var i = 0; i < tempVisited.length; i ++)
{
tempVisited[i].upText = (i + 1) + "";
message = message + tempVisited[i].mainText + " ";
}
return message;
}
BFSAlgorithm.prototype.getPriority = function()
{
return -9.5;
}
BFSAlgorithm.prototype.step = function()
{
for (var i = 0; i < this.visited.length; i++)
{
if (this.bfs(this.visited[i], this.visited, this.edges))
{
this.app.redrawGraph();
return;
}
}
clearTimeout(this.timer);
this.timer = null;
return;
}
BFSAlgorithm.prototype.bfs = function(vertex, vertexArray, edgeArray)
{
for (var i = 0; i < this.graph.vertices.length; i ++)
{
var nextVertex = this.graph.vertices[i];
var edge = this.graph.FindEdgeAny(vertex.id, nextVertex.id);
if (edge && !vertexArray.includes(nextVertex))
{
edgeArray.push(edge);
vertexArray.push(nextVertex);
return true;
}
}
return false;
}
// Algorithm support multi graph
BFSAlgorithm.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateBFSAlgorithm(graph, app)
{
return new BFSAlgorithm(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateBFSAlgorithm);

View File

@@ -0,0 +1,386 @@
/**
* Default handler.
* Select using mouse, drag.
*
*/
function Coloring(graph, app)
{
BaseAlgorithm.apply(this, arguments);
this.connectedComponentNumber = 0;
this.component = {};
this.selectedObjects = [];
this.MaxColor = 1000;
}
// inheritance.
Coloring.prototype = Object.create(BaseAlgorithm.prototype);
Coloring.prototype.getName = function(local)
{
return g_ColoringName; //local == "ru" ? "Раскраска графа" : "Graph coloring";
}
Coloring.prototype.getId = function()
{
return "OlegSh.GraphColoring";
}
// @return message for user.
Coloring.prototype.getMessage = function(local)
{
return g_colorNumber + " " + this.connectedComponentNumber;
}
Coloring.prototype.result = function(resultCallback)
{
this.calculate(true);
var result = {};
result["version"] = 1;
this.selectedObjects = this.component;
return result;
}
Coloring.prototype.calculate = function(fillUpText = false)
{
this.connectedComponentNumber = 0;
this.component = {};
connectedVertex = getVertexToVertexArray(this.graph, true);
var listOfOrders = [];
this.addSimpleAndRandomOrders(listOfOrders);
this.addBasedOnDegree(listOfOrders, connectedVertex);
this.addForTree(listOfOrders, connectedVertex);
this.connectedComponentNumber = this.MaxColor;
// Find minimal variant.
for (var i = 0; i < listOfOrders.length; i++)
{
var coloringComponent = this.makeColoring(listOfOrders[i], connectedVertex);
if (coloringComponent["max"] < this.connectedComponentNumber)
{
this.component = coloringComponent;
this.connectedComponentNumber = coloringComponent["max"];
}
}
// Fill Up text
for (var i = 0; i < this.graph.vertices.length; i++)
{
this.graph.vertices[i].upText = this.component[this.graph.vertices[i].id];
}
//var result = {};
//result["version"] = 1;
//this.selectedObjects = this.component;
return this.connectedComponentNumber;
}
Coloring.prototype.makeColoring = function(vertexOrder, connectedVertex)
{
var res = {};
var maxColor = 0;
for (var i = 0; i < vertexOrder.length; i++)
{
var id = this.graph.vertices[vertexOrder[i]].id;
var hasColor = {};
if (id in connectedVertex)
{
// find color of neighbors.
for (var j = 0; j < connectedVertex[id].length; j++)
{
nearId = connectedVertex[id][j].id;
if (nearId in res)
{
hasColor[res[nearId]] = 1;
}
}
}
// find color for current vertex;
var color = 0;
for (var j = 1; j < this.MaxColor; j++)
{
if (!(j in hasColor))
{
color = j;
break;
}
}
res[id] = color;
maxColor = Math.max(maxColor, color);
}
res["max"] = maxColor;
return res;
}
Coloring.prototype.addSimpleAndRandomOrders = function(listOfOrders)
{
var vertexOrder = [];
for (var i = 0; i < this.graph.vertices.length; i++)
{
vertexOrder.push(i);
}
// As in graph
listOfOrders.push(vertexOrder);
// Push some randoms
for (var i = 0; i < Math.floor(Math.sqrt(this.graph.vertices.length)); i++)
{
listOfOrders.push(this.shuffleArray(vertexOrder));
}
}
Coloring.prototype.addBasedOnDegree = function(listOfOrders, connectedVertex)
{
var vertexDegree = [];
for (var i = 0; i < this.graph.vertices.length; i++)
{
var degree = 0;
var id = this.graph.vertices[i].id;
if (id in connectedVertex)
{
degree = connectedVertex[id].length;
}
vertexDegree.push({index : i, degree : degree});
}
// sort
vertexDegree.sort(
function(a, b) {
return (a.degree > b.degree) ? -1 :
((b.degree > a.degree) ? 1 : 0);
});
var vertexOrder = [];
for (var i = 0; i < vertexDegree.length; i++)
{
vertexOrder.push(vertexDegree[i].index);
}
//console.log(vertexDegree);
// Sorted by degree.
listOfOrders.push(vertexOrder);
var shuffleLitle = vertexOrder.slice();
for (var i = 0; i < shuffleLitle.length - 1; i +=2)
{
var t = shuffleLitle[i];
shuffleLitle[i] = shuffleLitle[i + 1];
shuffleLitle[i + 1] = t;
}
// Swap near.
listOfOrders.push(shuffleLitle);
// shufl by half
if (vertexDegree.length > 1)
{
var pivotElement = Math.round(vertexOrder.length / 2);
var randomByPart = this.shuffleArray(vertexOrder.slice(0, pivotElement)).concat(this.shuffleArray(vertexOrder.slice(pivotElement)));
listOfOrders.push(randomByPart);
// add with random pivots
for (var i = 0; i < Math.floor(Math.sqrt(this.graph.vertices.length)); i++)
{
var pivot = Math.floor(Math.random() * (vertexOrder.length - 2)) + 1;
var randomByPart = this.shuffleArray(vertexOrder.slice(0, pivot)).concat(this.shuffleArray(vertexOrder.slice(pivot)));
listOfOrders.push(randomByPart);
//console.log(randomByPart);
}
}
}
Coloring.prototype.addForTree = function(listOfOrders, connectedVertex)
{
var vertexDegree = [];
var idToIndex = {};
var idToDegree = {};
for (var i = 0; i < this.graph.vertices.length; i++)
{
var degree = 0;
var id = this.graph.vertices[i].id;
if (id in connectedVertex)
{
degree = connectedVertex[id].length;
}
vertexDegree.push({index : i, degree : degree});
idToIndex[id] = i;
idToDegree[id] = degree;
}
// sort
vertexDegree.sort(
function(a, b) {
return (a.degree > b.degree) ? -1 :
((b.degree > a.degree) ? 1 : 0);
});
var vertexDegreeOrder = [];
for (var i = 0; i < vertexDegree.length; i++)
{
vertexDegreeOrder.push(vertexDegree[i].index);
}
{
var wasAdded = {};
var resSimple = [];
//------ simple near ------
for (var i = 0; i < vertexDegreeOrder.length; i++)
{
var vertex = this.graph.vertices[vertexDegreeOrder[i]].id;
if (!(vertex in wasAdded))
{
wasAdded[vertex] = 1;
resSimple.push(idToIndex[vertex]);
var queue = [];
queue.push(vertex);
while (true)
{
var needBreak = true;
for (var j = 0; j < queue.length; j++)
{
var vertexId = queue[j];
if (vertexId in connectedVertex)
{
for (var k = 0; k < connectedVertex[vertexId].length; k++)
{
if (!(connectedVertex[vertexId][k].id in wasAdded))
{
var id = connectedVertex[vertexId][k].id;
wasAdded[id] = 1;
queue.push(id);
resSimple.push(idToIndex[id]);
needBreak = false;
}
}
}
}
if (needBreak)
{
break;
}
}
}
}
listOfOrders.push(resSimple);
}
//-------------------------------
//------ simple near with max degree
{
var wasAdded = {};
var resMaxDegree = [];
for (var i = 0; i < vertexDegreeOrder.length; i++)
{
var vertex = this.graph.vertices[vertexDegreeOrder[i]].id;
if (!(vertex in wasAdded))
{
wasAdded[vertex] = 1;
resMaxDegree.push(idToIndex[vertex]);
var queue = [];
queue.push(vertex);
while (true)
{
var needBreak = true;
for (var j = 0; j < queue.length; j++)
{
var vertexId = queue[j];
if (vertexId in connectedVertex)
{
var maxDegree = -1;
var vertexMaxId = -1;
for (var k = 0; k < connectedVertex[vertexId].length; k++)
{
if (!(connectedVertex[vertexId][k].id in wasAdded))
{
var id = connectedVertex[vertexId][k].id;
if (idToDegree[id] > maxDegree)
{
maxDegree = idToDegree[id];
vertexMaxId = id;
}
}
}
if (vertexMaxId >= 0)
{
wasAdded[vertexMaxId] = 1;
queue.push(vertexMaxId);
resMaxDegree.push(idToIndex[vertexMaxId]);
needBreak = false;
}
}
}
if (needBreak)
{
break;
}
}
}
}
listOfOrders.push(resMaxDegree);
}
//-------------------------------
}
Coloring.prototype.shuffleArray = function(a)
{
var j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
return a;
}
Coloring.prototype.getObjectSelectedGroup = function(object)
{
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
}
Coloring.prototype.getPriority = function()
{
return -9.0;
}
// Algorithm support multi graph
Coloring.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateColoring(graph, app)
{
return new Coloring(graph)
}
// Gerister connected component.
RegisterAlgorithm (CreateColoring);

View File

@@ -0,0 +1,130 @@
/**
* 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 g_findConnectedComponent; //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.calculate(true);
var result = {};
result["version"] = 1;
this.selectedObjects = this.component;
return result;
}
FindConnectedComponentNew.prototype.calculate = function(fillUpText = false)
{
this.connectedComponentNumber = 0;
this.component = {};
var tempVertices = this.graph.vertices.slice();
connectedVertex = getVertexToVertexArray(this.graph, true);
var connectedComponentNumber = 0;
while (tempVertices.length > 0)
{
connectedComponentNumber++;
var stack = [];
stack.push(tempVertices[0]);
tempVertices.splice(0, 1);
indexInStack = 0;
for (i = 0; i < stack.length; i++)
{
var stackElement = stack[i];
this.component[stackElement.id] = connectedComponentNumber;
if (fillUpText)
{
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.FindEdgeAny(stackElement.id, nextVertex.id);
if (stack.indexOf(nextVertex) < 0)
{
stack.push(nextVertex);
tempVertices.splice(tempVertices.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 this.connectedComponentNumber;
}
FindConnectedComponentNew.prototype.getObjectSelectedGroup = function(object)
{
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
}
FindConnectedComponentNew.prototype.getPriority = function()
{
return 0;
}
// Algorithm support multi graph
FindConnectedComponentNew.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateConnectedComponetsNew(graph, app)
{
return new FindConnectedComponentNew(graph)
}
// Gerister connected component.
RegisterAlgorithm (CreateConnectedComponetsNew);

View File

@@ -0,0 +1,124 @@
/**
* Find short path.
*
*/
function DFSAlgorithm(graph, app)
{
BaseTraversal.apply(this, arguments);
this.message = g_startTraversal;
}
// inheritance.
DFSAlgorithm.prototype = Object.create(BaseTraversal.prototype);
// timer interval
DFSAlgorithm.prototype.timerInterval = 500;
DFSAlgorithm.prototype.getName = function(local)
{
return g_DFSName;// local == "ru" ? "Поиск в глубину" : "Depth-first search";
}
DFSAlgorithm.prototype.getId = function()
{
return "OlegSh.DFSAlgorithm";
}
// @return message for user.
DFSAlgorithm.prototype.getMessage = function(local)
{
return this.message;
}
DFSAlgorithm.prototype.result = function(resultCallback)
{
var result = {};
result["version"] = 1;
return result;
}
DFSAlgorithm.prototype.getMainMessage = function()
{
var message = g_traversalOrder;
// calculate.
var tempVisited = this.visited.slice();
var tempEdge = [];
var oldLength = 0;
while (oldLength < tempVisited.length)
{
oldLength = tempVisited.length;
for (var i = tempVisited.length - 1; i >= 0; i--)
{
if (this.dfs(tempVisited[i], tempVisited, tempEdge))
break;
}
}
// Format message
for (var i = 0; i < tempVisited.length; i ++)
{
tempVisited[i].upText = (i + 1) + "";
message = message + tempVisited[i].mainText + " ";
}
return message;
}
DFSAlgorithm.prototype.getPriority = function()
{
return -9.5;
}
DFSAlgorithm.prototype.getCategory = function()
{
return 1;
}
DFSAlgorithm.prototype.step = function()
{
for (var i = this.visited.length - 1; i >= 0; i--)
{
if (this.dfs(this.visited[i], this.visited, this.edges))
{
this.app.redrawGraph();
return;
}
}
clearTimeout(this.timer);
this.timer = null;
return;
}
DFSAlgorithm.prototype.dfs = function(vertex, vertexArray, edgeArray)
{
for (var i = 0; i < this.graph.vertices.length; i ++)
{
var nextVertex = this.graph.vertices[i];
var edge = this.graph.FindEdgeAny(vertex.id, nextVertex.id);
if (edge && !vertexArray.includes(nextVertex))
{
edgeArray.push(edge);
vertexArray.push(nextVertex);
return true;
}
}
return false;
}
// Algorithm support multi graph
DFSAlgorithm.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateDFSAlgorithm(graph, app)
{
return new DFSAlgorithm(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateDFSAlgorithm);

View File

@@ -0,0 +1,97 @@
/**
* 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 g_EulerinLoopName;//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.getCategory = function()
{
return 1;
}
FindEulerianLoop.prototype.result = function(resultCallback)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("elloop", [], function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
}, true);
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) ? "&rArr;" : "");
}
}
this.outResultCallback(outputResult);
}
FindEulerianLoop.prototype.getObjectSelectedGroup = function(object)
{
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
}
FindEulerianLoop.prototype.getPriority = function()
{
return -7.5;
}
// Factory for connected components.
function CreateFindEulerianLoop(graph, app)
{
return new FindEulerianLoop(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindEulerianLoop);

View File

@@ -0,0 +1,97 @@
/**
* Find Eulerian Path.
*
*/
function FindEulerianPath(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.message = g_processing;
this.selectedObjects = [];
}
// inheritance.
FindEulerianPath.prototype = Object.create(BaseAlgorithmEx.prototype);
FindEulerianPath.prototype.getName = function(local)
{
return g_EulerinPath;//local == "ru" ? "Найти Эйлерову цепь" : "Find Eulerian path";
}
FindEulerianPath.prototype.getId = function()
{
return "OlegSh.FindEulerianPath";
}
// @return message for user.
FindEulerianPath.prototype.getMessage = function(local)
{
return this.message;
}
FindEulerianPath.prototype.getCategory = function()
{
return 1;
}
FindEulerianPath.prototype.result = function(resultCallback)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("elpath", [], function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
}, true);
return true;
}
FindEulerianPath.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_hasEulerianPath : g_hasNotEulerianPath;
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) ? "&rArr;" : "");
}
}
this.outResultCallback(outputResult);
}
FindEulerianPath.prototype.getObjectSelectedGroup = function(object)
{
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
}
FindEulerianPath.prototype.getPriority = function()
{
return -7.5;
}
// Factory for connected components.
function CreateFindEulerianPath(graph, app)
{
return new FindEulerianPath(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindEulerianPath);

View File

@@ -0,0 +1,232 @@
/**
* Find short path.
*
*/
function FindAllPathes(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.message = g_selectStartVertex;
this.selectedObjects = {};
this.foundSubGraphs = {};
this.nSubgraphIndex = 0;
this.nSubGraphCount = 0;
this.foundPaths = {};
}
// inheritance.
FindAllPathes.prototype = Object.create(BaseAlgorithmEx.prototype);
// First selected.
FindAllPathes.prototype.firstObject = null;
// Second selected.
FindAllPathes.prototype.secondObject = null;
// Path
FindAllPathes.prototype.pathObjects = null;
// Infinity
FindAllPathes.prototype.infinityValue = 1E9 - 1;
FindAllPathes.prototype.getName = function(local)
{
return g_findAllPathes;
}
FindAllPathes.prototype.getId = function()
{
return "Abin.FindAllPathes";
}
// @return message for user.
FindAllPathes.prototype.getMessage = function(local)
{
return this.message;
}
FindAllPathes.prototype.getCategory = function()
{
return 1;
}
FindAllPathes.prototype.result = function(resultCallback)
{
if (this.firstObject && this.secondObject)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("prnpaths", [
{name: "start", value: this.firstObject.id},
{name: "finish", value: this.secondObject.id}
],
function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
}
return null;
}
FindAllPathes.prototype.setResultMessage = function()
{
if (this.nSubGraphCount > 0)
{
var currentPath = "";
var first = true;
this.foundPaths[this.nSubgraphIndex].forEach((nodeId) => {
currentPath += (first ? "" : "⇒") + this.graph.FindVertex(nodeId).mainText;
first = false;
});
this.message = g_numberOfPathesFrom + this.firstObject.mainText +
g_to + this.secondObject.mainText + g_are +
this.nSubGraphCount + ". " + g_pathN + (1 + parseInt(this.nSubgraphIndex)) + ": " + currentPath +
" <select style=\"float:right\" id=\"enumSubgraphs\"></select>";
}
else
{
this.message = g_pathNotExists;
}
}
FindAllPathes.prototype.resultCallback = function(pathObjects, properties, results)
{
var outputResult = {};
outputResult["version"] = 1;
outputResult["minPath"] = true;
this.pathObjects = pathObjects;
this.properties = properties;
var bFound = results.length > 0 && results[0].value < this.infinityValue && (results[0].type == 1 || results[0].type == 2);
if (bFound)
{
this.nSubGraphCount = results.length > 0 && results[0].type == 1 ? results[0].value : 0;
this.foundSubGraphs = {};
this.foundPaths = {};
for (var i = 0; i < this.nSubGraphCount; i++)
{
this.foundSubGraphs[i] = {};
this.foundPaths[i] = [];
}
var subGraphIndex = 0;
var prevNodeId = -1;
for (var i = 0; i < results.length; i++)
{
if (results[i].type == 6)
{
subGraphIndex++;
prevNodeId = -1;
}
if (results[i].type == 4)
{
var nodeId = parseInt(results[i].value);
var index = subGraphIndex;
var subgGraph = this.foundSubGraphs[index];
subgGraph[nodeId] = true;
this.foundPaths[index].push(nodeId);
if (prevNodeId >= 0)
{
var edgeObject = this.graph.FindEdgeMin(prevNodeId, nodeId);
subgGraph[edgeObject.id] = true;
}
prevNodeId = nodeId;
}
}
this.setResultMessage();
}
else
{
this.secondObject = null;
this.firstObject = null;
this.message = g_pathNotExists;
}
this.outResultCallback(outputResult);
}
FindAllPathes.prototype.messageWasChanged = function()
{
var self = this;
if ($('#enumSubgraphs'))
{
for (var i = 0; i < this.nSubGraphCount; i++)
{
$('#enumSubgraphs').append("<option value=\"" + i + "\"" + (self.nSubgraphIndex==i ? "selected": "") + ">" +
g_pathN + (i + 1) +
"</option>");
}
$('#enumSubgraphs').change(function () {
self.nSubgraphIndex = $('#enumSubgraphs').val();
self.setResultMessage();
self.app.redrawGraph();
self.app.updateMessage();
});
}
}
FindAllPathes.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_selectFinishVertex;
}
return true;
}
FindAllPathes.prototype.deselectAll = function()
{
this.firstObject = null;
this.secondObject = null;
this.selectedObjects = {};
this.foundSubGraphs = {};
this.nSubgraphIndex = 0;
this.nSubGraphCount = 0;
this.message = g_selectStartVertex;
return true;
}
FindAllPathes.prototype.instance = function()
{
return false;
}
FindAllPathes.prototype.getObjectSelectedGroup = function(object)
{
return (this.nSubgraphIndex in this.foundSubGraphs && object.id in this.foundSubGraphs[this.nSubgraphIndex]) ? 1 :
(object.id in this.selectedObjects) ? this.selectedObjects[object.id] : ((object == this.firstObject || object == object.secondObject) ? 1 : 0);
}
FindAllPathes.prototype.getPriority = function()
{
return -9.4;
}
// Factory for connected components.
function CreateFindAllPathes(graph, app)
{
return new FindAllPathes(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindAllPathes);

View File

@@ -0,0 +1,229 @@
/**
* Find short path.
*
*/
function FindLongestPath(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.message = g_selectStartVertex;
this.selectedObjects = {};
this.foundSubGraphs = {};
this.nSubgraphIndex = 0;
this.nSubGraphCount = 0;
this.foundPaths = {};
this.maxPathLength = 0;
}
// inheritance.
FindLongestPath.prototype = Object.create(BaseAlgorithmEx.prototype);
// First selected.
FindLongestPath.prototype.firstObject = null;
// Second selected.
FindLongestPath.prototype.secondObject = null;
// Path
FindLongestPath.prototype.pathObjects = null;
// Infinity
FindLongestPath.prototype.infinityValue = 1E9 - 1;
FindLongestPath.prototype.getName = function(local)
{
return g_findLongestPath;
}
FindLongestPath.prototype.getId = function()
{
return "OlegSh.FindLongestPath";
}
// @return message for user.
FindLongestPath.prototype.getMessage = function(local)
{
return this.message;
}
FindLongestPath.prototype.getCategory = function()
{
return 1;
}
FindLongestPath.prototype.result = function(resultCallback)
{
if (this.firstObject && this.secondObject)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("prnpaths", [
{name: "start", value: this.firstObject.id},
{name: "finish", value: this.secondObject.id}
],
function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
}
return null;
}
FindLongestPath.prototype.setResultMessage = function()
{
if (this.nSubGraphCount > 0)
{
var currentPath = "";
var first = true;
this.foundPaths[this.nSubgraphIndex].forEach((nodeId) => {
currentPath += (first ? "" : "⇒") + this.graph.FindVertex(nodeId).mainText;
first = false;
});
this.message = g_LengthOfLongestPathFrom + this.firstObject.mainText +
g_to + this.secondObject.mainText + g_are +
this.maxPathLength + ": " + currentPath;
}
else
{
this.message = g_pathNotExists;
}
}
FindLongestPath.prototype.resultCallback = function(pathObjects, properties, results)
{
var outputResult = {};
outputResult["version"] = 1;
outputResult["minPath"] = true;
this.pathObjects = pathObjects;
this.properties = properties;
var bFound = results.length > 0 && results[0].value < this.infinityValue && (results[0].type == 1 || results[0].type == 2);
if (bFound)
{
this.nSubGraphCount = results.length > 0 && results[0].type == 1 ? results[0].value : 0;
this.foundSubGraphs = {};
this.foundPaths = {};
this.maxPathLength = 0;
var maxPathIndex = 0;
var currentLength = 0;
for (var i = 0; i < this.nSubGraphCount; i++)
{
this.foundSubGraphs[i] = {};
this.foundPaths[i] = [];
}
var subGraphIndex = 0;
var prevNodeId = -1;
for (var i = 0; i < results.length; i++)
{
if (results[i].type == 6)
{
if (currentLength > this.maxPathLength) {
this.maxPathLength = currentLength;
maxPathIndex = subGraphIndex;
}
currentLength = 0;
subGraphIndex++;
prevNodeId = -1;
}
if (results[i].type == 4)
{
var nodeId = parseInt(results[i].value);
var index = subGraphIndex;
var subgGraph = this.foundSubGraphs[index];
subgGraph[nodeId] = true;
this.foundPaths[index].push(nodeId);
if (prevNodeId >= 0)
{
var edgeObject = this.graph.FindEdgeMax(prevNodeId, nodeId);
subgGraph[edgeObject.id] = true;
currentLength += edgeObject.GetWeight();
}
prevNodeId = nodeId;
}
}
if (currentLength > this.maxPathLength) {
this.maxPathLength = currentLength;
maxPathIndex = subGraphIndex;
}
this.nSubgraphIndex = maxPathIndex;
this.setResultMessage();
this.firstObject = null;
this.secondObject = null;
}
else
{
this.secondObject = null;
this.firstObject = null;
this.message = g_pathNotExists;
}
this.outResultCallback(outputResult);
}
FindLongestPath.prototype.selectVertex = function(vertex)
{
this.pathObjects = null;
this.shortDist = null;
if (this.firstObject)
{
this.message = g_processing;
this.secondObject = vertex;
this.selectedObjects = [];
}
else
{
this.deselectAll();
this.firstObject = vertex;
this.secondObject = null;
this.selectedObjects = {};
this.message = g_selectFinishVertex;
}
return true;
}
FindLongestPath.prototype.deselectAll = function()
{
this.firstObject = null;
this.secondObject = null;
this.selectedObjects = {};
this.foundSubGraphs = {};
this.nSubgraphIndex = 0;
this.nSubGraphCount = 0;
this.message = g_selectStartVertex;
this.maxPathLength = 0;
return true;
}
FindLongestPath.prototype.instance = function()
{
return false;
}
FindLongestPath.prototype.getObjectSelectedGroup = function(object)
{
return (this.nSubgraphIndex in this.foundSubGraphs && object.id in this.foundSubGraphs[this.nSubgraphIndex]) ? 1 :
(object.id in this.selectedObjects) ? this.selectedObjects[object.id] : ((object == this.firstObject || object == object.secondObject) ? 1 : 0);
}
FindLongestPath.prototype.getPriority = function()
{
return -9.4;
}
// Factory for connected components.
function CreateFindLongestPath(graph, app)
{
return new FindLongestPath(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindLongestPath);

View File

@@ -0,0 +1,219 @@
/**
* Find short path.
*
*/
function FindShortPatchsFromOne(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.message = g_selectStartVertex;
this.selectedObjects = {};
this.foundSubGraphs = {};
this.nSubgraphIndex = 0;
this.nSubGraphCount = 0;
this.lastVertexInPath = [];
this.lengthOfPath = [];
}
// inheritance.
FindShortPatchsFromOne.prototype = Object.create(BaseAlgorithmEx.prototype);
// First selected.
FindShortPatchsFromOne.prototype.firstObject = null;
// Path
FindShortPatchsFromOne.prototype.pathObjects = null;
// Infinity
FindShortPatchsFromOne.prototype.infinityValue = 1E9 - 1;
FindShortPatchsFromOne.prototype.getName = function(local)
{
return g_findAllPathesFromVertex;
}
FindShortPatchsFromOne.prototype.getId = function()
{
return "Abin.FindShortPatchsFromOne";
}
// @return message for user.
FindShortPatchsFromOne.prototype.getMessage = function(local)
{
return this.message;
}
FindShortPatchsFromOne.prototype.getCategory = function()
{
return 1;
}
FindShortPatchsFromOne.prototype.result = function(resultCallback)
{
if (this.firstObject)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("blf", [
{name: "start", value : this.firstObject.id}
], function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
}
return null;
}
FindShortPatchsFromOne.prototype.setResultMessage = function()
{
if (this.nSubGraphCount > 0)
{
this.message = g_distanceFrom + this.firstObject.mainText +
g_to + this.lastVertexInPath[this.nSubgraphIndex] + g_are +
this.lengthOfPath[this.nSubgraphIndex] + " <select style=\"float:right\" id=\"enumSubgraphs\"></select>";
}
else
{
this.message = g_pathNotExists;
}
}
FindShortPatchsFromOne.prototype.resultCallback = function(pathObjects, properties, results)
{
var outputResult = {};
outputResult["version"] = 1;
outputResult["minPath"] = true;
this.pathObjects = pathObjects;
this.properties = properties;
var bFound = results.length > 0 && results[0].value < this.infinityValue && (results[0].type == 1 || results[0].type == 2);
if (bFound)
{
this.nSubGraphCount = results.length > 0 && results[0].type == 1 ? results[0].value : 0;
this.foundSubGraphs = {};
for (var i = 0; i < this.nSubGraphCount; i++)
{
this.foundSubGraphs[i] = {};
this.lengthOfPath.push(0);
this.lastVertexInPath.push(0);
}
var subGraphIndex = 0;
var prevNodeId = -1;
for (var i = 0; i < results.length; i++)
{
if (results[i].type == 6)
{
subGraphIndex++;
prevNodeId = -1;
}
if (results[i].type == 4)
{
var nodeId = parseInt(results[i].value);
var index = subGraphIndex;
var subgGraph = this.foundSubGraphs[index];
subgGraph[nodeId] = true;
var vertex = this.graph.FindVertex(nodeId);
this.lastVertexInPath[index] = vertex != null ? vertex.mainText : "";
if (prevNodeId >= 0)
{
var edgeObject = this.graph.FindEdgeMin(prevNodeId, nodeId);
subgGraph[edgeObject.id] = true;
this.lengthOfPath[index] += edgeObject.GetWeight();
}
prevNodeId = nodeId;
}
}
this.setResultMessage();
}
else
{
this.firstObject = null;
this.message = g_pathNotExists;
}
this.outResultCallback(outputResult);
}
FindShortPatchsFromOne.prototype.messageWasChanged = function()
{
var self = this;
if ($('#enumSubgraphs'))
{
for (var i = 0; i < this.nSubGraphCount; i++)
{
$('#enumSubgraphs').append("<option value=\"" + i + "\"" + (self.nSubgraphIndex==i ? "selected": "") + ">" +
g_pathTo + this.lastVertexInPath[i] +
"</option>");
}
$('#enumSubgraphs').change(function () {
self.nSubgraphIndex = $('#enumSubgraphs').val();
self.app.redrawGraph();
self.setResultMessage();
});
}
}
FindShortPatchsFromOne.prototype.selectVertex = function(vertex)
{
this.pathObjects = null;
this.shortDist = null;
this.deselectAll();
this.firstObject = vertex;
this.selectedObjects = {};
this.message = "Processing...";
return true;
}
FindShortPatchsFromOne.prototype.deselectAll = function()
{
this.firstObject = null;
this.selectedObjects = {};
this.foundSubGraphs = {};
this.nSubgraphIndex = 0;
this.nSubGraphCount = 0;
this.message = g_selectStartVertex;
this.lastVertexInPath = [];
this.lengthOfPath = [];
return true;
}
FindShortPatchsFromOne.prototype.instance = function()
{
return false;
}
FindShortPatchsFromOne.prototype.getObjectSelectedGroup = function(object)
{
return (this.nSubgraphIndex in this.foundSubGraphs && object.id in this.foundSubGraphs[this.nSubgraphIndex]) ? 1 :
(object.id in this.selectedObjects) ? this.selectedObjects[object.id] : ((object == this.firstObject || object == object.secondObject) ? 1 : 0);
}
FindShortPatchsFromOne.prototype.getPriority = function()
{
return -9.4;
}
// Algorithm support multi graph
FindShortPatchsFromOne.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateFindShortPatchsFromOne(graph, app)
{
return new FindShortPatchsFromOne(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindShortPatchsFromOne);

View File

@@ -0,0 +1,235 @@
/**
* Find short path.
*
*/
function FloidAlgorithm(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.selectedObjects = {};
this.matrix = [];
this.updateMessage(false);
this.edgesCopy = [];
}
// inheritance.
FloidAlgorithm.prototype = Object.create(BaseAlgorithmEx.prototype);
// First selected.
FloidAlgorithm.prototype.firstObject = null;
// Second selected.
FloidAlgorithm.prototype.secondObject = null;
// Path
FloidAlgorithm.prototype.pathObjects = null;
// infinity
FloidAlgorithm.prototype.infinity = 1E8;
FloidAlgorithm.prototype.getName = function(local)
{
return g_FloidName; //local == "ru" ? "Алгоритм Флойда — Уоршелла" : "FloydWarshall algorithm";
}
FloidAlgorithm.prototype.getId = function()
{
return "OlegSh.FloidAlgorithm";
}
// @return message for user.
FloidAlgorithm.prototype.getMessage = function(local)
{
return this.message;
}
FloidAlgorithm.prototype.getCategory = function()
{
return 1;
}
FloidAlgorithm.prototype.result = function(resultCallback)
{
var result = {};
result["version"] = 1;
this.matrix = [];
this.resultMatrix();
//console.log(this.matrix);
// Remove all edges.
this.egdesCopy = this.graph.edges.slice();
this.removeAllEdges();
this.isGraphMulti = this.graph.isMulti();
this.graph.hasDirect = false;
// Added new edges
for (var i = 0; i < this.graph.vertices.length; i ++)
{
for (var j = 0; j < this.graph.vertices.length; j ++)
{
if (i != j)
{
var directed = (this.matrix[i][j] != this.matrix[j][i]);
if (this.matrix[i][j] < this.infinity && (directed || i < j))
{
this.graph.AddNewEdgeSafe(this.graph.vertices[i], this.graph.vertices[j], directed, this.matrix[i][j]);
}
}
}
}
this.app.redrawGraph();
return result;
}
FloidAlgorithm.prototype.resultMatrix = function()
{
this.matrix = [];
for (var i = 0; i < this.graph.vertices.length; i ++)
{
this.matrix.push([]);
var v1 = this.graph.vertices[i];
var str = "";
for (var j = 0; j < this.graph.vertices.length; j ++)
{
var v2 = this.graph.vertices[j];
var edge = this.graph.FindEdgeMin(v1.id, v2.id);
if (edge != null)
{
this.matrix[i][j] = edge.GetWeight();
}
else
{
this.matrix[i][j] = this.infinity;
}
}
}
for (var k = 0; k < this.graph.vertices.length; k ++)
for (var i = 0; i < this.graph.vertices.length; i ++)
for (var j = 0; j < this.graph.vertices.length; j ++)
{
if (this.matrix[i][j] > this.matrix[i][k] + this.matrix[k][j])
{
this.matrix[i][j] = this.matrix[i][k] + this.matrix[k][j];
}
}
return this.matrix;
}
FloidAlgorithm.prototype.getObjectSelectedGroup = function(object)
{
return 0;
}
FloidAlgorithm.prototype.messageWasChanged = function()
{
var self = this;
var matrixButton = document.getElementById("showFloidMatrix");
if (matrixButton)
{
matrixButton.onclick = function () {
var dialogButtons = {};
dialogButtons[g_close] = function() {
$( this ).dialog( "close" );
};
$( "#FloidMatrixField" ).val(self.GetFloidMatrix());
$( "#floidMatrix" ).dialog({
resizable: false,
height: "auto",
width: "auto",
modal: true,
title: g_minDistMatrixText,
buttons: dialogButtons,
dialogClass: 'EdgeDialog'
});
};
}
$('#saveFloidGraph').change(function() {
self.updateMessage(this.checked);
});
}
FloidAlgorithm.prototype.GetFloidMatrix = function()
{
return this.graph.GetAdjacencyMatrixStr();
}
FloidAlgorithm.prototype.changedType = function()
{
var enumReport = document.getElementById("enumReport");
this.app.SetCurrentValue("findShortPathReportType", enumReport.options[enumReport.selectedIndex].value);
this.updateUpText();
}
FloidAlgorithm.prototype.getPriority = function()
{
return 0;
}
FloidAlgorithm.prototype.removeAllEdges = function()
{
while (this.graph.edges.length > 0)
{
this.graph.DeleteEdge(this.graph.edges[0]);
}
}
FloidAlgorithm.prototype.wantRestore = function()
{
console.log($("#saveFloidGraph").is(':checked'));
return !$("#saveFloidGraph").is(':checked');
}
FloidAlgorithm.prototype.restore = function()
{
this.removeAllEdges();
this.graph.hasDirect = false;
console.log(this.egdesCopy);
for (var i = 0; i < this.egdesCopy.length; i ++)
{
var edgeIndex = this.graph.AddNewEdgeSafe(this.egdesCopy[i].vertex1,
this.egdesCopy[i].vertex2,
this.egdesCopy[i].isDirect,
this.egdesCopy[i].weight,
this.isGraphMulti);
var edge = this.graph.edges[edgeIndex];
edge.model.type = this.egdesCopy[i].model.type;
edge.model.curveValue = this.egdesCopy[i].model.curveValue;
//edge.model = this.egdesCopy[i].model;
}
}
FloidAlgorithm.prototype.updateMessage = function(save)
{
this.message = g_graphOfMinDist + " <label style=\"margin-bottom: 0px\">" + g_checkToSave + " <input id=\"saveFloidGraph\" type=\"checkbox\"" + (save ? "checked" : "") + "></label>" +
"<button type=\"button\" class=\"btn btn-default btn-xs\" id=\"showFloidMatrix\" style=\"float:right\">" + g_showDistMatrix + "</button>"
}
// Algorithm support multi graph
FloidAlgorithm.prototype.IsSupportMultiGraph = function ()
{
return true;
}
// Factory for connected components.
function CreateFloidAlgorithm(graph, app)
{
return new FloidAlgorithm(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFloidAlgorithm);

View File

@@ -0,0 +1,175 @@
/**
* Algorithm for reorder graph.
*
*/
function GraphReorder(graph, app)
{
BaseAlgorithm.apply(this, arguments);
if (graph != null)
{
this.edges = graph.edges;
this.vertices = graph.vertices;
}
}
// inheritance.
GraphReorder.prototype = Object.create(BaseAlgorithm.prototype);
GraphReorder.prototype.getName = function(local)
{
return g_GraphReorder; //local == "ru" ? "Упорядочить граф" : "Arrange the graph";
}
GraphReorder.prototype.getId = function()
{
return "OlegSh.GraphReorder";
}
// @return message for user.
GraphReorder.prototype.getMessage = function(local)
{
return g_done;
}
GraphReorder.prototype.result = function(resultCallback)
{
var result = {};
result["version"] = 1;
if (this.vertices.length == 0)
{
return result;
}
var velocityDamping = 0.85;
var diameter = (new VertexModel()).diameter;
var maxDistance = diameter * 3;
var gravityDistanceSqr = 10 * (maxDistance * maxDistance);
var edgeGravityKof = 10 / (maxDistance);
var kCenterForce = 10 / (maxDistance * 10);
//var centerPoint = viewportSize.multiply(0.5);
var velocityMax = maxDistance * 10;
var centerPoint = new Point();
for(i = 0; i < this.vertices.length; i++) // loop through vertices
{
centerPoint.add(this.vertices[i].position);
}
centerPoint.multiply(1.0 / this.vertices.length);
var edgesMatrix = {};
for (var i = 0; i < this.edges.length; i++)
{
edgesMatrix[this.edges[i].vertex1.id + this.edges[i].vertex2.id * 1000] = 1;
edgesMatrix[this.edges[i].vertex2.id + this.edges[i].vertex1.id * 1000] = 1;
}
var k = 0;
var bChanged = true;
while (k < 1000 && bChanged)
{
var vertexData = [];
for(i = 0; i < this.vertices.length; i++) // loop through vertices
{
// Has no in newVertices.
var currentVertex = {};
currentVertex.object = this.vertices[i];
currentVertex.net_force = new Point (0, 0);
currentVertex.velocity = new Point (0, 0);
vertexData.push(currentVertex);
for(j = 0; j < this.vertices.length; j++) // loop through other vertices
{
otherVertex = this.vertices[j];
if (otherVertex == currentVertex.object) continue;
// squared distance between "u" and "v" in 2D space
var rsq = currentVertex.object.position.distanceSqr(otherVertex.position);
{
// counting the repulsion between two vertices
var force = (currentVertex.object.position.subtract(otherVertex.position)).normalize(gravityDistanceSqr / rsq);
currentVertex.net_force = currentVertex.net_force.add(force);
}
}
for(j = 0; j < this.vertices.length; j++) // loop through edges
{
otherVertex = this.vertices[j];
if (edgesMatrix.hasOwnProperty(currentVertex.object.id + 1000 * otherVertex.id))
{
var distance = currentVertex.object.position.distance(otherVertex.position);
if (distance > maxDistance)
{
// countin the attraction
var force = (otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof * (distance - maxDistance));
currentVertex.net_force = currentVertex.net_force.add(force);
}
}
}
// Calculate force to center of world.
var distanceToCenter = centerPoint.distance(currentVertex.object.position);
var force = centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter * kCenterForce);
currentVertex.net_force = currentVertex.net_force.add(force);
// counting the velocity (with damping 0.85)
currentVertex.velocity = currentVertex.velocity.add(currentVertex.net_force);
}
bChanged = false;
for(i = 0; i < vertexData.length; i++) // set new positions
{
var v = vertexData[i];
var velocity = v.velocity;
if (velocity.length() > velocityMax)
{
velocity = velocity.normalize(velocityMax);
}
v.object.position = v.object.position.add(velocity);
if (velocity.length() >= 1)
{
bChanged = true;
}
}
k++;
}
this.app.OnAutoAdjustViewport();
this.app.SetHandlerMode("default");
// Looks like somthing going wrong and will use circle algorithm for reposition.
//var bbox = this.getGraphBBox();
return result;
}
GraphReorder.prototype.getObjectSelectedGroup = function(object)
{
return 0;
}
GraphReorder.prototype.getPriority = function()
{
return -8.5;
}
// Algorithm support multi graph
GraphReorder.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateAlgorithmGraphReorder(graph, app)
{
return new GraphReorder(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateAlgorithmGraphReorder);

View File

@@ -0,0 +1,114 @@
/**
* Find Eulerian Loop.
*
*/
function FindHamiltonianLoop(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.message = g_processing;
this.selectedObjects = [];
}
// inheritance.
FindHamiltonianLoop.prototype = Object.create(BaseAlgorithmEx.prototype);
FindHamiltonianLoop.prototype.getName = function(local)
{
return g_HamiltoianCycleName; //local == "ru" ? "Найти Гамильтонов цикл" : "Find Hamiltonian cycle";
}
FindHamiltonianLoop.prototype.getId = function()
{
return "OlegSh.FindHamiltonianLoop";
}
// @return message for user.
FindHamiltonianLoop.prototype.getMessage = function(local)
{
return this.message;
}
FindHamiltonianLoop.prototype.getCategory = function()
{
return 1;
}
FindHamiltonianLoop.prototype.result = function(resultCallback)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("hamloop", [], function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
return true;
}
FindHamiltonianLoop.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_hasHamiltonianLoop : g_hasNotHamiltonianLoop;
if (result > 0)
{
var nodesEdgesPath = this.GetNodesEdgesPath(results, 1, results.length - 1);
var nodesPath = this.GetNodesPath(results, 1, results.length - 1);
this.message = this.message + ": ";
if (this.graph.isMulti())
{
outputResult["pathsWithEdges"] = [];
outputResult["pathsWithEdges"].push(nodesEdgesPath);
}
else
{
outputResult["paths"] = [];
outputResult["paths"].push(nodesEdgesPath);
}
for (var i = 0; i < nodesPath.length; i++)
{
this.message = this.message + this.graph.FindVertex(nodesPath[i]).mainText + ((i < nodesPath.length - 1) ? "&rArr;" : "");
}
this.selectedObjects = [];
for (var i = 0; i < pathObjects.length; i++)
{
this.selectedObjects[pathObjects[i].id] = 1;
}
}
this.outResultCallback(outputResult);
}
FindHamiltonianLoop.prototype.getObjectSelectedGroup = function(object)
{
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
}
FindHamiltonianLoop.prototype.getPriority = function()
{
return -5;
}
// Algorithm support multi graph
FindHamiltonianLoop.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateFindHamiltonianLoop(graph, app)
{
return new FindHamiltonianLoop(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindHamiltonianLoop);

View File

@@ -0,0 +1,112 @@
/**
* Find Eulerian Loop.
*
*/
function FindHamiltonianPath(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.message = g_processing;
this.selectedObjects = [];
}
// inheritance.
FindHamiltonianPath.prototype = Object.create(BaseAlgorithmEx.prototype);
FindHamiltonianPath.prototype.getName = function(local)
{
return g_HamiltonianPath;//local == "ru" ? "Найти Гамильтонову цепь" : "Find Hamiltonian path";
}
FindHamiltonianPath.prototype.getId = function()
{
return "OlegSh.FindHamiltonianPath";
}
// @return message for user.
FindHamiltonianPath.prototype.getMessage = function(local)
{
return this.message;
}
FindHamiltonianPath.prototype.getCategory = function()
{
return 1;
}
FindHamiltonianPath.prototype.result = function(resultCallback)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("hampath", [], function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
return true;
}
FindHamiltonianPath.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_hasHamiltonianPath : g_hasNotHamiltonianPath;
if (result > 0)
{
var nodesEdgesPath = this.GetNodesEdgesPath(results, 1, results.length - 1);
var nodesPath = this.GetNodesPath(results, 1, results.length - 1);
if (this.graph.isMulti())
{
outputResult["pathsWithEdges"] = [];
outputResult["pathsWithEdges"].push(nodesEdgesPath);
}
else
{
outputResult["paths"] = [];
outputResult["paths"].push(nodesEdgesPath);
}
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) ? "&rArr;" : "");
}
}
this.outResultCallback(outputResult);
}
FindHamiltonianPath.prototype.getObjectSelectedGroup = function(object)
{
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
}
FindHamiltonianPath.prototype.getPriority = function()
{
return -5;
}
FindHamiltonianPath.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateFindHamiltonianPath(graph, app)
{
return new FindHamiltonianPath(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindHamiltonianPath);

View File

@@ -0,0 +1,299 @@
/**
* Find short path.
*
*/
function IsomorphismCheck(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
if (graph && app)
{
this.connectedComponent = new FindConnectedComponentNew(graph, app);
this.connectedComponent.calculate();
}
this.setFirstMessage();
this.prevCalculated = false;
this.searchSubGraphs = false;
this.foundSubGraphs = {};
this.nSubgraphIndex = 0;
this.nSubGraphCount = 0;
this.bIsomorph = false;
}
// inheritance.
IsomorphismCheck.prototype = Object.create(BaseAlgorithmEx.prototype);
// First selected.
IsomorphismCheck.prototype.firstGraph = null;
// Second selected.
IsomorphismCheck.prototype.secondGraph = null;
IsomorphismCheck.prototype.getName = function(local)
{
return g_IsomorphismCheck;
}
IsomorphismCheck.prototype.getId = function()
{
return "OlegSh.IsomorphismCheck";
}
// @return message for user.
IsomorphismCheck.prototype.getMessage = function(local)
{
return this.message;
}
IsomorphismCheck.prototype.result = function(resultCallback)
{
if (this.firstGraph && this.secondGraph)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
var params = [
{name : "graph1", value: this.getGraphEdges(this.firstGraph)},
{name : "graph2", value: this.getGraphEdges(this.secondGraph)},
];
if (this.searchSubGraphs) {
params.push({name: "searchSubgraphs", value: true});
}
this.CalculateAlgorithm("isocheck", params, function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
}
return null;
}
IsomorphismCheck.prototype.getGraphEdges = function(nodesAndEdges)
{
var res = ""
for (var key in nodesAndEdges)
{
var edgeObject = this.graph.FindEdgeById(key);
if (edgeObject)
{
if (res != "")
res = res + ","
res = res + edgeObject.vertex1.id + "-" + edgeObject.vertex2.id;
}
}
return res;
}
IsomorphismCheck.prototype.resultCallback = function(pathObjects, properties, results)
{
var outputResult = {};
outputResult["version"] = 1;
if (!this.searchSubGraphs)
{
this.bIsomorph = results.length > 0 && results[0].type == 1 && results[0].value == 1;
this.setResultMessage();
}
else
{
this.nSubGraphCount = results.length > 0 && results[0].type == 1 ? results[0].value : 0;
this.setResultMessage();
this.foundSubGraphs = {};
for (var i = 0; i < this.nSubGraphCount; i++)
{
this.foundSubGraphs[i] = {};
}
var subGraphIndex = 0;
for (var i = 0; i < results.length; i++)
{
if (results[i].type == 6)
{
subGraphIndex++;
}
if (results[i].type == 5)
{
var edgeId = parseInt(results[i].value);
var index = subGraphIndex;
var subgGraph = this.foundSubGraphs[index];
subgGraph[edgeId] = true;
var edgeObject = this.graph.FindEdgeById(edgeId);
subgGraph[edgeObject.vertex1.id] = true;
subgGraph[edgeObject.vertex2.id] = true;
}
}
}
this.prevCalculated = true;
this.outResultCallback(outputResult);
}
IsomorphismCheck.prototype.selectVertex = function(vertex)
{
if (this.connectedComponent && this.connectedComponent.connectedComponentNumber <= 1)
return true;
if (this.firstGraph && !this.prevCalculated && (!this.firstGraph || !(vertex.id in this.firstGraph)))
{
this.message = g_processing;
this.secondGraph = this.getGraphWithNode(vertex);
}
else
{
this.deselectAll();
this.firstGraph = this.getGraphWithNode(vertex);
this.secondGraph = null;
this.setSecondMessage();
this.app.updateMessage();
}
return true;
}
IsomorphismCheck.prototype.deselectAll = function()
{
this.firstGraph = null;
this.secondGraph = null;
this.prevCalculated = false;
this.setFirstMessage();
this.restore();
this.foundSubGraphs = {};
this.nSubgraphIndex = 0;
this.nSubGraphCount = 0;
this.bIsomorph = false;
this.app.updateMessage();
return true;
}
IsomorphismCheck.prototype.instance = function()
{
return false;
}
IsomorphismCheck.prototype.getObjectSelectedGroup = function(object)
{
return (this.nSubgraphIndex in this.foundSubGraphs && object.id in this.foundSubGraphs[this.nSubgraphIndex]) ? 3 :
(this.firstGraph && object.id in this.firstGraph) ? 1 : ((this.secondGraph && object.id in this.secondGraph) ? 2 : 0);
}
IsomorphismCheck.prototype.getPriority = function()
{
return -8.0;
}
IsomorphismCheck.prototype.getGraphWithNode = function(node)
{
var res = {}
if (node.id in this.connectedComponent.component)
{
var componentNumber = this.connectedComponent.component[node.id];
for (var key in this.connectedComponent.component)
{
if (this.connectedComponent.component[key] == componentNumber)
{
res[key] = true;
}
}
}
return res;
}
IsomorphismCheck.prototype.setFirstMessage = function()
{
if (this.connectedComponent && this.connectedComponent.connectedComponentNumber <= 1)
{
this.message = g_graphHasNoAtleast2Graphs;
return;
}
if (!this.searchSubGraphs)
this.message = g_selectFirstGraphIsomorphismCheck + "<input id=\"searchSubGraph\" type=\"checkbox\" " + (this.searchSubGraphs ? "checked": "")+ " style=\"float:right\">" + "<label style=\"margin-bottom: 0px;float:right\">" + g_searchIsomorphSubgraph + "&nbsp; </label>";
else
this.message = g_selectFirstGraphPatternCheck + "<input id=\"searchSubGraph\" type=\"checkbox\" " + (this.searchSubGraphs ? "checked": "")+ " style=\"float:right\">" + "<label style=\"margin-bottom: 0px;float:right\">" + g_searchIsomorphSubgraph + "&nbsp; </label>";
}
IsomorphismCheck.prototype.setSecondMessage = function()
{
if (!this.searchSubGraphs)
this.message = g_selectSecondGraphIsomorphismCheck + "<input id=\"searchSubGraph\" type=\"checkbox\" " + (this.searchSubGraphs ? "checked": "")+ " style=\"float:right\">" + "<label style=\"margin-bottom: 0px;float:right\">" + g_searchIsomorphSubgraph + "&nbsp; </label>";
else
this.message = g_selectSecondGraphForSearchSubgraph + "<input id=\"searchSubGraph\" type=\"checkbox\" " + (this.searchSubGraphs ? "checked": "")+ " style=\"float:right\">" + "<label style=\"margin-bottom: 0px;float:right\">" + g_searchIsomorphSubgraph + "&nbsp; </label>";
}
IsomorphismCheck.prototype.setResultMessage = function()
{
if (!this.searchSubGraphs)
{
if (this.bIsomorph)
{
this.message = g_graphsIsomorph;
}
else
{
this.message = g_graphsNotIsomorph;
}
}
else
{
if (this.nSubGraphCount > 0)
{
this.message = g_numberOfIsomorphSubgraphIs + this.nSubGraphCount + " <select style=\"float:right\" id=\"enumSubgraphs\"></select>";
}
else
{
this.message = g_graphHasNoIsomorphSubgraph;
}
}
}
IsomorphismCheck.prototype.messageWasChanged = function()
{
var self = this;
if ($('#searchSubGraph'))
{
$('#searchSubGraph').change(function() {
self.searchSubGraphs = this.checked;
if (self.firstGraph && !self.prevCalculated)
self.setSecondMessage();
else
self.setFirstMessage();
self.app.updateMessage();
});
}
if ($('#enumSubgraphs'))
{
for (var i = 0; i < this.nSubGraphCount; i++)
{
$('#enumSubgraphs').append("<option value=\"" + i + "\"" + (self.nSubgraphIndex==i ? "selected": "") + ">" +
g_subgraphNo + (i + 1) +
"</option>");
}
$('#enumSubgraphs').change(function () {
self.nSubgraphIndex = $('#enumSubgraphs').val();
self.app.redrawGraph();
self.setResultMessage();
});
}
}
// Factory for connected components.
function CreateIsomorphismCheck(graph, app)
{
return new IsomorphismCheck(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateIsomorphismCheck);

View File

@@ -0,0 +1,100 @@
/**
* Find Eulerian Loop.
*
*/
function MaxClique(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.message = g_processing;
this.selectedObjects = [];
}
// inheritance.
MaxClique.prototype = Object.create(BaseAlgorithmEx.prototype);
MaxClique.prototype.getName = function(local)
{
return g_MaxClique;
}
MaxClique.prototype.getId = function()
{
return "OlegSh.MaxClique";
}
// @return message for user.
MaxClique.prototype.getMessage = function(local)
{
return this.message;
}
MaxClique.prototype.result = function(resultCallback)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("mc", [], function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
return true;
}
MaxClique.prototype.resultCallback = function(pathObjects, properties, results)
{
result = results.length > 0 && results[0].value > 0 && results[0].type == 1;
var outputResult = {};
outputResult["version"] = 1;
console.log("properties");
console.log(properties);
console.log("results");
console.log(results);
console.log("pathObjects");
console.log(pathObjects);
this.message = result > 0 ? "" : g_MaxCliqueNotFound;
if (result > 0)
{
let size = results[0].value;
this.message = g_MaxCliqueSizeIs + size;
this.selectedObjects = [];
this.message = this.message + g_MaxCliqueContains;
var vertexIndex = 0;
for (var i = 0; i < pathObjects.length; i++)
{
let object = pathObjects[i];
if (object instanceof BaseVertex) {
this.message = this.message + object.mainText + ((vertexIndex < size - 1) ? ", " : ".");
vertexIndex++;
}
this.selectedObjects[object.id] = 1;
}
}
this.outResultCallback(outputResult);
}
MaxClique.prototype.getObjectSelectedGroup = function(object)
{
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : 0;
}
MaxClique.prototype.getPriority = function()
{
return -5;
}
function CreateMaxClique(graph, app)
{
return new MaxClique(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateMaxClique);

View File

@@ -0,0 +1,227 @@
/**
* Find short path.
*
*/
function FindMaxFlow(graph, app)
{
BaseAlgorithmEx.apply(this, arguments);
this.message = g_selectStartVertexForMaxFlow;
this.selectedObjects = {};
this.selectedEdges = [];
this.resetUpText = [];
this.minEdgeSize = 2;
this.maxEdgeSize = 12;
}
// inheritance.
FindMaxFlow.prototype = Object.create(BaseAlgorithmEx.prototype);
// First selected.
FindMaxFlow.prototype.firstObject = null;
// Second selected.
FindMaxFlow.prototype.secondObject = null;
// Path
FindMaxFlow.prototype.selectedEdges = null;
FindMaxFlow.prototype.getName = function(local)
{
return g_MaxFlowName; //local == "ru" ? "Поиск максимального потока" : "Find Maximum flow";
}
FindMaxFlow.prototype.getId = function()
{
return "OlegSh.FindMaxFlow";
}
// @return message for user.
FindMaxFlow.prototype.getMessage = function(local)
{
return this.message;
}
FindMaxFlow.prototype.result = function(resultCallback)
{
if (this.firstObject && this.secondObject)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("mfpr",
[
{name: "source", value: this.firstObject.id},
{name: "drain", value: this.secondObject.id}
],
function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
}
return null;
}
FindMaxFlow.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) && results[0].value * 1 > 0.0;
var maxFlow = results[0].value * 1;
if (bFound)
{
this.selectedObjects = {};
var defaultDiameter = (new EdgeModel()).width;
var avgFlow = 0;
var countEdges = 0;
for (var i = 0; i < pathObjects.length; i++)
{
if (pathObjects[i] instanceof BaseEdge)
{
avgFlow += properties[pathObjects[i].id]["flowValue"] * 1;
countEdges += 1;
}
}
avgFlow = avgFlow / countEdges;
for (var i = 0; i < pathObjects.length; i++)
{
if (pathObjects[i] instanceof BaseEdge)
{
this.selectedObjects[pathObjects[i].id] = 1;
var flow = properties[pathObjects[i].id]["flowValue"] * 1;
if (pathObjects[i].useWeight || flow != pathObjects[i].GetWeight())
{
pathObjects[i].text = flow + " / " + pathObjects[i].GetWeight();
}
if (!pathObjects[i].isDirect)
{
if (parseInt(properties[pathObjects[i].id]["backToFront"]) > 0)
{
pathObjects[i].arrayStyleStart = "arrow";
}
else
{
pathObjects[i].arrayStyleFinish = "arrow";
}
}
pathObjects[i].model.width = Math.max(Math.min((flow / avgFlow) * defaultDiameter, this.maxEdgeSize), this.minEdgeSize);
}
}
this.selectedEdges = pathObjects;
this.message = g_maxFlowResult.replace("%1", (maxFlow).toString()).replace("%2", this.firstObject.mainText).replace("%3", this.secondObject.mainText);
this.selectedObjects[this.secondObject.id] = 3;
this.selectedObjects[this.firstObject.id] = 1;
this.secondObject.upText = g_sinkVertex;
this.resetUpText.push(this.secondObject);
}
else
{
this.message = g_flowNotExists.toString().replace("%1", this.firstObject.mainText).replace("%2", this.secondObject.mainText);
}
this.secondObject = null;
this.firstObject = null;
this.outResultCallback(outputResult);
}
FindMaxFlow.prototype.selectVertex = function(vertex)
{
this.pathObjects = null;
this.shortDist = null;
if (this.firstObject)
{
this.message = g_processing;
this.secondObject = vertex;
this.selectedObjects = [];
}
else
{
this.restore();
this.firstObject = vertex;
this.secondObject = null;
this.selectedObjects = {};
this.message = g_selectFinishVertexForMaxFlow;
this.firstObject.upText = g_sourceVertex;
this.resetUpText.push(this.firstObject);
}
return true;
}
FindMaxFlow.prototype.deselectAll = function()
{
this.firstObject = null;
this.secondObject = null;
this.selectedObjects = {};
this.message = g_selectStartVertexForMaxFlow;
this.restore();
return true;
}
FindMaxFlow.prototype.instance = function()
{
return false;
}
FindMaxFlow.prototype.getObjectSelectedGroup = function(object)
{
return (object.id in this.selectedObjects) ? this.selectedObjects[object.id] : ((object == this.firstObject || object == object.secondObject) ? 1 : 0);
}
FindMaxFlow.prototype.getPriority = function()
{
return -8.0;
}
// @return true, if you change resotry graph after use.
BaseAlgorithm.prototype.wantRestore = function()
{
return true;
}
// calls this method if wantRestore return true.
BaseAlgorithm.prototype.restore = function()
{
if (this.selectedEdges != null)
{
for (var i = 0; i < this.selectedEdges.length; i++)
{
if (this.selectedEdges[i] instanceof BaseEdge)
{
this.selectedEdges[i].text = "";
this.selectedEdges[i].arrayStyleStart = "";
this.selectedEdges[i].arrayStyleFinish = "";
this.selectedEdges[i].model.width = (new EdgeModel()).width;
}
}
for (var i = 0; i < this.resetUpText.length; i++)
{
this.resetUpText[i].upText = "";
}
}
}
// Factory for connected components.
function CreateFindMaxFlow(graph, app)
{
return new FindMaxFlow(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindMaxFlow);

View File

@@ -0,0 +1,167 @@
function MinimumSpanningTree(graph, app)
{
BaseAlgorithm.apply(this, arguments);
this.isNotConnected = false;
this.MST = 0;
this.edges = [];
}
// inheritance.
MinimumSpanningTree.prototype = Object.create(BaseAlgorithm.prototype);
MinimumSpanningTree.prototype.getName = function(local)
{
return g_minimumSpanningTree; //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.isNotConnected )
{
return g_SpanningTreeResult + this.MST + ". " +
(this.graph.hasDirectEdge() ? g_SpanningTreeIgnoreDir : "");
}
else
{
return g_SpanningTreeNotConnected;
}
}
MinimumSpanningTree.prototype.result = function(resultCallback)
{
this.MST = 0;
this.edges = [];
this.isNotConnected = true;
var tempVertices = this.graph.vertices.slice();
connectedVertex = getVertexToVertexArray(this.graph, true);
// We ignore orientation for this algorithm.
//if (!this.graph.hasDirectEdge())
{
res = this.resultStartedFrom(tempVertices[0], connectedVertex);
this.isNotConnected = res.isNotConnected;
if (!this.isNotConnected)
{
this.MST = res.MST;
this.edges = res.edges;
}
}
/*else
{
for (var i = 0; i < tempVertices.length; i++)
{
res = this.resultStartedFrom(tempVertices[i], connectedVertex);
if (!res.isNotConnected)
{
this.isNotConnected = res.isNotConnected;
if (this.MST == 0 || res.MST < this.MST)
{
console.log(res);
this.MST = res.MST;
this.edges = res.edges;
}
}
}
}*/
var result = {};
result["version"] = 1;
result["minPath"] = true;
return result;
}
MinimumSpanningTree.prototype.resultStartedFrom = function(vertex, connectedVertex)
{
var res = {};
res.MST = 0;
res.edges = [];
res.isNotConnected = 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.FindEdgeMinIgnoreDirection(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.isNotConnected = (inTree.length < this.graph.vertices.length);
return res;
}
MinimumSpanningTree.prototype.getObjectSelectedGroup = function(object)
{
return this.isNotConnected ? 0 :
(object instanceof BaseVertex || this.edges.indexOf(object) >= 0) ? 1 : 0;
}
MinimumSpanningTree.prototype.getPriority = function()
{
return -9.3;
}
// Algorithm support multi graph
MinimumSpanningTree.prototype.IsSupportMultiGraph = function ()
{
return true;
}
// Factory for algorithm.
function CreateMinimumSpanningTree(graph, app)
{
return new MinimumSpanningTree(graph)
}
// Register connected component.
RegisterAlgorithm (CreateMinimumSpanningTree);

View File

@@ -0,0 +1,198 @@
/**
* Algorithm for modern style of graph.
*
*/
function ModernGraphStyle(graph, app)
{
BaseAlgorithm.apply(this, arguments);
this.minVertexSize = 20;
this.maxVertexSize = 100;
this.minEdgeSize = 2;
this.maxEdgeSize = 12;
}
// inheritance.
ModernGraphStyle.prototype = Object.create(BaseAlgorithm.prototype);
ModernGraphStyle.prototype.getName = function(local)
{
return g_modernGraphStyleName;// local == "ru" ? "Визуализация на основе весов" : "Visualisation based on weight";
}
ModernGraphStyle.prototype.getId = function()
{
return "OlegSh.ModernGraphStyle";
}
// @return message for user.
ModernGraphStyle.prototype.getMessage = function(local)
{
return g_done;
}
ModernGraphStyle.prototype.result = function(resultCallback)
{
var result = {};
result["version"] = 1;
this.vertexVisualization2();
this.edgeVisualization();
return result;
}
ModernGraphStyle.prototype.vertexVisualization = function()
{
var degree = getVertexToVertexArray(this.graph, false);
var graph = this.graph;
var maxDegree = 0;
var sumDegree = 0;
var sumOfDiameters = graph.vertices.length * (new VertexModel()).diameter;
// Search max vertex degree.
for (var i = 0; i < graph.vertices.length; i++)
{
var vertex = graph.vertices[i];
if (degree.hasOwnProperty(vertex.id))
{
var currentDegree = degree[vertex.id].length;
maxDegree = Math.max(maxDegree, currentDegree);
sumDegree = sumDegree + currentDegree;
}
}
for (var i = 0; i < graph.vertices.length; i++)
{
var vertex = graph.vertices[i];
if (degree.hasOwnProperty(vertex.id))
{
var currentDegree = degree[vertex.id].length;
//vertex.model.diameter = (currentDegree / maxDegree) * (this.maxVertexSize - this.minVertexSize) + this.minVertexSize;
vertex.model.diameter = Math.max(Math.min((currentDegree / sumDegree) * sumOfDiameters, this.maxVertexSize), this.minVertexSize);
//sumOfDiameters
}
else
{
vertex.model.diameter = this.minVertexSize;
}
}
}
ModernGraphStyle.prototype.vertexVisualization2 = function()
{
var degree = {};
var graph = this.graph;
var sumDegree = 0;
var sumOfDiameters = graph.vertices.length * (new VertexModel()).diameter;
// Search max vertex degree.
for (var i = 0; i < graph.edges.length; i++)
{
var edge = graph.edges[i];
if (!degree.hasOwnProperty(edge.vertex1.id))
{
degree[edge.vertex1.id] = 0;
}
if (!degree.hasOwnProperty(edge.vertex2.id))
{
degree[edge.vertex2.id] = 0;
}
var currentWeight = 0;
if (edge.isDirect)
{
currentWeight = edge.GetWeight() / 2;
}
else
{
currentWeight = edge.GetWeight();
}
sumDegree = sumDegree + 2 * currentWeight;
degree[edge.vertex1.id] += currentWeight;
degree[edge.vertex2.id] += currentWeight;
}
console.log("sumDegree = " + sumDegree);
for (var i = 0; i < graph.vertices.length; i++)
{
var vertex = graph.vertices[i];
if (degree.hasOwnProperty(vertex.id))
{
var currentDegree = degree[vertex.id];
console.log(currentDegree / sumDegree);
vertex.model.diameter = Math.max(Math.min((currentDegree / sumDegree) * sumOfDiameters, this.maxVertexSize), this.minVertexSize);
//sumOfDiameters
}
else
{
vertex.model.diameter = this.minVertexSize;
}
}
}
ModernGraphStyle.prototype.edgeVisualization = function()
{
var graph = this.graph;
var maxEdgeWeight = 0;
var sumWeight = 0;
var sumOfDiameters = graph.edges.length * (new EdgeModel()).width;
// Search max edge weight.
for (var i = 0; i < graph.edges.length; i++)
{
var edge = graph.edges[i];
if (edge.useWeight)
{
maxEdgeWeight = Math.max(maxEdgeWeight, edge.weight);
sumWeight = sumWeight + edge.weight;
}
}
// Search max edge weight.
if (maxEdgeWeight != 0)
{
for (var i = 0; i < graph.edges.length; i++)
{
var edge = graph.edges[i];
if (edge.useWeight)
{
//edge.model.width = (edge.weight / maxEdgeWeight) * (this.maxEdgeSize - this.minEdgeSize) + this.minEdgeSize;
edge.model.width = Math.max(Math.min((edge.weight / sumWeight) * sumOfDiameters, this.maxEdgeSize), this.minEdgeSize);
}
else
{
edge.model.width = this.minEdgeSize;
}
}
}
}
ModernGraphStyle.prototype.getObjectSelectedGroup = function(object)
{
return 0;
}
// Algorithm support multi graph
ModernGraphStyle.prototype.IsSupportMultiGraph = function()
{
return true;
}
// Factory for connected components.
function CreateAlgorithmModernGraphStyle(graph, app)
{
return new ModernGraphStyle(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateAlgorithmModernGraphStyle);

View File

@@ -0,0 +1,231 @@
/**
* Algorithm for reorder graph.
*
*/
function RadiusAndDiameter(graph, app)
{
BaseAlgorithm.apply(this, arguments);
this.diameter = 0;
this.radius = 0;
this.diameterSelectedObjects = [];
this.radiusSelectedObjects = [];
this.centerVertices = [];
this.peripheralVertices = [];
this.isNotConnected = false;
this.isOneVertex = false;
}
// inheritance.
RadiusAndDiameter.prototype = Object.create(BaseAlgorithm.prototype);
RadiusAndDiameter.prototype.getName = function(local)
{
return g_RadiusAndDiameter;
}
RadiusAndDiameter.prototype.getId = function()
{
return "OlegSh.RadiusAndDiameter";
}
// @return message for user.
RadiusAndDiameter.prototype.getMessage = function(local)
{
if (this.isNotConnected)
{
return g_graphIsDisconnected;
}
if (this.isOneVertex)
{
return g_graphIsTrivial;
}
var text = g_graphRadius + ": " + this.radius;
text = text + " (";
for (i = 0; i < this.radiusSelectedObjects.length; i++)
{
if (this.radiusSelectedObjects[i] instanceof BaseVertex)
{
text = text + this.radiusSelectedObjects[i].mainText + ((i < this.radiusSelectedObjects.length - 1) ? "&rArr;" : "");
}
}
text = text + ").";
text = text + " " + g_graphDiameter + ": " + this.diameter;
text = text + " (";
for (i = 0; i < this.diameterSelectedObjects.length; i++)
{
if (this.diameterSelectedObjects[i] instanceof BaseVertex)
{
text = text + this.diameterSelectedObjects[i].mainText + ((i < this.diameterSelectedObjects.length - 1) ? "&rArr;" : "");
}
}
text = text + ").";
return text;
}
RadiusAndDiameter.prototype.result = function(resultCallback)
{
var result = {};
result["version"] = 1;
if (this.graph.vertices.length == 1)
{
this.isOneVertex = true;
return;
}
var connectedComponents = new FindConnectedComponentNew(this.graph, this.app);
var connectedComponentNumber = connectedComponents.calculate();
if (connectedComponentNumber == 1)
{
var floid = new FloidAlgorithm(this.graph, this.app);
var matrix = floid.resultMatrix();
this.diameter = -1;
var diameterStart = 0;
var diameterFinish = 0;
this.radius = 1E10;
var radiusStart = 0;
var radiusFinish = 0;
var eccentricity = [];
for (var i = 0; i < matrix.length; i++)
{
var vertex = -1;//(i == 0 ? 1 : 0);
var vertexEccentricity = -1;//matrix[i][vertex];
for (var j = 0; j < matrix[i].length; j++)
{
if (vertexEccentricity < matrix[i][j] && i != j && matrix[i][j] != floid.infinity)
{
vertexEccentricity = matrix[i][j];
vertex = j;
}
}
var res = {value: vertexEccentricity, vertex: vertex};
eccentricity.push(res);
}
for (var i = 0; i < eccentricity.length; i++)
{
var vertexEccentricity = eccentricity[i].value;
if (vertexEccentricity < 0)
{
continue;
}
if (this.radius > vertexEccentricity)
{
this.radius = vertexEccentricity;
radiusStart = i;
radiusFinish = eccentricity[i].vertex;
}
if (this.diameter < vertexEccentricity)
{
this.diameter = vertexEccentricity;
diameterStart = i;
diameterFinish = eccentricity[i].vertex;
}
}
for (var i = 0; i < eccentricity.length; i++)
{
var vertexEccentricity = eccentricity[i].value;
if (vertexEccentricity < 0)
{
continue;
}
if (eccentricity[i].value == this.radius)
{
this.centerVertices.push(this.graph.vertices[i].id);
this.graph.vertices[i].upText = g_vertexCentral;
}
if (eccentricity[i].value == this.diameter)
{
this.peripheralVertices.push(this.graph.vertices[i].id);
this.graph.vertices[i].upText = g_vertexPeripheral;
}
}
this.diameterSelectedObjects = this.getPathByMatrix(this.graph.GetAdjacencyMatrix(), matrix, diameterStart, diameterFinish, this.diameter);
this.radiusSelectedObjects = this.getPathByMatrix(this.graph.GetAdjacencyMatrix(), matrix, radiusStart, radiusFinish, this.radius);
}
else
{
this.isNotConnected = true;
}
return result;
}
RadiusAndDiameter.prototype.getPathByMatrix = function(adjacencyMatrix, minPathMatrix, startNode, finishNode, length)
{
var res = [];
vertices = this.graph.vertices;
while (length != adjacencyMatrix[startNode][finishNode])
{
for (var i = 0; i < adjacencyMatrix.length; i ++)
{
if (minPathMatrix[i][finishNode] == length - adjacencyMatrix[startNode][i] && i != startNode)
{
res.push(vertices[startNode]);
res.push(this.graph.FindEdgeMin(vertices[startNode].id, vertices[i].id));
length -= adjacencyMatrix[startNode][i];
startNode = i;
break;
}
}
}
res.push(vertices[startNode]);
res.push(this.graph.FindEdgeMin(vertices[startNode].id, vertices[finishNode].id));
res.push(vertices[finishNode]);
return res;
}
RadiusAndDiameter.prototype.getObjectSelectedGroup = function(object)
{
var res = (this.diameterSelectedObjects.includes(object)) ? 1 : 0;
res = (this.radiusSelectedObjects.includes(object)) ? 2 : res;
//res = (this.centerVertices.includes(object.id)) ? 3 : res;
//res = (this.peripheralVertices.includes(object.id)) ? 4 : res;
return res;
}
RadiusAndDiameter.prototype.getPriority = function()
{
return 0;
}
// Algorithm support multi graph
RadiusAndDiameter.prototype.IsSupportMultiGraph = function ()
{
return true;
}
// Factory for connected components.
function CreateAlgorithmRadiusAndDiameter(graph, app)
{
return new RadiusAndDiameter(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateAlgorithmRadiusAndDiameter);

View File

@@ -0,0 +1,232 @@
/**
* 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;
// Infinity
FindShortPathNew.prototype.infinityValue = 1E9 - 1;
FindShortPathNew.prototype.getName = function(local)
{
return g_findShortPathName; //local == "ru" ? "Поиск кратчайший путь алгоритмом Дейкстры" : "Find shortest path using Dijkstra's algorithm";
}
FindShortPathNew.prototype.getId = function()
{
return "OlegSh.FindShortestPath";
}
// @return message for user.
FindShortPathNew.prototype.getMessage = function(local)
{
return this.message;
}
FindShortPathNew.prototype.getCategory = function()
{
return 1;
}
FindShortPathNew.prototype.result = function(resultCallback)
{
if (this.firstObject && this.secondObject)
{
this.outResultCallback = function (result ) { resultCallback(result); };
self = this;
this.CalculateAlgorithm("dsp",
[
{name: "start", value: this.firstObject.id},
{name: "finish", value: this.secondObject.id}
], function (pathObjects, properties, results)
{
self.resultCallback(pathObjects, properties, results);
});
}
return null;
}
FindShortPathNew.prototype.resultCallback = function(pathObjects, properties, results)
{
var outputResult = {};
outputResult["version"] = 1;
outputResult["minPath"] = true;
this.pathObjects = pathObjects;
this.properties = properties;
var bFound = results.length > 0 && results[0].value < this.infinityValue && (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) ? "&rArr;" : "");
}
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 > this.infinityValue ? "\u221E" : (propertie.lowestDistance * 1).toString());
}
}
}
}
else
{
for (var i = 0; i < this.graph.vertices.length; i++)
{
this.graph.vertices[i].upText = "";
}
}
}
FindShortPathNew.prototype.getPriority = function()
{
return -10;
}
// Algorithm support multi graph
FindShortPathNew.prototype.IsSupportMultiGraph = function ()
{
return true;
}
// Factory for connected components.
function CreateFindShortPathNew(graph, app)
{
return new FindShortPathNew(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateFindShortPathNew);

View File

@@ -0,0 +1,102 @@
/**
* 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 g_VerticesDegreeName; //local == "ru" ? "Рассчитать степень вершин" : "Calculate vertices degree";
}
VerticesDegree.prototype.getId = function()
{
return "OlegSh.VertexDegree";
}
// @return message for user.
VerticesDegree.prototype.getMessage = function(local)
{
return g_maximumDegreeOfGraph + " " + this.maxDegree;
}
VerticesDegree.prototype.result = function(resultCallback)
{
this.degree = {};
this.maxDegree = 0;
var result = {};
result["version"] = 1;
var graph = this.graph;
var thisObj = this;
var addDegreeToVertex = function (id)
{
if (thisObj.degree.hasOwnProperty(id))
{
thisObj.degree[id] ++;
currentDegree = thisObj.degree[id];
thisObj.maxDegree = Math.max(thisObj.maxDegree, currentDegree);
}
else
{
thisObj.degree[id] = 1;
}
}
for (var i = 0; i < graph.edges.length; i++)
{
var edge = graph.edges[i];
var currentDegree = 0;
addDegreeToVertex(edge.vertex1.id);
if (!edge.isDirect)
{
addDegreeToVertex(edge.vertex2.id);
}
}
for (var i = 0; i < graph.vertices.length; i++)
{
var vertex = graph.vertices[i];
if (!this.degree.hasOwnProperty(vertex.id))
{
this.degree[vertex.id] = 0;
}
vertex.upText = this.degree[vertex.id];
}
return result;
}
VerticesDegree.prototype.getObjectSelectedGroup = function(object)
{
return (this.degree.hasOwnProperty(object.id)) ? this.degree[object.id]: 0;
}
// Algorithm support multi graph
VerticesDegree.prototype.IsSupportMultiGraph = function ()
{
return true;
}
// Factory for connected components.
function CreateAlgorithmVerticesDegree(graph, app)
{
return new VerticesDegree(graph, app)
}
// Gerister connected component.
RegisterAlgorithm (CreateAlgorithmVerticesDegree);

View File

@@ -0,0 +1,117 @@
/**
* Default handler.
* Select using mouse, drag.
*
*/
function NeedAlgorithm(graph, app)
{
BaseAlgorithm.apply(this, arguments);
}
// inheritance.
NeedAlgorithm.prototype = Object.create(BaseAlgorithm.prototype);
NeedAlgorithm.prototype.getName = function(local)
{
return local == "ru" ? "Не нашли нужный алгоритм?" : "Didn't you find the algorithm you need?";
}
NeedAlgorithm.prototype.getId = function()
{
return "OlegSh.NeedAlgorithm";
}
// @return message for user.
NeedAlgorithm.prototype.getMessage = function(local)
{
return local == "ru" ? "Спасибо" : "Thank you";
}
NeedAlgorithm.prototype.result = function(resultCallback)
{
/*
var dialogButtons = {};
dialogButtons[g_send] = function() {
console.log("Message" + $( "#NeedAlgorithmMessage" ).val());
$.ajax({
type: "GET",
url: "/cgi-bin/sendEmail.php?text=" + $( "#NeedAlgorithmMessage" ).val(),
dataType: "text"
});
$( this ).dialog( "close" );
};
dialogButtons[g_close] = function() {
$( this ).dialog( "close" );
};
$( "#NeedAlgorithm" ).dialog({
resizable: false,
title: g_recommendAlgorithm,
width: 400,
modal: true,
dialogClass: 'EdgeDialog',
buttons: dialogButtons,
});
*/
var dialogButtons = {};
for (var i = 0; i < 6 && document.getElementById('vote' + i) !== null; i++)
{
document.getElementById('vote' + i)["voteIndex"] = i;
document.getElementById('vote' + i).onclick = function ()
{
console.log("Vote" + this["voteIndex"]);
$.ajax({
type: "GET",
url: "/" + SiteDir + "cgi-bin/vote.php?index=" + this["voteIndex"],
dataType: "text"
});
$("#voteDialog").dialog('close');
$("#VoteButton").hide();
}
}
dialogButtons[g_close] = function() {
$( this ).dialog( "close" );
};
$( "#voteDialog" ).dialog({
resizable: false,
title: g_vote,
width: 400,
modal: true,
dialogClass: 'EdgeDialog',
buttons: dialogButtons,
});
var result = {};
result["version"] = 1;
return result;
}
NeedAlgorithm.prototype.getObjectSelectedGroup = function(object)
{
return 0;
}
NeedAlgorithm.prototype.getPriority = function()
{
return 100;
}
// Factory for connected components.
function CreateNeedAlgorithm(graph, app)
{
return new NeedAlgorithm(graph)
}
// Gerister connected component.
RegisterAlgorithm (CreateNeedAlgorithm);