Esempio n. 1
0
 def getMostRecentGainMeasurments(coordinator_id, tx_node_id, rx_node_id, number = 6):
     #number represents the number of measurements to be returned. How many measurements you want to get. Example: if number=3, return last 3 measurements made
     #use this method when you want to get a list with a specified number of last measurements made
     if number == 0:
         #that means nothing
         return None
     
     #define a queue
     queue = MyQueue(number)
 
     #read from file (if it exists)
     #first, check if the file exists
     path = "./gain measurements/coor_%d/gain_between_tx_%d_and_rx_%d.dat" %(coordinator_id ,tx_node_id,  rx_node_id)
     
     if not os.path.isfile(path) or not os.path.exists(path):
         return None
     
     f = open(path, "r")
     
     #read first line, it's a header
     f.readline()
     
     #read file line by line
     while True:
         line = f.readline()
         if not line:
             break
         
         #define a line list: [gain - linear , received_power[w] , noise_power[w], transmitted_power[w], date ] - this is how results are saved in the file
         line_list = line.split()
         try:
             queue.append(float(line_list[0]))
         except:
             pass
     
     f.close()
     return queue.getListReverse()
Esempio n. 2
0
class PowerAllocation(threading.Thread):
    #This class is responsible with the allocation of powers which players application can use
    #Needs a player object and playerApp object in order to work
  
    #VESNA power generating list. This must be sorted. Powers are in dBm
    available_generating_powers = [0, -2, -4, -6, -8, -10, -12, -14, -16, -18, -20, -22, -24, -26, -28, -30, -55]
  
    #current transmitting power [dBm]
    current_transmitting_power = random.choice(available_generating_powers)
    
    #previous transmitted_power [dBm]
    previous_transmitted_power = current_transmitting_power
    
    #neighbor current_transmitting power [dBm]
    neighbor_current_transmitting_power = random.choice(available_generating_powers)
    
    #neighbor previous transmitted_power [dBm]
    neighbor_previous_transmitted_power = neighbor_current_transmitting_power
    
    #temporary - this best response is not truncated according to VESNA power list 
    best_response_untouched = current_transmitting_power
    
    #game type - can be: 1, 2, 3 . Depends on the implementation you want to use
    game_type = 3
    
    #neighborPowerEvent. When this is True, It means that neighbor player changed its power
    neighborPowerEvent = False
    
    #threshold_power. This can be set any time. We need this when we determine if Nash equilibrium was reached
    threshold_power = 0.8
    
    #A list in which we will save experiment results
    results_list = []
    
    #a boolean variable which tells the program if the cost is fixed or adaptive [not implemented yet]
    adaptive_cost = False
    
    #When this is triggered( =True ) then it means that equilibrium has been reached and the threads stops here.
    equilibriumDetected = False
    
    def __init__(self, playerObject ,playerAppObject, gameType = 3):
        print "Player power Allocation"
        threading.Thread.__init__(self)
        
        #save player object, that way, I can have any data I want from this player. Player object contains info about nodes (tx and rx), gains, cost..
        self.player = playerObject
        
        #Save playerAppObject this is how I can communicate with the PlayerApp object.
        self.playerApp = playerAppObject
        
        #configure sense node here, it's enough to be done only once
        self.player.rx_node.setSenseConfiguration(self.playerApp.frequency, self.playerApp.frequency, 400e3)
    
        #Let playerApp have this powerAllocationObject
        self.playerApp.setPowerAllocationOjbect(self)
        
        #save gameType
        self.game_type = gameType
        
    def printPowerAllocationInfo(self):
        print "PowerAllocation associated to player %d" %self.player.player_number    
    
    def setGameType(self, game_type):
        if game_type<1 or game_type>3:
            print "Game type can be 1, 2 or 3"
            self.game_type = 1
            return
        self.game_type = game_type    
        
    def setNeighborPowerAllocationObject(self, powerAllocationObject):
        #This is how I can communicate with the neighbor player
        #save powerAllocationObject
        self.neighborPowerAllocation = powerAllocationObject
        
    def setThresholdPower(self, threshold_power):    
        self.threshold_power = threshold_power
        print "Player %d : threshold power was set to: %.3f" %(self.player.player_number, self.threshold_power)
        
    def getTransmittingPower(self):
        #if PlayerApp needs to know the power which he can use, it's calling this method and he will get the allowed transmitting power
        #return self.current_transmitting_power
        return self.getTheNearestPower(self.current_transmitting_power)
    
    #there are several bestReponse methods
    def getBestResponseTheoreticallyForm(self):
        #based on the cost, cross gain, direct gain , neighbor power transmitting and noise we can determine new power
        #for best understanding see the formula in the article
        #We want to return a power in dBm. This power is the best power in interference condition 
        #this formula anticipates the received power basing on constant gains and noise
        
        #convert power from dBm to W
        #I need to know what power my neighbor is using. I know this from self.neighbor_current_transmitting_power, but is always worth checking.
        if (self.neighborPowerAllocation.current_transmitting_power != self.neighbor_current_transmitting_power):
            #Update neighbor_current_transmiting_power
            print "Neighbor current transmitting power uncertainty.Updating neighbor_current_transmitting_power"
            self.neighbor_current_transmitting_power = self.neighborPowerAllocation.current_transmitting_power
            
        #convert power to W
        neighbor_transmitting_power = math.pow(10.00, float(self.neighbor_current_transmitting_power) / 10.00) * 0.001
        best_response = (1.00/float(self.player.cost)) - (self.player.cross_gain * neighbor_transmitting_power  + self.player.noise_power) / float(self.player.direct_gain)
        
        #return a dBm power
        try:
            return 10.00 * math.log10(best_response/0.001)  
        except:
            print "Player %d: negative best response" %(self.player.player_number)
            return None  
    
    def getBestResponsePracticallyForm1(self, transmitted_power_dbm, received_power_dbm):
        #For best understanding see the formula in the article
        #This method returns a power in dBm. This power is the best power in interference condition
        #This method use the practically formula which will be used in empirical games
        #this formula will take into account the useful transmitted power 
        
        #parameters are  powers in dBm, we must convert them to W 
        transmitted_power_watts = math.pow(10.00, float(transmitted_power_dbm)/10.00) * 0.001
        useful_received_power_watts = transmitted_power_watts * self.player.direct_gain
        received_power_watts = math.pow(10.00, float(received_power_dbm)/10.00) * 0.001
        
        #now we have everything we need to calculate the new power based on formula: 1/c  -  (I+N)/gain, where I+N = received_power - useful_received_power
        if (transmitted_power_dbm < -1000):
            #In this case we consider that current player is not sending something useful, so he measured only noise and interference
            best_response = (1.00/float(self.player.cost)) - (received_power_watts)/float(self.player.direct_gain)
        else :
            best_response = (1.00/float(self.player.cost)) - (received_power_watts - useful_received_power_watts)/float(self.player.direct_gain)

        #I want to return a dBm power, because that is what we are sending to the nodes
        try:
            return 10.00 * math.log10(best_response/0.001) 
        except:
            print "Player %d: negative best response" %(self.player.player_number)
            return None
       
    def getBestResponsePracticallyForm2(self, received_power_dbm):
        #For best understanding see the formula in the article
        #This method return a power in dBm. This power is the best power in interference condition
        #This method use the practically formula which will be used in empirical games 
        #This formula is based on the received power dBm, which must be only noise and interference
        
        #convert received_power in W
        received_power_watts = math.pow(10.00, float(received_power_dbm)/10.00) * 0.001
        best_response = (1.00/float(self.player.cost)) - (received_power_watts)/float(self.player.direct_gain) 
        
        #I want to return a dBm power
        try:
            return 10.00 * math.log10(best_response/0.001) 
        except:
            print "Player %d: negative best response" %(self.player.player_number)
            return None
    
     
    '''
    #not implemented
    def costAdaptiveChange_Fang(self, received_power_dbm, useful_received_power_dbm):
        #must measure sinr first
        received_power = math.pow(10.00, float(received_power_dbm)/10.00) * 0.001
        useful_received_power = math.pow(10.00, float(useful_received_power_dbm)/10.000) * 0.001
        sinr = (useful_received_power)/(received_power-useful_received_power)
        print "Player %d  new cost adaptive changed: %.6f" %(self.player.player_number, 10/sinr)
    
    def costAdaptiveChange_Huang(self, received_power_dbm):
        received_power = math.pow(10.00, float(received_power_dbm)/10.00) * 0.001
        new_cost = (self.player.priority / (received_power))
        print "Player %d  new cost adaptive changed: %.6f" %(self.player.player_number, new_cost)
        self.player.setCost(new_cost)
        
    def enableAdaptiveCost(self):
        self.adaptive_cost = True
        
    def disableAdaptiveCost(self):
        self.adaptive_cost = False
    '''    
        
    def sharePowerToTheNeighbor(self, power_dBm):
        #Player i will call this method to share his new power to the neighbor
        #This is used in theoretically game
        self.neighborPowerAllocation.changeNeighborPowerAtribute(power_dBm)
        
    def changeNeighborPowerAtribute(self, new_power_dBm):
        #this method only changes self.neighbor_current_transmitting_power
        self.neighbor_previous_transmitted_power = self.neighbor_current_transmitting_power 
        self.neighbor_current_transmitting_power = new_power_dBm    
       
    def alertNeighborAboutAChangeOfPower(self):
        #Player i will call this method to alert the neighbor player that he made a change of power.
        self.neighborPowerAllocation.neighborPowerEvent = True
        
    def changeCurrentPower(self, new_power_dbm):
        #change power on current object. Use this method to unbalance the system by generating an event.
        
        #save new power
        self.previous_transmitted_power = self.current_transmitting_power
        self.current_transmitting_power = new_power_dbm
        
        print "Player %d intentionally changed  his power: previous power = %.6f   current power = %.6f" %(self.player.player_number ,self.previous_transmitted_power, self.current_transmitting_power)
        
        #before we generate, let's make sure the other players are not transmitting now
        #wait for the neighbor to finish his transmission
        while self.neighborPowerAllocation.playerApp.isSendingAPacket():
            print "Player %d : waiting for the neighbor to finish his transmission" %self.player.player_number
            time.sleep(1)

        #transmit for a few seconds. 
        if self.game_type != 1:
            #if it's a theoretical game (simulation) it's no needed to transmit anything
            self.playerApp.sendPacket(8)
            #announce the other player that I made a change
            #but first, wait 1-2 seconds to be sure that the neighbor player catch the interference (there might be other delays in the testbed)
            time.sleep(1)
         
        #announce neighbor about a change
        self.sharePowerToTheNeighbor(self.current_transmitting_power)
        self.alertNeighborAboutAChangeOfPower()   
        
        #add an iteration to the results_list (We want to save all experiment results in a file). results_list has the following structure: [new power calculated_truncated, new_power_calculated_non_truncated, received power, anticipated useful received power, player cost] 
        try:
            self.results_list[0] = ([self.current_transmitting_power, self.current_transmitting_power, "None", "None", self.player.cost])
        except:
            pass 
            
        return
    
    def checkEquilibrium(self,equal_condition = False):
        #check difference between last best responses
        #Depends on the implementation, if you want to compare equilibrium considering truncated values, than equal_condition= True, otherwise set it to False
        #list :[most recent, less recent, less recent, ..]
        print "Player %d check equilibrium :" %(self.player.player_number)
        list = self.queue_list.getList()
        length = self.queue_list.len
        print list
        
        if len(list) != length :return False
        
        if equal_condition == False:
            for i in range(0, len(list)):
                if math.fabs(math.fabs(float(list[0])) - math.fabs(float(list[i])) ) > float(self.threshold_power):
                    return False
             
            #if I've got here it means that the Nash equilibrium condition is reached   
            return True 
        else:
            #in this case, all best responses must be equal
            for i in range(0, len(list)-1):
                if float(list[i]) != float(list[i+1]):
                    return False
                
            return True
    
    def limitCurrentTransmittingPower(self):
        if self.current_transmitting_power > 0 :
            print "Player %d limited his own  power to 0 dBm from %.3f" %(self.player.player_number, self.current_transmitting_power)
            self.current_transmitting_power = 0
        if self.current_transmitting_power < -55:
            print "Player %d limited his own  power to -55 dBm from %.3f" %(self.player.player_number, self.current_transmitting_power)
            self.current_transmitting_power = -55
    
    def printIterationsToFile(self, results_list, other_observations = None):
        #first make folders
        try:
            os.mkdir("./iterations")
        except:
            pass
        
        try:
            if self.player.player_number == 1:
                os.mkdir("./iterations/c1_%d-c2_%d" %(self.player.cost, self.neighborPowerAllocation.player.cost))
            elif self.player.player_number == 2:
                os.mkdir("./iterations/c1_%d-c2_%d" %(self.neighborPowerAllocation.player.cost, self.player.cost))
        except:
            pass
        
        if self.player.player_number == 1:    
            path =  "./iterations/c1_%d-c2_%d/player_%d_with_tx_%d_and_rx_%d.dat" %(self.player.cost, self.neighborPowerAllocation.player.cost,self.player.player_number, self.player.tx_node.node_id, self.player.rx_node.node_id)
        else:
            path =  "./iterations/c1_%d-c2_%d/player_%d_with_tx_%d_and_rx_%d.dat" %(self.neighborPowerAllocation.player.cost,self.player.cost,self.player.player_number, self.player.tx_node.node_id, self.player.rx_node.node_id)
        
        #see if the path exits and if not create if for the first time
        if (not os.path.exists(path) or not os.path.isfile(path)):
            #create the file
            f = open(path, "w")
            f.write("In this file you will find experiments results about the convergence of the player %d with tx_%d and rx_%d\n" %(self.player.player_number, self.player.tx_node.node_id, self.player.rx_node.node_id))
            f.close()
        
        f = open(path, "a")
        
        if other_observations == None:
            other_observations = "None"
        
        if self.adaptive_cost:
            f.write("Experiment made at: %s. Configuration: cost = %s    threshold = %.3f . Type of the game: %d . Direct gain: %.3f dB   Cross gain: %.3f dB  Observations:%s\n" %(str(datetime.datetime.now()),str(self.player.cost)+ " adaptive", self.threshold_power, self.game_type, 10.00*math.log10(self.player.direct_gain), 10.00 * math.log10(self.player.cross_gain), other_observations))
        else:
            f.write("Experiment made at: %s. Configuration: cost = %s    threshold = %.3f . Type of the game: %d . Direct gain: %.3f dB   Cross gain: %.3f dB  Observations:%s\n" %(str(datetime.datetime.now()), str(self.player.cost) + " fixed", self.threshold_power, self.game_type, 10.00*math.log10(self.player.direct_gain), 10.00 * math.log10(self.player.cross_gain), other_observations))
        
        for i in range(0, len(results_list)):
            f.write("Iteration: %d     New_Power: %.12f ( %.6f )  Measured_Power: %s  Anticipated_useful_received_power: %s    Instant cost: %.3f\n" %(i, results_list[i][0], results_list[i][1],str(results_list[i][2]), str(results_list[i][3]), results_list[i][4] ) )
            
        f.write("\n")
        f.close()
        
    def printStrategyTable(self, nash_value_player1, nash_value_player2, iterations=-1):
        #prints to a file, only the Nash equilibrium value
        path = "./iterations/strategyTable.dat" 
        
        #see if the path exits and if not create it for the first time
        if (not os.path.exists(path) or not os.path.isfile(path)):
            #create the file
            f = open(path, "w")
            f.write("In this file you will find Nash Equilibrium values\n")
            f.close()
        
        f = open(path, "a")
        
        if self.player.player_number == 1:
            f.write("c1= %d   c2= %d   Nash value player 1= %.9f dBm    Nash value player 2= %.9f dBm  Iterations= %d  h11= %.3f dB h21= %.3f dB  h22= %.3f dB  h12= %.3f dB  Player1Noise=%.3fE-13  Player2Noise=%.3fE-13  Date= %s\n" % (self.player.cost, self.neighborPowerAllocation.player.cost, nash_value_player1, nash_value_player2, iterations, 10.00 * math.log10(self.player.direct_gain), 10.00*math.log10(self.player.cross_gain), 10.00*math.log10(self.neighborPowerAllocation.player.direct_gain), 10.00*math.log10(self.neighborPowerAllocation.player.cross_gain), self.player.noise_power*1e13, self.neighborPowerAllocation.player.noise_power*1e13,datetime.datetime.now() )  )
        f.close()
        
    def getTheNearestPower(self, power):
        #from the available power list choose the nearest from the power
        
        min_diferrence = float("inf")
        nearest_power = None
        #Small discussion: self.available_generating_powers it's ascending sorted
        #The update takes only when you find an available power more appropriate to given power. If the there are 2 available power which gives the same distance from the given power, the greater value will be chosen. Example: available power list [0 , -2, -4, ..] and we have a given power= -1, the result will be 0 
        for i in range(0, len(self.available_generating_powers)):
            if (math.fabs(power-self.available_generating_powers[i]) < min_diferrence):
                min_diferrence = math.fabs(power-self.available_generating_powers[i])
                nearest_power = self.available_generating_powers[i]
                
        return nearest_power
    
    def equilibriumDectected(self):
        #when other players detect the equilibrium
        self.equilibriumDetected = True
    
    def gameType1(self):
        #number of iterations until player reach the Nash equilibrium
        iterations = 0
        #Use this because I want to see how long it takes to reach the Nash equilibrium
        process_start_time = time.time()
      
        #initialize results_list because I want to save all experiment results 
        self.results_list = [[self.getTheNearestPower(self.current_transmitting_power), self.current_transmitting_power, "None", "None", self.player.cost]]
        
        print "Player %d: game type 1 started" %self.player.player_number
        while True:
            #infinite loop
            #see if neighbor changed it's power
            if (self.neighbor_previous_transmitted_power != self.neighbor_current_transmitting_power):
                #neighbor power change event triggered
                #reset the event by equaling the old power with the current power 
                self.neighbor_previous_transmitted_power = self.neighbor_current_transmitting_power
                
                print "Player %d detected a change of power and it's recalculating its own transmission power" %self.player.player_number
                
                #there has been a change of power on the neighbor player, so I have to recalculate my own power
                #in this game type we use the theoretically formula
                self.previous_transmitted_power = self.current_transmitting_power
                self.current_transmitting_power = self.getBestResponseTheoreticallyForm()
                #save best response
                self.best_response_untouched = self.current_transmitting_power
                #truncate the value
                #self.current_transmitting_power = self.getTheNearestPower(self.current_transmitting_power)
                
                #append data in results list: [new power calculated, new_power_untouched, received power, anticipated useful received power] 
                self.results_list.append([self.current_transmitting_power, self.best_response_untouched, "None", "None", self.player.cost])
                iterations+= 1
                
                #now see if the new calculated power is different from the old one. If no, that means Nash equilibrium
                if self.previous_transmitted_power != self.current_transmitting_power :
                    print "Player %d changed his own power: previous power = %.6f dBm     current power = %.6f dBm" %(self.player.player_number, self.previous_transmitted_power, self.current_transmitting_power)
                    #announce the other player about my change
                    self.sharePowerToTheNeighbor(self.current_transmitting_power)
                else:
                    #best response is the same from the previous iteration
                    print "Player %d : new power is not different from the old one, that means Equilibrium. Number of iterations:%d  previous power=%.3f  current power=%.3f\n" %(self.player.player_number,iterations, self.previous_transmitted_power, self.current_transmitting_power)
                
                    #finish the game by stopping the threads
                    self.equilibriumDectected()
                    self.neighborPowerAllocation.equilibriumDectected()
    
            else:
                if self.equilibriumDetected:
                    print "Player %d Equilibrium. No events had been detected. Number of iterations:%d. Time passed: %.6f" %(self.player.player_number, iterations, (time.time() - process_start_time)) 
                    print "Player %d power allocated: %.3f" %(self.player.player_number, self.current_transmitting_power)
                    
                    #write experiment results in a file
                    self.printIterationsToFile(self.results_list)
                   
                    #if this is player 1, then print the strategy table( is enough that only one player to do that)
                    if self.player.player_number == 1:
                        self.printStrategyTable(self.current_transmitting_power, self.neighborPowerAllocation.current_transmitting_power, iterations=iterations)
                    break
                 
            time.sleep(0.01)  
         
    def gameType2(self):
        #number of iterations until player reach the Nash equilibrium
        iterations = 0
        #USe this because I want to see how long it takes to reach the Nash equilibrium
        process_start_time = time.time()
        
        print "Player %d Game type 2 started" %self.player.player_number
        
        #want to save the experiment results. results_list_ [new power calculated, received power, anticipated useful received power] 
        self.results_list = [[self.getTheNearestPower(self.current_transmitting_power), self.current_transmitting_power, "None", "None", self.player.cost]]
        
        self.queue_list = MyQueue(5)
        
        while True:
            #see if there is any power change alert from the neighbor
            if self.neighborPowerEvent :
                #that means neighbor changed its own power
                #reset the event because is being treated
                self.neighborPowerEvent = False
                
                print "Player %d detected a change of power and it's recalculating its own transmission power. Iteration %d" %(self.player.player_number, iterations)
                
                #anticipate transmitted_power. Initialize transmited_power with  -100000 dBm, equivalent with almost 0 in linear scale
                transmited_power_dbm_before_measurement = -100000   
                if self.playerApp.isSendingAPacket():
                    #yes, I am sending a packet right now, I have to consider that because I want to know what is interference and noise and what is not
                    transmited_power_dbm_before_measurement = self.playerApp.getTransmittingPower()
                
                #there hass been a change of power on the neighbor player, so I have to recalculate my own power
                #measure received power. received_power has the following structure: [[frequency], [power_dbm]]
                received_power = self.player.rx_node.senseStartQuick()
                
                #see if there is any power transmitting right now again. First initialize transmited_power_dbm with a very low power: -10000 dBm it's very small
                transmited_power_dbm_after_measurement = -100000
                if self.playerApp.isSendingAPacket():
                    #yes, I am sending a packet right now, I have to consider that because want to know when is interference and noise and when is not
                    transmited_power_dbm_after_measurement = self.playerApp.getTransmittingPower()
                
                #see if the useful transmitted power before and after measurements are equal, if not I can't be sure that when I did the measure, I was generating signal or no, that way I won't be able to determine the interference level
                if transmited_power_dbm_after_measurement != transmited_power_dbm_before_measurement:
                    print "Player %d bad anticipation of useful received power, continue this iteration and measure again" %(self.player.player_number)
                    #set event to true because it wasn't complete treated 
                    self.neighborPowerEvent = True
                    #measure again
                    continue
                
                if (transmited_power_dbm_after_measurement + 10.00 * math.log10(self.player.direct_gain)) > received_power[1][0]:
                    #the anticipated useful received power can't be higher than the received power
                    print "Anticipated received power > received power : %.6f > %.6f" %(transmited_power_dbm_after_measurement + 10.00 * math.log10(self.player.direct_gain), received_power[1][0])
                    self.neighborPowerEvent = True
                    continue
                    
                #just print some info
                if float(transmited_power_dbm_after_measurement) < -1000:
                    print "Player %d received power: [%.3f dBm] and he is not transmitting anything at this moment" %(self.player.player_number, received_power[1][0])
                else :
                    print "Player %d received power: [%.3f dBm] and he is transmitting with %.3f dBm. Anticipated useful received power: %.3f" %(self.player.player_number, received_power[1][0], transmited_power_dbm_after_measurement,  transmited_power_dbm_after_measurement + 10.00 * math.log10(self.player.direct_gain))
                    
                #now we have anything we need to calculate new power
                self.previous_transmitted_power = self.current_transmitting_power
                self.current_transmitting_power = self.getBestResponsePracticallyForm1(transmited_power_dbm_after_measurement, float(received_power[1][0]))
                
                #Sometimes formula returns a negative power (in linear!), which can't be possible.
                if self.current_transmitting_power is None:
                    self.neighborPowerEvent = True
                    #anyway, I want to keep previous transmitted power
                    self.current_transmitting_power = self.previous_transmitted_power
                    continue
                
                #copy best response
                self.best_response_untouched = self.current_transmitting_power
                self.current_transmitting_power = self.getTheNearestPower(self.current_transmitting_power)
                
                #make some list with iterations and calculated powers
                self.results_list.append([self.current_transmitting_power, self.best_response_untouched, received_power[1][0], transmited_power_dbm_after_measurement + 10.00 * math.log10(self.player.direct_gain), self.player.cost])
                self.queue_list.append(self.best_response_untouched)
                #we want to count how many iterations the algorithm used to reach the Nash equilibrium
                iterations+= 1
                
                #see if the difference between new power and old power exceeds the threshold_power
                if not self.checkEquilibrium(equal_condition=False):
                    #Nash equilibrium hasn't reached yet
                    print "Player %d has not reached the Nash Equilibrium yet" %(self.player.player_number)
                    
                    #generate at new power. This is needed because this way the neighbor player can see the change I made
                    #send a packet for 12 seconds
                    self.playerApp.sendPacket(8)
                    #to be sure the neighbor will catch my generated signal, a wait for 1 second (this way I consider the programming time)
                    time.sleep(1)
                    #announce the other player about my change
                    self.alertNeighborAboutAChangeOfPower()
                else:
                    #that means equilibrium
                    print "Player %d : Equilibrium has been reached" %(self.player.player_number)
                    
                    #finish the game by stopping the threads
                    self.equilibriumDectected()
                    self.neighborPowerAllocation.equilibriumDectected()
                
            else:
                if self.equilibriumDetected:
                    print "Player %d Equilibrium. No events had been detected. Number of iterations:%d. Time passed: %.6f" %(self.player.player_number, iterations, (time.time() - process_start_time) - 45) 
                    print "Player %d power allocated: %.3f" %(self.player.player_number, self.current_transmitting_power)
                    
                    #write experiment results in a file
                    self.printIterationsToFile(self.results_list)
                   
                    #if this is player 1, then print the strategy table( is enough that only one player to do that)
                    if self.player.player_number == 1:
                        self.printStrategyTable(self.current_transmitting_power, self.neighborPowerAllocation.current_transmitting_power, iterations=iterations)
                    break
            time.sleep(0.03)
                    
    def gameType3(self):  
        #number of iterations until player reached the Nash equilibrium
        iterations = 0
        #USe this because I want to see how long it takes to reach the Nash equilibrium
        process_start_time = time.time()
        
        print "Player %d Game type 3 started" %self.player.player_number
        
        #want to save the experiment results. results_list_ [[new power calculated truncated, new_power_calculated, received power, anticipated useful received power], [same thing],[same thing].. ] 
        self.results_list = [[self.getTheNearestPower(self.current_transmitting_power), self.current_transmitting_power, "None", "None", self.player.cost]]
        #a queue_list which will help us to know if the equilibrium has been reached
        self.queue_list = MyQueue(5)
        
        while True:
            #infinite loop
            #see if there is any power change alert from the neighbor
            if self.neighborPowerEvent :
                #that means neighbor changed its own power, so I have to update my power
                #reset the event because is being treated
                self.neighborPowerEvent = False
                
                print "Player %d detected a change of power and it's recalculating its own transmission power. Iteration %d" %(self.player.player_number, iterations)
                
                #check if I am transmitting something right now
                if( self.playerApp.isSendingAPacket()):
                    #I can't measure in this case, I want to measure only interference and noise
                    while self.playerApp.isSendingAPacket():
                        print "Player %d : bad news, I'm transmitting packets right now, wait to stop!" %self.player.player_number
                        time.sleep(1)
                    
                    #Ask the neighbor to recalculate power and regenerate a signal
                    self.alertNeighborAboutAChangeOfPower()
                    continue
                
                #measure received power. received_power has the following structure: [[frequency], [power_dbm]]
                received_power = self.player.rx_node.senseStartQuick()
                print "Player %d received noise and interference power: %.3f dBm" %(self.player.player_number, received_power[1][0])
                
                #now we have anything we need to calculate new power
                self.previous_transmitted_power = self.current_transmitting_power
                #the best response returned is in dBm
                self.current_transmitting_power = self.getBestResponsePracticallyForm2(received_power[1][0])
                
                #sometimes formula returns a negative power in linear, that can't be possible in practice, so if that happens, continue this iteration
                if self.current_transmitting_power is None:
                    print "Player %d negative power" %self.player.player_number
                    self.current_transmitting_power = self.previous_transmitted_power
                    self.neighborPowerEvent = True
                    continue
                
                #the best response give us a real power, in practice we can't generate a power at any resolution ( The formula doesn't take into account this thing)
                #On VESNA platform there are a few power values that can be generated
                print "Player %d best response: %.6f. Choosing the right value for VESNA..." %(self.player.player_number, self.current_transmitting_power) 
                #I want to keep the best response given by the formula
                self.best_response_untouched = self.current_transmitting_power
                #truncate the power
                self.current_transmitting_power = self.getTheNearestPower(self.current_transmitting_power)
            
                #make some list with iterations and calculated powers
                self.results_list.append([self.current_transmitting_power, self.best_response_untouched, received_power[1][0], "None", self.player.cost])
                self.queue_list.append(self.best_response_untouched)
                #we want to count how many iterations the algorithm used to reach the Nash equilibrium
                iterations+= 1
                
                #see if we have reached the equilibrium
                if not self.checkEquilibrium(equal_condition=False):
                    #the equilibrium has not been reached yet 
                    print "Player %d has not reached the Nash Equilibrium yet" %(self.player.player_number)
                    
                    #wait for the neighbor to finish his transmission
                    while self.neighborPowerAllocation.playerApp.isSendingAPacket():
                        print "Player %d : waiting for the neighbor to finish his transmission" %self.player.player_number
                        time.sleep(1)
                    
                    #generate at new power. This is needed because this way the neighbor player can see the change I made
                    #send a packet for a few seconds
                    self.playerApp.sendPacket(6)
                    #to be sure the neighbor will catch my generated signal,  wait for 1 second (this way I consider others delay that can appear within the testbed)
                    time.sleep(1)
                    #announce the other player about my change
                    self.alertNeighborAboutAChangeOfPower()
                else:
                    #that means equilibrium
                    print "Player %d : Equilibrium has been reached" %(self.player.player_number)
                    
                    #check if neighbor has reached equilibrium too
                    if(not self.neighborPowerAllocation.checkEquilibrium(equal_condition=False)):
                        print "Player %d : My neighbor has not reached the Nash equilibrium yet, send a packet again" %self.player.player_number
                        
                        #wait for the neighbor to finish his transmission
                        while self.neighborPowerAllocation.playerApp.isSendingAPacket():
                            print "Player %d : waiting for the neighbor to finish his transmission" %self.player.player_number
                            time.sleep(1)
                        
                        #send packet
                        self.playerApp.sendPacket(6)
                        time.sleep(1)
                        self.alertNeighborAboutAChangeOfPower()
                        continue
                    
                    #finish this game
                    self.neighborPowerAllocation.equilibriumDectected()
                    self.equilibriumDectected()
                    
            else:
                if self.equilibriumDetected:
                    print "\x1b[1;31m"
                    print "Player %d Equilibrium. No events had been detected. Number of iterations:%d. Time passed: %.6f \n" %(self.player.player_number, iterations, (time.time() - process_start_time) - 45) 
                    print "Player %d power allocated: %.3f" %(self.player.player_number, self.current_transmitting_power)
                    print "\x1b[0m"
                    
                    #write experiment results in a file
                    self.printIterationsToFile(self.results_list, "Using threshold with a 5 size queue, predicted gains")
                    if self.player.player_number == 1:
                        self.printStrategyTable(self.best_response_untouched, self.neighborPowerAllocation.best_response_untouched, iterations)
                    
		    while True:
			    time.sleep(1)

            time.sleep(0.05)
            
    def run(self):
        if self.game_type == 1:
            self.gameType1()
        elif self.game_type == 2:
            self.gameType2()
        elif self.game_type == 3:
            self.gameType3()
