-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathAnt.scala
97 lines (76 loc) · 2.56 KB
/
Ant.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import scala.util.Random
import Params._
class Ant(val inst: Instance) extends Solver {
val rnd = new Random()
/**
* el valor heurístico de distancia entre nodo y v
*/
def η(nodo: Customer, v: Customer, h: Double): Double = {
inst.tau(nodo, v) / inst.tiempo(nodo, v, h)
}
def proximo(nodo: Customer, vecinos: List[Customer],
hora: Double, capacidad: Int): Customer = {
//println("-----------------\ndesde " + nodo.num)
// filtro los que llego a tiempo y me alcanza la capacidad
val insertables = vecinos.filter(vecino => insertable(nodo, vecino, hora, capacidad))
//println("insertables: " + insertables.map(_.num))
//val tau = insertables.foldLeft(Map[Customer, Double]()) {
// (m, v) => m(v) = inst.tau(nodo, v)
//}
//println("tau("+nodo.num+") | " + tau.map( p => (p._1.num, p._2)).toList.filter(_._2 > 0))
if (insertables.isEmpty) {
null
}
else {
// un mapa [Customer, Double] con (tau*η^β) precalculado
val mapη = insertables.foldLeft(Map[Customer, Double]()) {
(m, v) => m(v) = η(nodo, v, hora)
}
//println("mapη = " + mapη.map( p => (p._1.num, p._2)).toList.filter(_._2 > 0 ))
// obtengo el mayor η
val values = mapη.values.toList
val bestη = values.tail.foldLeft(values.head){ (a,b) => if (a > b) a else b }
val bests = insertables.filter(mapη(_) == bestη)
val q = rnd.nextDouble
if (q < q0) {
// exploitation
//println("exploitation")
// si hay varios con el mismo η, obtengo el que cierra antes
if (bests.length > 1) {
val best = bests.tail.foldLeft(bests.head) { (a,b) => if (a.due < b.due) a else b }
//println("best = " + best.num)
best
}
else {
//println("bests.head = " + bests.head.num)
bests.head
}
}
else {
// exploration
//println("exploration")
// el denominador
val Σ = mapη.values.reduceLeft(_+_)
// construyo una lista de (Customer, proba)
val probas = (mapη.map(t => (t._1, mapη(t._1) / Σ)) toList)// filter(_._2 > 0)
//println("probas = " + probas.map( p => (p._1.num, p._2)) )
val ret = weightedCases(probas)
//println("elijo: " + ret.num)
ret
}
}
}
def weightedCases[A](inp: List[(A, Double)]): A = {
def coinFlip[A](p: Double)(a1: A, a2: A) = {
if (rnd.nextDouble() < p) a1 else a2
}
def coinFlips[A](w: Double)(l: List[(A,Double)]): A = {
l match {
case Nil => error("no coinFlips")
case (d, _) :: Nil => d
case (d, p) :: rest => coinFlip(p/(1.0-w))(d, coinFlips(w+p)(rest))
}
}
coinFlips(0)(inp)
}
}