maia-markov
Version:
Markov analysis and generation functions supporting various applications by Music Artificial Intelligence Algorithms, Inc.
283 lines (246 loc) • 7.36 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = Graph;
var _Vertex = require('./Vertex');
var _Vertex2 = _interopRequireDefault(_Vertex);
var _Edge = require('./Edge');
var _Edge2 = _interopRequireDefault(_Edge);
var _PriorityQueue = require('./PriorityQueue');
var _PriorityQueue2 = _interopRequireDefault(_PriorityQueue);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var mu = require('maia-util');
// Constructor for Graph object
// Imports
function Graph(arr, vtxStr, nbsStr, distStr) {
// If supplied with an input array, this constructor fills the graph with
// directed edges by default.
this.vertexMap = {};
// Workaround for JS context peculiarities.
var self = this;
if (arr !== undefined) {
arr.map(function (a) {
a[nbsStr].map(function (n) {
if (distStr !== undefined) {
self.add_directed_edge(a[vtxStr], n[vtxStr], n[distStr]);
} else {
self.add_directed_edge(a[vtxStr], n[vtxStr], 1);
}
});
});
}
// Possible to return something.
// return sth;
}
// Methods for Graph object
Graph.prototype = {
constructor: Graph,
add_edge: function add_edge(start, end, w) {
var u = this.get_vertex(start);
var v = this.get_vertex(end);
u.nbs.push(new _Edge2.default(u, v, w));
v.nbs.push(new _Edge2.default(v, u, w));
},
add_directed_edge: function add_directed_edge(start, end, w) {
var u = this.get_vertex(start);
var v = this.get_vertex(end);
u.nbs.push(new _Edge2.default(u, v, w));
},
get_vertex: function get_vertex(name) {
var v = this.vertexMap[name];
if (v == undefined) {
v = new _Vertex2.default(name);
this.vertexMap[name] = v;
}
return v;
},
get_neighbors: function get_neighbors(name) {
var v = this.vertexMap[name];
if (v == undefined) {
console.log("Error: start vertex not found.");
return;
}
return v.nbs.map(function (nb) {
return nb.v.name;
});
},
print_neighbors: function print_neighbors(name) {
var v = this.vertexMap[name];
if (v == undefined) {
console.log("Error: start vertex not found.");
return;
}
var str = "";
v.nbs.map(function (nb) {
str += nb.v.name + ", ";
});
return str;
},
// Could write one of these, because there's too much code copy/paste at the
// beginnings of bfs, dfs, and shortest_path below.
// prep_for_search: function(startName){}
// Untested breadth-first search
bfs: function bfs(startName) {
var startVertex = this.vertexMap[startName];
if (startVertex == undefined) {
console.log("Error: start vertex not found.");
return;
}
this.reset();
startVertex.dist = 0;
var dq = [startVertex];
var _loop = function _loop() {
var u = dq.shift();
console.log(u.name + " " + u.dist);
u.nbs.map(function (nb) {
var v = nb.v;
if (v.dist == Infinity) {
v.dist = u.dist + 1;
dq.push(v);
}
});
};
while (dq.length > 0) {
_loop();
}
},
// Untested depth-first search
dfs: function dfs(startName) {
var startVertex = this.vertexMap[startName];
if (startVertex == undefined) {
console.log("Error: start vertex not found.");
return;
}
this.reset();
startVertex.visited = true;
var dq = [startVertex];
while (dq.length > 0) {
var _u = dq.pop();
console.log(_u.name);
_u.nbs.map(function (nb) {
var v = nb.v;
if (!v.visited) {
v.visited = true;
dq.push(v);
}
});
}
},
// Untested recursive depth-first search
// No reseting here, which is a potential problem.
recursive_dfs: function recursive_dfs(u) {
u.visited = true;
console.log(u.name);
u.nbs.map(function (nb) {
var v = nb.v;
if (!v.visited) {
this.recursive_dfs(v);
}
});
},
shortest_path: function shortest_path(startName) {
var startVertex = this.vertexMap[startName];
if (startVertex == undefined) {
console.log("Error: start vertex not found.");
return;
}
this.reset();
var q = new _PriorityQueue2.default();
startVertex.dist = 0;
q.enqueue(startVertex.dist, startVertex);
// console.log("q:", q)
var _loop2 = function _loop2() {
var u = q.dequeue();
if (u.visited) return 'continue';
u.visited = true;
// console.log(u.name + " " + u.dist + " " + ((u.prev==null)?"":u.prev.name))
u.nbs.map(function (nb) {
var v = nb.v;
if (v.dist > u.dist + nb.w) {
q.heap.removeValue(v);
v.dist = u.dist + nb.w;
v.prev = u;
q.enqueue(v.dist, v);
}
});
};
while (!q.heap.isEmpty()) {
var _ret2 = _loop2();
if (_ret2 === 'continue') continue;
}
},
print_shortest_path: function print_shortest_path(startName, endName) {
this.shortest_path(startName);
var relVtx = this.get_vertex(endName);
if (!relVtx.visited) {
// These two vertices are not connected.
return;
}
var rv = [endName];
while (relVtx.prev !== null) {
rv.push(relVtx.prev.name);
relVtx = this.get_vertex(relVtx.prev.name);
}
return rv.reverse();
},
scenic_path: function scenic_path(startName, loveOfScenery) {
var startVertex = this.vertexMap[startName];
if (startVertex == undefined) {
console.log("Error: start vertex not found.");
return;
}
this.reset();
var q = new _PriorityQueue2.default();
startVertex.dist = 0;
q.enqueue(startVertex.dist, startVertex);
// console.log("q:", q)
var _loop3 = function _loop3() {
var u = q.dequeue();
if (u.visited) return 'continue';
u.visited = true;
// console.log(u.name + " " + u.dist + " " + ((u.prev==null)?"":u.prev.name))
u.nbs.map(function (nb) {
var v = nb.v;
if (
// The next line is intended to avoid the undefined error in beginning
// to construct the shortest path.
v.dist === Infinity ||
// If true, there's a better way to get to vertex v.
v.dist > u.dist + nb.w && Math.random() > loveOfScenery) {
// Update the heap with the more efficient route.
q.heap.removeValue(v);
v.dist = u.dist + nb.w;
v.prev = u;
q.enqueue(v.dist, v);
}
});
};
while (!q.heap.isEmpty()) {
var _ret3 = _loop3();
if (_ret3 === 'continue') continue;
}
},
print_scenic_path: function print_scenic_path(startName, endName, loveOfScenery) {
this.scenic_path(startName, loveOfScenery);
var relVtx = this.get_vertex(endName);
if (!relVtx.visited) {
// These two vertices are not connected.
return;
}
var rv = [endName];
while (relVtx.prev !== null) {
rv.push(relVtx.prev.name);
relVtx = this.get_vertex(relVtx.prev.name);
}
return rv.reverse();
},
reset: function reset() {
var self = this;
Object.keys(this.vertexMap).map(function (v) {
self.vertexMap[v].dist = Infinity;
self.vertexMap[v].visited = false;
self.vertexMap[v].prev = null;
});
}
};