structure.py 5.96 KB
from operator import itemgetter as ig
from math import floor

class RSSVector():
    distances = []
    def __init__(self, n1, n2, n3, n4):
        self.n1 = n1
        self.n2 = n2
        self.n3 = n3
        self.n4 = n4

class Location():
    def __init__(self, x, y, z=0):
        self.x = x
        self.y = y
        self.z = z

    def __mul__(self, multiplier):
        returnValue = Location(self.x, self.y, self.z)
        returnValue.x *= multiplier 
        returnValue.y *= multiplier
        returnValue.z *= multiplier
        return returnValue

    def __rmul__(self, multiplier):
        return self * multiplier

    def __add__(self, added):
        returnValue = Location(self.x, self.y, self.z)
        returnValue.x += added.x
        returnValue.y += added.y
        returnValue.z += added.z
        return returnValue

    def __isub__(self, value):
        return self + -1 * value

    def __itruediv__(self, divider):
        returnValue = Location(self.x, self.y, self.z)
        returnValue.x /= divider
        returnValue.y /= divider
        returnValue.z /= divider
        return returnValue

    def toString(self):
        return "(" + str(self.x) + " ; " + str(self.y) + " ; " + str(self.z) + ")"

    def getPositionInArray(self, arraySize=3):
        temp = Location(self.x, self.y)
        temp /= 2
        temp -= Location(1,1)
        return floor((temp.x * arraySize + temp.y)/2)

    @staticmethod
    def fromID(id, arraySize=3):
        id -= 1
        y=id % 3
        x=floor((id - y) / 3)
        returnValue = Location(x, y)
        returnValue *= 2
        returnValue += Location(1,1)
        returnValue *= 2
        return returnValue

class Cell():
    def __init__(self, v_, loc):
        self.v = v_
        self.location = loc

class MarkovValue():
    def __init__(self, nb=0, percentage=0.0):
        self.nb = nb
        self.percentage = percentage # Probability of Markov model (100% <=> 1.0)

class MarkovModel():
    def __init__(self,cells):
        self.MarkovValues = [] #table of the coefficients of the Markov Model
        self.cells = cells
        self.previousCell = 0
        for i in range (0, 11):
            self.MarkovValues.append([])
            for _ in range (0, 10):
                self.MarkovValues[i].append(MarkovValue())
        self.MarkovValues[10][0].nb = 1 #initial position sigma increment  

    def moveToCellID(self, nextCell):
        self.MarkovValues[nextCell][self.previousCell].nb += 1     
        self.MarkovValues[10][nextCell].nb += 1
        self.refreshPercentage(self.previousCell)
        self.previousCell = nextCell
        
    def moveToCell(self, nextCell):
        self.moveToCellID(nextCell.location.getPositionInArray()+1)

    def refreshPercentage(self, col):
        if  self.MarkovValues[10][col].nb:
            for k in range(0,10):
                    self.MarkovValues[k][col].percentage = self.MarkovValues[k][col].nb / self.MarkovValues[10][col].nb
            
    def printValues(self):
        print("\t? \t1 \t2 \t3\t4 \t5 \t6 \t7 \t8 \t9")
        print("---------------------------------------------------------------------------------", end='')
        
        for i in range (0, 11):
            print("\r\n", end='')
            if i == 10 or i == 1:
                print("---------------------------------------------------------------------------------\r\n",end='')
            
            print(i, end='\t')
            for k in range (0,10):
                print(self.MarkovValues[i][k].nb, end='\t')
        print("")

    def printPercentages(self):
        print("\t? \t1 \t2 \t3\t4 \t5 \t6 \t7 \t8 \t9")
        print("---------------------------------------------------------------------------------", end='')
    
        for i in range (1, 10):
            print("\r\n", end='')
            
            print(i, end='\t')
            for k in range (0,10):
                print(str(floor(self.MarkovValues[i][k].percentage * 100)), end='\t')
        print("")

    def getMostLikely(self):
        return self.getMostLikelyFromCell(self.previousCell)

    def getMostLikelyFromCell(self, currentCell):
        max=0
        max_id=0
        for k in range(1,10):
            if self.MarkovValues[k][currentCell].nb > max:
                max = self.MarkovValues[k][currentCell].nb
                max_id = k
        return max_id 

    def path(self, locationIDs):
        for loc in locationIDs:
            self.moveToCellID(loc)
    

def newCell(n1, n2, n3, n4, l1, l2):
    return Cell(RSSVector(n1,n2,n3,n4), Location(l1,l2))
    
def KNeighbors(fingerprints, sample):  
    '''
    Returns the 4 closest cells to the given sample and fills sample distance data
    :param Cell[3][3] fingerprints: 2D array of all the cells
    :param RSSVector sample: Mobile terminal sample
    :return Cell[4]: the 4 nearest cells
    '''
    distances, neighbours = [], []
    for row in fingerprints:
        for currentItem in row:
            dist = abs(currentItem.v.n1 - sample.n1) \
                 + abs(currentItem.v.n2 - sample.n2) \
                 + abs(currentItem.v.n3 - sample.n3) \
                 + abs(currentItem.v.n4 - sample.n4) 
            distances.append((dist, currentItem))
    distances = sorted(distances, key=ig(0))
    for k in range (0,4):
        neighbours.append(distances[k][1])
        sample.distances.append(distances[k][0])
    return neighbours



def resolve_barycenter(nC, d):
    '''
    Returns the weighted barycenter of the 4 neighbouring cells
    :param Cell[4] nC: (neighborCells) Array containing the 4 closest cells
    :param distance[4] d: distances of the sample of the mobile terminal
    :return Location: Estimated location of the mobile terminal (return None if error)
    '''
    return None if len(nC) != 4 or len(d) != 4 else  \
          1 / (1+d[0]/d[1]+d[0]/d[2]+d[0]/d[3])*nC[0].location \
        + 1 / (1+d[1]/d[0]+d[1]/d[2]+d[1]/d[3])*nC[1].location \
        + 1 / (1+d[2]/d[1]+d[2]/d[0]+d[2]/d[3])*nC[2].location \
        + 1 / (1+d[3]/d[1]+d[3]/d[2]+d[3]/d[0])*nC[3].location