Beispiel #1
0
class Tank(object):
    def __init__(self, position):
        self.position = position
        self.rotation = random.random() * 2 * math.pi
        self.bearing = Vector(math.cos(self.rotation), math.sin(self.rotation))

        self.neural_net = NeuralNet(4, 1, 10, 3)
        self.fitness = 0

    def update(self, mines):

        mines = sorted(mines, key=lambda m: m.position.distance(self.position))

        # closest mine
        closest_mine = mines[0]

        # look_at vector
        look_at = Vector(self.position.x - closest_mine.position.x,
                         self.position.y - closest_mine.position.y)
        look_at.normalize()

        outputs = self.neural_net.update(
            [look_at.x, look_at.y, self.bearing.x, self.bearing.y])

        # rotation
        self.rotation += (outputs[0] - outputs[1]) * 0.01

        # speed
        self.speed = outputs[2]

        # calcuate new bearing
        degrees = self.rotation * 180 / math.pi
        self.bearing.x = -math.sin(degrees)
        self.bearing.y = math.cos(degrees)

        # calculate new position
        self.position.x += self.bearing.x * self.speed
        self.position.y += self.bearing.y * self.speed

        if self.position.x > WIDTH: self.position.x = 0
        if self.position.x < 0: self.position.x = WIDTH

        if self.position.y > HEIGHT: self.position.y = 0
        if self.position.y < 0: self.position.y = HEIGHT

        return closest_mine

    def __repr__(self):
        return 'Tank(position=[%s], bearing=[%s], fitness=%s)'\
                % (self.position, self.bearing, self.fitness)
Beispiel #2
0
class Tank(object):
    def __init__(self, position):
        self.position = position
        self.rotation = random.random() * 2 * math.pi
        self.bearing = Vector(math.cos(self.rotation), math.sin(self.rotation))

        self.neural_net = NeuralNet(4,1,10,3)
        self.fitness = 0

    def update(self, mines):

        mines = sorted(mines, key = lambda m: m.position.distance(self.position))

        # closest mine
        closest_mine = mines[0]

        # look_at vector
        look_at = Vector(self.position.x - closest_mine.position.x,
                         self.position.y - closest_mine.position.y)
        look_at.normalize()

        outputs = self.neural_net.update([look_at.x, look_at.y,
                                          self.bearing.x, self.bearing.y])

        # rotation
        self.rotation += (outputs[0] - outputs[1]) * 0.01

        # speed
        self.speed = outputs[2]

        # calcuate new bearing
        degrees = self.rotation * 180 / math.pi
        self.bearing.x = -math.sin(degrees)
        self.bearing.y = math.cos(degrees)

        # calculate new position
        self.position.x += self.bearing.x * self.speed
        self.position.y += self.bearing.y * self.speed

        if self.position.x > WIDTH: self.position.x = 0
        if self.position.x < 0: self.position.x = WIDTH

        if self.position.y > HEIGHT: self.position.y = 0
        if self.position.y < 0: self.position.y = HEIGHT

        return closest_mine

    def __repr__(self):
        return 'Tank(position=[%s], bearing=[%s], fitness=%s)'\
                % (self.position, self.bearing, self.fitness)
Beispiel #3
0
class Plane(object):
    def __init__(self, position, usage, speed, angle):
        self.position = position
        self.rotation = angle
        self.bearing = Vector(math.cos(self.rotation), math.sin(self.rotation))

        self.neural_net = NeuralNet(5, 1, 10, 1)

        self.usage = usage
        self.speed = speed

        self.reset()

    def reset(self):
        self.fitness = 0
        self.beam = None
        self.th = 0
        self.action = 0

    def update(self, beams):

        beams = sorted([
            b for b in beams
            if ((self.beam and b.load < self.beam.load) or self.beam == None)
            and b != self.beam
            and b.position.distance(self.position) <= b.radius
        ],
                       key=lambda b: b.load)

        # other beam
        next_beam = beams[0] if beams else None

        if self.beam and abs(self.beam.position.distance(
                self.position)) >= self.beam.radius:
            self.beam.load -= self.usage * 1.0 / self.beam.capacity
            self.beam = None
            if next_beam:
                self.th = 0

        sigmoid = lambda x, x0, a, b: a - a / (1 + np.exp(-b * (x - x0)))
        perf = lambda x: np.round(sigmoid(x, 0.9, 1.0, 3.0), 2)

        self.lc = self.beam.load if self.beam else 1

        self.ln = next_beam.load if next_beam else 1

        self.ld = perf(self.ln) - perf(self.lc)

        # current beam
        self.fc = 1 if self.beam else -1

        # next beam
        self.fn = 1 if next_beam else -1

        # time since handover
        if self.beam:
            self.th += 1
        max_th = 10
        self.th = min([self.th, max_th])

        state = [self.ld, self.fc, self.fn, self.th, self.speed]
        outputs = self.neural_net.update(state)
        self.action = outputs[0]

        if self.action < 0.5:
            # handover
            if self.beam:
                self.beam.load -= self.usage * 1.0 / self.beam.capacity
                if next_beam:
                    # minimize handovers
                    penalty = 2 * max([0, (max_th - self.th + 1)])
                    if next_beam.load < self.beam.load:
                        penalty *= 0.1
                    self.fitness -= penalty

            self.th = 0
            if next_beam:
                self.beam = next_beam
                self.beam.load += self.usage * 1.0 / self.beam.capacity
            else:
                if self.beam:
                    self.beam = None
                    self.fitness -= 50
                else:
                    # no current beam
                    pass
        else:
            if self.beam and next_beam:
                if self.beam.load > next_beam:
                    self.fitness -= 0.5 * self.th

        if self.beam:
            fitness = 100 * np.power(perf(self.beam.load), 1)
            self.fitness += fitness

        # calculate new position
        self.position.x += self.bearing.x * self.speed
        self.position.y += self.bearing.y * self.speed

        if self.position.x > WIDTH: self.position.x = 0
        if self.position.x < 0: self.position.x = WIDTH

        if self.position.y > HEIGHT: self.position.y = 0
        if self.position.y < 0: self.position.y = HEIGHT

        return self.beam

    def __repr__(self):
        return 'Beam(position=[%s], bearing=[%s], fitness=%s)'\
                % (self.position, self.bearing, self.fitness)