Exemplo n.º 1
0
class SmartHome(Home):
    def __init__(self, w, h):
        super().__init__(w, h)
        self.scenario = Scenario()
        self.width_bound = [1, w - 1]
        self.height_bound = [1, h - 1]
        #self.presence, self.bulbs = self.scenario.diagonal(self.width, self.height)
        #self.presence, self.bulbs = self.scenario.stripes(self.width, self.height)
        #self.presence, self.bulbs = self.scenario.corners(self.width, self.height)
        #self.presence, self.bulbs = self.scenario.corners2(self.width, self.height)
        self.presence, self.bulbs = self.scenario.extreme(
            self.width, self.height)

        self.init_deap()
        self.init_figures()

    def generate_individual(self, icls):
        luminosity = np.zeros((self.height, self.width))

        for y in range(self.height_bound[0], self.height_bound[1]):
            for x in range(self.width_bound[0], self.width_bound[1]):
                luminosity[y, x] = random.choice([0, 1])
                #print ('mutating')

        genome = self.encode(luminosity)
        return icls(genome)

    def init_deap(self):
        creator.create("FitnessMax", base.Fitness, weights=(1.0, ))
        creator.create("Individual", list, fitness=creator.FitnessMax)
        self.steps = 0
        self.MAX_STEPS = 500
        self.toolbox = base.Toolbox()

        self.toolbox.register("random_num", random.choice, [0, 1])

        self.DIM = self.width * self.height

        self.toolbox.register(
            "individual",
            self.generate_individual,
            #tools.initRepeat,
            creator.Individual

            #self.toolbox.random_num,
            #n=self.DIM
        )

        print(self.toolbox.individual())

        self.toolbox.register("population", tools.initRepeat, list,
                              self.toolbox.individual)
        self.toolbox.register("mate", tools.cxTwoPoint)
        self.toolbox.register("select", tools.selBest)
        self.toolbox.register("evaluate", self.fitness)
        self.toolbox.register("mutate", self.mutate)
        self.pop = self.toolbox.population(n=100)


#    def fitness_(self, individual, data):
#        print (data)
#        print (individual)
#        match = 0
#        #for selected, bulbs in zip(individual, data):
#            #if selected:
#        for x in range(self.width):
#            for y in range(self.height):
#                if self.presence[x,y]>0 and individual[x,y]>0:
#                    match += 1
#        match_percentage = match / self.width * self.height
#        return match_percentage

#    def fitness(self, individual):#evalInd4
#        score = 0
#        #for selected, bulbs in zip(individual, data):
#            #if selected:
#        for y in range(self.height): # top left is (X=0,Y=0)
#            for x in range(self.width):
#
#                if individual[y*self.width+x]>0:
#                    #if self.presence_in_radius(1, x, y):
#                    presence_score = self.presence_in_radius2(1, x, y, individual)
#                    if self.bulbs[x,y] > -1 and presence_score > 0:
#                        score += presence_score
#                    else:
#                        score -= 1 #penalty for using a broken bulb
#        return (float(score),)

    def fitness(self, individual):  #evalInd4
        score = 0
        #for selected, bulbs in zip(individual, data):
        #if selected:
        for y in range(self.height):  # top left is (X=0,Y=0)
            for x in range(self.width):

                if individual[y * self.width + x] > 0:
                    #if self.presence_in_radius(1, x, y):
                    presence_score = self.presence_in_radius2(
                        1, x, y, individual)
                    if self.bulbs[y, x] > -1 and presence_score > 0:
                        score += presence_score
                    else:
                        score -= 1  #penalty for using a broken bulb
        return (float(score), )

    def presence_in_radius2(self, radius, x, y, individual):
        block = ((y - 1, x - 1), (y, x - 1), (y + 1, x - 1), (y + 1, x),
                 (y + 1, x + 1), (y, x + 1), (y - 1, x + 1), (y - 1, x)
                 )  # starts from left top

        presence_score = 0

        if self.presence[y, x] > 0:
            presence_score += int(
                self.weight['present'] *
                self.evaluation_unit)  #award for presence under the bulb
            #print ('+50')

        for point in block:
            if point[0] in range(self.height) and point[1] in range(
                    self.width):
                if self.presence[point[0], point[1]] > 0:
                    #and self.bulbs[point[0],point[1]] < 0: #individual[point[0]*self.width+point[1]] < 1:#someone present in radius and that area is dark
                    presence_score += int(0.30 * self.weight['present'] *
                                          self.evaluation_unit)

        return presence_score

    def mutate(self, individual):
        #print('Mutating')
        luminosity = self.decode(individual)

        for i in range(self.width):
            x = random.randint(self.width_bound[0], self.width_bound[1])
            y = random.randint(self.height_bound[0], self.height_bound[1])

            if (self.bulbs[y, x] > -1):
                luminosity[y, x] = random.choice([0, 1])

        #luminosity = self.encode (luminosity)
        self.update_individual(individual, luminosity)
        #for i in range(self.width):
        #    individual[random.randint(0,len(individual)-1)] = random.choice([0,1])
        return (individual, )

    def update_individual(self, individual, data):
        for y in range(self.height):
            for x in range(self.width):
                individual[y * self.width + x] = data[y, x]

    def encode(self, luminosity):
        return luminosity.flatten()

    def decode(self, individual):
        bulbs = np.zeros((self.height, self.width))
        for y in range(self.height):  # top left is (X=0,Y=0)
            for x in range(self.width):
                bulbs[y, x] = individual[y * self.width + x]
        return bulbs  #np.reshape(individual, (-1, self.width))

    #------------------ simulation loop ----------------
    def updatefig(self, *args):
        algorithms.eaMuPlusLambda(
            self.pop,
            self.toolbox,
            400,
            100,  #parents, children
            0.5,
            0.5,  #probabilities
            1)  #iterations

        top = sorted(self.pop, key=lambda x: x.fitness.values[0])[-1]
        fit = top.fitness.values[0]
        print('generation:{}, best fitness-: {}'.format(self.steps, fit))
        #print("TOP:", top)
        self.luminosity = self.decode(top)
        #print("DRAW:",self.luminosity)
        self.im.set_data(self.luminosity)
        #self.im.set_array(self.luminosity)
        #self.im.set_facecolors(self.luminosity)

        self.luminosity_im.set_data(
            self.luminosity_extrapolate(self.luminosity))
        #im.set_cmap("gray")
        #im.update()
        self.steps += 1
        if self.steps > self.MAX_STEPS:
            self.ani.event_source.stop()
            plt.grid()
            plt.grid()

        return self.im, self.luminosity_im

    def luminosity_extrapolate(self, luminosity):
        #there must some function doing this interpolation?
        for y in range(self.height_bound[0], self.height_bound[1]):
            for x in range(self.width_bound[0], self.width_bound[1]):
                if self.bulbs[y, x] > -1:
                    if luminosity[y, x] > 0:
                        block = ((y - 1, x - 1), (y, x - 1), (y + 1, x - 1),
                                 (y + 1, x), (y + 1, x + 1), (y, x + 1),
                                 (y - 1, x + 1), (y - 1, x))
                        for point in block:
                            if point[1] in range(
                                    self.width_bound[0],
                                    self.width_bound[1]) and point[0] in range(
                                        self.height_bound[0],
                                        self.height_bound[1]):
                                luminosity[point[0],
                                           point[1]] += 0.15 * luminosity[y, x]
                else:
                    luminosity[y, x] = 0

        return luminosity

    def run(self):
        self.ani = animation.FuncAnimation(self.fig,
                                           self.updatefig,
                                           interval=50,
                                           blit=True)
        plt.show()