Commit 57a9ebb0cf68e36878de75b234d6f50c5c665f1f
1 parent
2def30ad
Implement hidden Markov model
Showing
3 changed files
with
136 additions
and
14 deletions
Show diff stats
.gitignore
main.py
1 | - | |
2 | -from structure import RSSVector, Location, Cell, newCell, KNeighbors, resolve_barycenter | |
1 | +from structure import RSSVector, Location, Cell, newCell, KNeighbors, resolve_barycenter, MarkovModel, MarkovValue | |
3 | 2 | import sys |
4 | 3 | |
5 | 4 | Tf = [] #cells table |
... | ... | @@ -13,7 +12,7 @@ for i in range (0, 3): |
13 | 12 | for k in range (0,3): |
14 | 13 | Tf[i].append([]) |
15 | 14 | |
16 | -#known fingerprints | |
15 | +#known fingerprints | |
17 | 16 | Tf[0][0] = newCell(-38,-27,-54,-13,2,2) |
18 | 17 | Tf[0][1] = newCell(-74,-62,-48,-33,2,6) |
19 | 18 | Tf[0][2] = newCell(-13,-28,-12,-40,2,10) |
... | ... | @@ -39,6 +38,35 @@ def main(args): |
39 | 38 | print(a.toString()) |
40 | 39 | |
41 | 40 | #### Markov #### |
41 | + MM = MarkovModel(Tf) | |
42 | + """ | |
43 | + for a in range(0,3): | |
44 | + for b in range(0,3): | |
45 | + d = Location(Tf[a][b].location.x, Tf[a][b].location.y) | |
46 | + print(d.toString()) | |
47 | + print(d.getPositionInArray()) | |
48 | + """ | |
49 | + MM.moveToCellID(8) | |
50 | + MM.moveToCellID(7) | |
51 | + MM.moveToCellID(8) | |
52 | + MM.moveToCellID(7) | |
53 | + MM.moveToCellID(8) | |
54 | + MM.moveToCellID(7) | |
55 | + MM.moveToCellID(8) | |
56 | + MM.moveToCellID(5) | |
57 | + MM.moveToCellID(8) | |
58 | + MM.moveToCellID(2) | |
59 | + MM.moveToCellID(9) | |
60 | + MM.moveToCellID(8) | |
61 | + MM.moveToCellID(1) | |
62 | + MM.moveToCell(Tf[2][2]) | |
63 | + MM.moveToCellID(8) | |
64 | + MM.moveToCell(Tf[2][2]) | |
65 | + | |
66 | + MM.printValues() | |
67 | + print("") | |
68 | + MM.printPercentages() | |
42 | 69 | |
43 | - return 0 | |
70 | + print("\r\ncurrent cell is #" + str(MM.previousCell) + " , most likely next cell is #" + str(MM.getMostLikely()) + " which is located at " + str(Location.fromID(MM.getMostLikely()).toString())) | |
71 | + | |
44 | 72 | main(sys.argv) |
45 | 73 | \ No newline at end of file | ... | ... |
structure.py
1 | 1 | from operator import itemgetter as ig |
2 | +from math import floor | |
2 | 3 | |
3 | 4 | class RSSVector(): |
4 | 5 | distances = [] |
... | ... | @@ -9,20 +10,20 @@ class RSSVector(): |
9 | 10 | self.n4 = n4 |
10 | 11 | |
11 | 12 | class Location(): |
12 | - def __init(self): | |
13 | - self.x = self.y = self.z = 0 | |
14 | - | |
13 | + | |
15 | 14 | def __init__(self, x, y, z=0): |
16 | 15 | self.x = x |
17 | 16 | self.y = y |
18 | 17 | self.z = z |
19 | - | |
18 | + | |
19 | + | |
20 | 20 | def __mul__(self, multiplier): |
21 | 21 | returnValue = Location(self.x, self.y, self.z) |
22 | 22 | returnValue.x *= multiplier |
23 | 23 | returnValue.y *= multiplier |
24 | 24 | returnValue.z *= multiplier |
25 | 25 | return returnValue |
26 | + | |
26 | 27 | def __rmul__(self, multiplier): |
27 | 28 | return self * multiplier |
28 | 29 | |
... | ... | @@ -33,16 +34,109 @@ class Location(): |
33 | 34 | returnValue.z += added.z |
34 | 35 | return returnValue |
35 | 36 | |
37 | + def __isub__(self, value): | |
38 | + return self + -1 * value | |
39 | + | |
40 | + def __itruediv__(self, divider): | |
41 | + returnValue = Location(self.x, self.y, self.z) | |
42 | + returnValue.x /= divider | |
43 | + returnValue.y /= divider | |
44 | + returnValue.z /= divider | |
45 | + return returnValue | |
46 | + | |
36 | 47 | def toString(self): |
37 | 48 | return "(" + str(self.x) + " ; " + str(self.y) + " ; " + str(self.z) + ")" |
38 | 49 | |
50 | + def getPositionInArray(self, arraySize=3): | |
51 | + temp = Location(self.x, self.y) | |
52 | + temp /= 2 | |
53 | + temp -= Location(1,1) | |
54 | + return floor((temp.x * arraySize + temp.y)/2) | |
55 | + | |
56 | + @staticmethod | |
57 | + def fromID(id, arraySize=3): | |
58 | + id -= 1 | |
59 | + y=id % 3 | |
60 | + x=floor((id - y) / 3) | |
61 | + returnValue = Location(x, y) | |
62 | + returnValue *= 2 | |
63 | + returnValue += Location(1,1) | |
64 | + returnValue *= 2 | |
65 | + return returnValue | |
39 | 66 | |
40 | 67 | class Cell(): |
41 | 68 | def __init__(self, v_, loc): |
42 | 69 | self.v = v_ |
43 | 70 | self.location = loc |
44 | - self.Likeliness = .0 # Probability of Markov model | |
45 | - self.pastCount = 1 | |
71 | + | |
72 | +class MarkovValue(): | |
73 | + def __init__(self, nb=0, percentage=0): | |
74 | + self.nb = nb | |
75 | + self.percentage = percentage # Probability of Markov model (100% <=> 1.0) | |
76 | + self.attachedCell = None | |
77 | + | |
78 | +class MarkovModel(): | |
79 | + def __init__(self,cells): | |
80 | + self.MarkovValues = [] #table of the coefficients of the Markov Model | |
81 | + self.cells = cells | |
82 | + self.previousCell = 0 | |
83 | + for i in range (0, 11): | |
84 | + self.MarkovValues.append([]) | |
85 | + for k in range (0, 10): | |
86 | + self.MarkovValues[i].append(MarkovValue()) | |
87 | + | |
88 | + | |
89 | + def moveToCellID(self, nextCell): | |
90 | + self.MarkovValues[self.previousCell][nextCell].nb += 1 | |
91 | + self.MarkovValues[10][nextCell].nb += 1 | |
92 | + self.MarkovValues[self.previousCell][nextCell].percentage = self.MarkovValues[self.previousCell][nextCell].nb /self.MarkovValues[10][nextCell].nb | |
93 | + self.previousCell = nextCell | |
94 | + | |
95 | + def moveToCell(self, nextCell): | |
96 | + self.moveToCellID(nextCell.location.getPositionInArray()+1) | |
97 | + | |
98 | + def printValues(self): | |
99 | + print("\t? \t1 \t2 \t3\t4 \t5 \t6 \t7 \t8 \t9") | |
100 | + print("---------------------------------------------------------------------------------", end='') | |
101 | + | |
102 | + for i in range (0, 11): | |
103 | + print("\r\n", end='') | |
104 | + if i == 10 or i == 1: | |
105 | + print("---------------------------------------------------------------------------------\r\n",end='') | |
106 | + | |
107 | + print(i, end='\t') | |
108 | + for k in range (0,10): | |
109 | + print(self.MarkovValues[i][k].nb, end='\t') | |
110 | + print("") | |
111 | + | |
112 | + def printPercentages(self): | |
113 | + print("\t? \t1 \t2 \t3\t4 \t5 \t6 \t7 \t8 \t9") | |
114 | + print("---------------------------------------------------------------------------------", end='') | |
115 | + | |
116 | + for i in range (0, 11): | |
117 | + print("\r\n", end='') | |
118 | + if i == 1: | |
119 | + print("---------------------------------------------------------------------------------\r\n",end='') | |
120 | + | |
121 | + print(i, end='\t') | |
122 | + for k in range (0,10): | |
123 | + print(round(self.MarkovValues[i][k].percentage,2), end='\t') | |
124 | + print("") | |
125 | + | |
126 | + def getMostLikely(self): | |
127 | + return self.getMostLikelyFromCell(self.previousCell) | |
128 | + | |
129 | + def getMostLikelyFromCell(self, currentCell): | |
130 | + max=0 | |
131 | + max_id=0 | |
132 | + for k in range(1,10): | |
133 | + if self.MarkovValues[k][currentCell].nb > max: | |
134 | + max = self.MarkovValues[k][currentCell].nb | |
135 | + max_id = k | |
136 | + return max_id | |
137 | + | |
138 | + def toString(self): | |
139 | + return "" | |
46 | 140 | |
47 | 141 | def newCell(n1, n2, n3, n4, l1, l2): |
48 | 142 | return Cell(RSSVector(n1,n2,n3,n4), Location(l1,l2)) |
... | ... | @@ -51,11 +145,10 @@ def KNeighbors(fingerprints, sample): |
51 | 145 | ''' |
52 | 146 | Returns the 4 closest cells to the given sample and fills sample distance data |
53 | 147 | :param Cell[3][3] fingerprints: 2D array of all the cells |
54 | - :param RSSIVector sample: Mobile terminal sample | |
148 | + :param RSSVector sample: Mobile terminal sample | |
55 | 149 | :return Cell[4]: the 4 nearest cells |
56 | 150 | ''' |
57 | - distances = [] | |
58 | - neighbours = [] | |
151 | + distances, neighbours = [], [] | |
59 | 152 | for row in fingerprints: |
60 | 153 | for currentItem in row: |
61 | 154 | dist = abs(currentItem.v.n1 - sample.n1) \ |
... | ... | @@ -78,7 +171,7 @@ def resolve_barycenter(nC, d): |
78 | 171 | :param distance[4] d: distances of the sample of the mobile terminal |
79 | 172 | :return Location: Estimated location of the mobile terminal (return None if error) |
80 | 173 | ''' |
81 | - return None if len(nC) != 4 else \ | |
174 | + return None if len(nC) != 4 or len(d) != 4 else \ | |
82 | 175 | 1 / (1+d[0]/d[1]+d[0]/d[2]+d[0]/d[3])*nC[0].location \ |
83 | 176 | + 1 / (1+d[1]/d[0]+d[1]/d[2]+d[1]/d[3])*nC[1].location \ |
84 | 177 | + 1 / (1+d[2]/d[1]+d[2]/d[0]+d[2]/d[3])*nC[2].location \ | ... | ... |