Esempio n. 3
0
class GamePlayer:
    """
    Defines a game player (tx node, rx node, tx characteristics..)
    Has attached a playerApp and a powerAllocation object.
    """

    # player power cost [1/W], must be in [0,1]
    cost = 0
    scaledCost = 0

    # channel gains, dimensionless
    directGain = 0.0
    crossGain = 0.0

    # noise power, must be measured
    noisePower = 6.43e-13

    # player number used for identification
    playerNumber = None

    # current transmission power [dBm]. updated based in game iterations
    currentTxPower = 0.0

    # used for transmitting data and sensing the spectrum
    physicalLayer = None

    # compute best response only if player is not the source of the event
    sourceOfEvent = False

    # count number of iterations
    playerIterations = 0

    # save result in this list
    queueList = None

    # threshold_power. This can be set any time. We need this when we determine if Nash equilibrium was reached
    thresholdPower = 0.8

    def __init__(self, coordinatorId, txNodeId, rxNodeId, cost, playerNumber, gameFreq, gameType=0):
        """
        Create a player and initialize internal parameters.

        Keyword arguments:
        coordinatorId -- Numerical cluster id.
        txNodeId -- Numerical id for transmission node.
        rxNodeId -- Numerical id for receiver node.
        cost -- Energy cost.
        playerNumber -- Numerical number used to identify players.
        gateType -- Type of game played.
        """

        self.coordinatorId = coordinatorId
        self.cost = cost
        self.playerNumber = playerNumber
        self.gameFreq = gameFreq
        self.gameType = gameType

        self.txNodeId = txNodeId
        self.rxNodeId = rxNodeId

        self.sourceOfEvent = False

        self.queueList = MyQueue(5)
        self.playerIterations = 0

        # initialize physical layer
        self.physicalLayer = PlayerPhysicalLayer(self, txNodeId, self.rxNodeId, self.coordinatorId, self.gameFreq, self.cost, self.gameType)

    def resetPlayerObject(self):
        """Use this to reset player variables, used for multiple runs"""
        self.queueList.emptyList()
        self.playerIterations = 0
        self.physicalLayer.changeTxPowerRandomly()

    def getPlayerNumber(self):
        return self.playerNumber

    def getPlayerCost(self):
        return self.cost

    def setPlayerCost(self, newCost):
        self.cost = newCost

    def getScaledCost(self):
        return self.scaledCost

    def setScaledCost(self, newScaledCost):
        self.scaledCost = newScaledCost
        self.physicalLayer.setCost(self.scaledCost)

    def getNrPlayerIterations(self):
        return self.playerIterations

    def generatePowerEvent(self):
        """Generate new tx power"""
        self.sourceOfEvent = True
        self.physicalLayer.changeTxPowerRandomly()
        return self.physicalLayer.getCrtTxPower()

    def updateTxPowerAsAverage(self):
        """Update current transmission power as average of last 5 tx powers"""
        bestRespList = self.queueList.getList()
        nrBestResp = len(bestRespList)
        mySum = 0

        for i in range(0, nrBestResp):
            mySum += float(bestRespList[i])

        avgTxPw = mySum / float(nrBestResp)
        self.physicalLayer.changeTxPower(avgTxPw)
        self.queueList.append(self.physicalLayer.getCrtTxPower())

    def updateTxPowerWithMask(self, pTxj, hjiDict, mask):
        self.playerIterations += 1
        opponentPowers = list()
        crossG = list()
        updateResult = False
        for key in pTxj:
            if key != self.playerNumber and mask[key]:
                opponentPowers.append(pTxj[key])
                crossG.append(hjiDict[key])
        bestResp = self.physicalLayer.computeBestResponseForm1(opponentPowers, crossG)
        if bestResp is not None:
            updateResult = True
            self.physicalLayer.changeTxPower(bestResp)
        self.queueList.append(self.physicalLayer.getCrtTxPower())

        return updateResult

    def updateTxPower(self, pTxj, hjiDict):
        """
        Update current transmission power based on best response relation.
        Must extract from pj a list of tx power for adversaries, delete from list tx power of current player

        Keyword arguments:
        pTxj -- dictionary with players tc powers in [dBm]
        hjiList -- dictionary with player cross gains for current player, e.g. {2:h_21,3:h_31}
        """
        # create list with opponent tx powers and cross gains
        self.playerIterations += 1

        opponentPowers = list()
        crossG = list()
        updateResult = False

        for key in pTxj:
            if key != self.playerNumber:
                opponentPowers.append(pTxj[key])
                crossG.append(hjiDict[key])

        bestResp = self.physicalLayer.computeBestResponseForm1(opponentPowers, crossG)
        if bestResp is not None:
            # sometimes the difference in best response in negative
            # in that case do nothing, player will continue to transmit
            # with current power
            updateResult = True
            self.physicalLayer.changeTxPower(bestResp)

        # self.result.append([iteration, self.physicalLayer.getCrtTxPower(), self.physicalLayer.bestResponseUntouched, self.cost])
        # TODO: in jocul facut de studenti cond de echilibru e verificata pe val reala, mai corect e pt cea discretizata
        self.queueList.append(self.physicalLayer.getCrtTxPower())

        return updateResult

    def updateTxPower1(self, measuredRxPower):
        """
        Update current transmission power based on best response relation, and measured power.

        Keyword arguments:
        measuredRxPower -- Measured receiving power, i.e. sum(h_ji * p_j) + n_0
        """
        self.playerIterations += 1
        bestResp = self.physicalLayer.computeBestResponseForm2(measuredRxPower)
        if bestResp is not None:
            # sometimes the difference in best response in negative
            # in that case do nothing, player will continue to transmit
            # with current power
            updateResult = True
            self.physicalLayer.changeTxPower(bestResp)

        self.queueList.append(self.physicalLayer.getCrtTxPower())

        return updateResult

    def updateTxPower2(self, measuredRxpower):
        """
        Update current transmission power based on best response relation, and measured power.

        Keyword arguments:
        measuredRxPower -- Measured receiving power, i.e. sum(h_ji * p_j) + n_0
        """
        self.playerIterations += 1
        bestResp = self.physicalLayer.computeBestResponseForm3(measuredRxpower)
        if bestResp is not None:
            updateResult = True
            self.physicalLayer.changeTxPower(bestResp)
        else:
            updateResult = False
        self.queueList.append(self.physicalLayer.getCrtTxPower())
        return updateResult

    def setThresholdPower(self, newThresholdPower):
        """Set threshold power used to determine if player has reached equilibrium"""
        self.thresholdPower = newThresholdPower
        print "Player %d : threshold power was set to: %.3f" % (self.playerObject.playerNumber, self.thresholdPower)


    def isInEquilibrium(self, equalCondition=True):
        """
        Check if player has reached a stable state

        Keyword arguments:
        equalCondition -- true->all elements from history must be equal.
        """
        bestrespList = self.queueList.getList()
        length = self.queueList.len

        if len(bestrespList) != length:
            return False

        if equalCondition:
            # all best responses must be equal
            for i in range(1, len(bestrespList)):
                if float(bestrespList[0]) != float(bestrespList[i]):
                    return False
            # print "Player %d has reached a stable state, i.e. equilibrium." % (self.playerNumber+1)
            return True
        else:
            for i in range(1, len(bestrespList)):
                if math.fabs(math.fabs(float(list[0])) - math.fabs(float(bestrespList[i]))) > float(self.thresholdPower):
                    return False
            # print "Player %d has reached a stable state, i.e. equilibrium." % (self.playerNumber+1)
            return True