From 40aa20bb7b50cf635a2be0148e10fe2302d778a4 Mon Sep 17 00:00:00 2001 From: baraa Date: Sat, 6 Mar 2021 17:45:13 +0200 Subject: [PATCH 1/3] - Implementing Tour class for node traversing --- Tour.js | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Tour.js diff --git a/Tour.js b/Tour.js new file mode 100644 index 0000000..b933799 --- /dev/null +++ b/Tour.js @@ -0,0 +1,105 @@ + +class Tour { + + constructor(theGraph) { + this.prey = 0; + this.stamina = 3 + this.graph = { ...theGraph } + this.tripPath = []; + } + + startTrip(theGraph) { + let graph = theGraph || this.graph; + this.tripPath = [] + /* visited contains the amount of boars on each node. */ + let visited = { + A: 3, + B: 3, + C: 3, + D: 3, + E: 3, + F: 3, + G: 3, + H: 3, + I: 3, + J: 3, + K: 3 + }; + /* queue contains the next node to explore */ + let queue = []; + let node = 'A'; + this.tripPath.push(node) + queue.push(node) + this.huntRoutine(visited, queue, node) + + while (queue.length != 0) { + node = queue.pop(); + if (!graph[node] || graph[node].length == 0) break; + let e = graph[node][0] + queue.push(e) + this.tripPath.push(e) + if (this.stamina < 3) { + this.restRoutine(visited, queue, e) + } else { + this.huntRoutine(visited, queue, e) + } + } + return this; + } + + restRoutine(visited, queue, e) { + this.stamina -= 1 + this.stamina += 2; + } + + huntRoutine(visited, queue, e) { + this.stamina -= 1 + + if (visited[e] == 1) { + visited[e] = visited[e] - 1; + this.prey += 1 + + } else if (visited[e] >= 2) { + visited[e] = visited[e] - 2; + this.prey += 2 + } + } + + changeTourRoute() { + let nameArr = Object.entries(this.graph).map(([key, val]) => key) + let rand = Math.floor(Math.random() * (nameArr.length - 1)); + let nodeTitle = nameArr[rand]; + let edges = this.graph[nodeTitle]; + + /* + * When shuffle edges for given node + * it will eventually simulate as if we go to different route when + * calling generate method. + */ + + this.graph[nodeTitle] = this.shuffle(edges); + return this; + } + + getTotalHunts() { + return this.prey; + } + + getTripPath() { + return this.tripPath; + } + + shuffle(arr) { + return [...arr].map((_, i, orgArr) => { + var rand = i + (Math.floor(Math.random() * (orgArr.length - i))); + [orgArr[rand], orgArr[i]] = [orgArr[i], orgArr[rand]] + return orgArr[i] + }) + } +} + +module.exports = Tour + + + + From abf1e64068f07c9172f5d2e71c6e4146245716f9 Mon Sep 17 00:00:00 2001 From: baraa Date: Sat, 6 Mar 2021 17:48:44 +0200 Subject: [PATCH 2/3] - Implemenging Simulated Annealing algorithm to find the best path with maximum hunts. --- SimulatedAnnealing.js | 58 +++++++++++++++++++++++++++++++++++++++++++ main.js | 38 ++++++++++++++++++---------- 2 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 SimulatedAnnealing.js diff --git a/SimulatedAnnealing.js b/SimulatedAnnealing.js new file mode 100644 index 0000000..58a1fed --- /dev/null +++ b/SimulatedAnnealing.js @@ -0,0 +1,58 @@ + +/*****************************************************************/ +/* This solution is utilizing on (Simulated Annealing) Algorithm */ +/****************************************************************/ + +const Tour = require('./Tour') + +const Params = { + MAX_TEMP: 10000, + MIN_TEMP: 1, + COOLING_RATE: 0.005 +} + +class SimulatedAnnealing { + + constructor(theGraph) { + this.graph = theGraph; + this.selectedTour = {}; + } + + simulate() { + let temp = Params.MAX_TEMP; + let currentTour = new Tour(this.graph); + currentTour.startTrip(); + + let bestTour = new Tour(this.graph) + bestTour.startTrip(); + + while (temp > Params.MIN_TEMP) { + let newTour = new Tour(this.graph); + newTour = newTour.changeTourRoute().startTrip(); + let currentEnergy = currentTour.getTotalHunts(); + let newEnergy = currentTour.getTotalHunts(); + if (this.acceptanceProbability(currentEnergy, newEnergy, temp) > Math.random()) + currentTour = newTour; + + if (currentEnergy > bestTour.getTotalHunts()) + bestTour = currentTour + + temp *= 1 - Params.COOLING_RATE; + } + this.selectedTour = bestTour; + return this; + } + + acceptanceProbability(currentEnergy, newEnergy, temp) { + if (newEnergy > currentEnergy) + return 1; + return Math.exp((currentEnergy - newEnergy) / temp) + } + + getSelectedTour() { + return this.selectedTour; + } + +} + +module.exports = SimulatedAnnealing diff --git a/main.js b/main.js index 7a5b4cb..ad6da7b 100644 --- a/main.js +++ b/main.js @@ -1,16 +1,28 @@ prey = 0 hunting_map = { - 'A':['B','C','K'], - 'B':['D','E'], - 'C':['E','G','H'], - 'D':['E','F'], - 'E':['G','I','F'], - 'F':['I','J'], - 'G':['I','K'], - 'H':['I','F'], - 'I':['K'], - 'J':['K'], - 'K':[] + 'A': ['B', 'C', 'K'], + 'B': ['D', 'E'], + 'C': ['E', 'G', 'H'], + 'D': ['E', 'F'], + 'E': ['G', 'I', 'F'], + 'F': ['I', 'J'], + 'G': ['I', 'K'], + 'H': ['I', 'F'], + 'I': ['K'], + 'J': ['K'], + 'K': [] }; -console.log(hunting_map); -console.log(prey); \ No newline at end of file +// console.log(hunting_map); +// console.log(prey); + + +let tourSimulation = new SimulatedAnnealing(hunting_map) + .simulate(); + +let tour = tourSimulation.getSelectedTour(); + +let selectTourPath = tour.getTripPath(); +let numberOfBoars = tour.getTotalHunts(); + +console.log(numberOfBoars) +console.log(selectTourPath.join(" ")) \ No newline at end of file From 148adc6207f7cd3d793970807580742eb5b9f5eb Mon Sep 17 00:00:00 2001 From: baraa Date: Sat, 6 Mar 2021 17:51:03 +0200 Subject: [PATCH 3/3] - importing SimulatedAnnealing class --- main.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.js b/main.js index ad6da7b..f4c8f95 100644 --- a/main.js +++ b/main.js @@ -1,3 +1,6 @@ + +const SimulatedAnnealing = require('./SimulatedAnnealing') + prey = 0 hunting_map = { 'A': ['B', 'C', 'K'],