我为JavaScript创建了A *算法。 重要的是,它必须搜索最长的路径而不是最短的路径。当路径搜索完成时,我只想获取路径的深度/长度。该算法仅返回最大长度而不是路径。
调试结果时,我认为该算法仅返回启发式的值。
我有带有id的舞台对象和活动对象,它们通过持有 fromId 和 toId 连接两个舞台。
示例:
我有状态对象的ID
和活动
我希望得到这样的结果:
但是我得到的结果是
为什么我可以使用A *作为最长路径?
那么A *比较距离并取下一个。它应该是 通过更改compare语句可以以更高的成本获得更长的距离。
我在这里提供一个工作代码示例
// #########################################
// My initializer script with some fake data
// #########################################
$(document).ready(() => {
const path = new Path(activities, 1);
for (let i = 0; i < stages.length; i++) {
const currentStage = stages[i];
const currentStageId = currentStage.id;
const currentDistance = path.getMaximumDistance(currentStage);
console.log(`id: ${currentStageId} distance: ${currentDistance}`);
}
});
const stages = [
new Stage(1),
new Stage(2),
new Stage(3),
new Stage(4),
new Stage(5)
];
function Stage(id) {
this.id = id;
}
const activities = [
new Activity(1, 2),
new Activity(1, 3),
new Activity(2, 3),
new Activity(3, 5),
new Activity(5, 1)
];
function Activity(fromId, toId) {
this.fromId = fromId;
this.toId = toId;
}
// #########################################
// The A* class
// #########################################
function Path(activities, initialId) {
this.getMaximumDistance = (targetStage) => {
var me = this;
var targetId = targetStage.id;
var openList = [];
var closedList = [];
this.addNodeToList(openList, this.createNode(initialId, this.activities));
let maxDistance = 0;
while (openList.length > 0) {
var currentNode = openList[this.getHighestCostIndex(openList)];
if (currentNode.id === targetId) {
maxDistance = this.getPathLength(currentNode);
break;
}
this.removeNodeFromList(openList, currentNode);
this.addNodeToList(closedList, currentNode);
currentNode.neighbourIds.forEach(id => {
var neighbour = me.createNode(id, me.activities);
let lookUpTableElement;
if (!me.listContainsNode(closedList, neighbour)) {
var tempIncrementalCost = currentNode.incrementalCost + 1;
if (me.listContainsNode(openList, neighbour)) {
if (tempIncrementalCost < neighbour.incrementalCost) {
neighbour.changeIncrementalCost(tempIncrementalCost);
}
} else {
neighbour.changeIncrementalCost(tempIncrementalCost);
me.addNodeToList(openList, neighbour);
}
for (var i = 0; i < me.lookUpTable.length; i++) {
var currentLookUpTableElement = me.lookUpTable[i];
if (currentLookUpTableElement.id === neighbour.id) {
lookUpTableElement = currentLookUpTableElement;
}
}
var heuristic = lookUpTableElement ? lookUpTableElement.cost : 0;
neighbour.changeHeuristic(heuristic);
neighbour.setParent(currentNode);
}
});
}
return maxDistance;
};
this.createNode = (id, activities) => {
return new PathNode(id, activities);
};
this.getHighestCostIndex = (openList) => {
let highestCostIndex = 0;
for (let i = 0; i < openList.length; i++) {
if (openList[i].totalCost > openList[highestCostIndex].totalCost) {
highestCostIndex = i;
}
}
return highestCostIndex;
};
this.addNodeToList = (list, node) => {
list.push(node);
};
this.listContainsNode = (list, node) => {
return list.some(x => x.id === node.id);
};
this.removeNodeFromList = (list, node) => {
var index = list.indexOf(node);
list.splice(index, 1);
};
this.getPathLength = (node) => {
let currentNode = node;
let counter = 0;
while (currentNode.parent) {
currentNode = currentNode.parent;
counter++;
}
return counter;
};
this.activities = activities;
this.lookUpTable = new LookUpTable(this.activities, initialId).table;
}
// #########################################
// Node class for the A*
// #########################################
function PathNode(id, activities) {
this.getNeighbourIds = (activities) => {
return activities
.filter(x => x.fromId === id)
.map(x => x.toId);
};
this.setParent = (parentNode) => {
this.parent = parentNode;
};
this.changeHeuristic = (heuristic) => {
this.heuristic = heuristic;
this.updateTotalCost();
};
this.changeIncrementalCost = (incrementalCost) => {
this.incrementalCost = incrementalCost;
this.updateTotalCost();
};
this.updateTotalCost = () => {
this.totalCost = this.incrementalCost + this.heuristic;
};
this.id = id;
this.heuristic = 0;
this.incrementalCost = 0;
this.totalCost = 0;
this.parent = null;
this.neighbourIds = this.getNeighbourIds(activities);
}
// #########################################
// The heuristic code
// #########################################
function LookUpTable(activities, originId) {
this.getLookUpTable = (originId) => {
const me = this;
const lookUpTable = [];
let currentLevel = 0;
let openList = [];
this.addStage(openList, originId, currentLevel);
while (openList.length > 0) {
var lookUpTableElements = openList.filter(openNode => openNode.cost <= currentLevel);
lookUpTableElements.forEach(lookUpTableElement => {
this.addStage(lookUpTable, lookUpTableElement.id, currentLevel);
var neighbours = activities.filter(targetActivity => targetActivity.fromId === lookUpTableElement.id);
neighbours.forEach(neighbour => {
var neighbourId = neighbour.toId === lookUpTableElement.id ? neighbour.fromId : neighbour.toId;
if (!lookUpTable.some(x => x.id === neighbourId) && !openList.some(x => x.id === neighbourId)) {
me.addStage(openList, neighbourId, currentLevel + 1);
}
});
});
openList = openList.filter(x => x.cost !== currentLevel);
currentLevel++;
}
return lookUpTable;
};
this.addStage = (array, stageId, level) => {
array.push({
id: stageId,
cost: level
});
};
this.activities = activities;
this.table = this.getLookUpTable(originId);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
我的A *算法有什么问题,它返回正确的启发式值而不是最大距离?
重要提示::如果有人对找到这些连接之间的最大距离有更好的主意,请告诉我!
答案 0 :(得分:4)
通常,无法调整最短路径算法以返回给定图中的(简单)最长路径。
另外,找到一个简单的(非循环的)Dynamic Feature Manifest。
在您的情况下,每条边的成本为1,不幸的是,这并没有改善。即使您知道可以到达所有顶点,也将最终搜索longest path is NP-hard,它是NP完全的。
我建议看看Hamilton Path中最长路径的问题。