2016-06-28 4 views
0

장애물이있는 지형에서 최적의 경로 찾기 알고리즘을 준비 중입니다. 지금까지 Dijsktra와 A * 알고리즘을 구현했습니다. 이제 유전자 알고리즘을 구현해야하고 문제가 있습니다.최적의 경로를 찾기 위해 그리드 보드에 유전 알고리즘을 어떻게 구현합니까?

먼저지도 표현이 어떻게 보이는지 보여 드리겠습니다. 지형은 7 가지 종류가 있습니다 (0- 시작, 7- 끝, 통과 할 수있는 1-4 법선, 5-6 통과 할 수 없음). 내가 어떻게 때문에 내지도의 이론적 인 관점에서 유전자 알고리즘을 구현하는 아무 생각이

class Graph(): 
    def __init__(self, x=10, y=10): 
     self.width = x 
     self.height = y 
     self.board = ((1, 1, 1, 5, 1, 1, 1, 1, 1, 7), 
         (1, 1, 1, 5, 1, 1, 1, 1, 1, 1), 
         (1, 1, 1, 5, 1, 5, 1, 1, 1, 1), 
         (0, 1, 1, 1, 1, 5, 1, 1, 1, 1), 
         (1, 1, 1, 1, 1, 5, 1, 1, 1, 1), 
         (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
         (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
         (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
         (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
         (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)) 
     self.time = {0: None, 
        1: 1, 
        2: 4, 
        3: 7, 
        4: 4, 
        7: 1} 
    def cost(self, id): 
     (x, y)= id 
     return self.time.get(self.board[y][x]) 

    def canPass(self, id): 
     (x, y) = id 
     return self.board[y][x] != 5 and self.board[y][x] != 6 and self.board[y][x] != 0 

    def inBounds(self, id): 
     (x, y) = id 
     return 0 <= x < self.width and 0 <= y < self.height 

    def neighbors(self, id): 
     (x, y) = id 
     nodes = [(x-1, y), (x, y-1), (x+1, y), (x, y+1)] 
     nodes = filter(self.inBounds, nodes) 
     nodes = filter(self.canPass, nodes) 
     return nodes 

: 여기 파이썬에서 그것을위한 코드 (코드의 가장 중요한 부분은 문제가 기능 neighbors 이해하기 위해, 제 생각에)입니다 이웃 표현과 나는 그들을 바꿀 수 없다.

내가 무슨 짓을 :

내가 거의 그 비용을 확인하지 않고 처음부터 끝까지 가장 쉬운 연결을 찾을 수있는 * 내 (A)의 수정을 사용하여 인구를 시작 준비했다. 여기에 코드가 있습니다

def heuristic(a, b): 
    (x1, y1) = a 
    (x2, y2) = b 
    return abs(x1 - x2) + abs(y1 - y2) 

def StartingPopulation(graph, start, goal): 
    (x, y) = start 
    frontier = PriorityQueue() 
    frontier.put(start, 0) 
    came_from = {} 
    cost_so_far = [[0 for i in xrange(10)] for j in xrange(10)] 
    came_from[start] = None 
    cost_so_far[y][x] = 0 
    while not frontier.empty(): 
     current = frontier.get() 
     (y1, x1) = current 
     if (y1, x1) == goal: 
      break 
     for next in graph.neighbors(current): 
      new_cost = cost_so_far[x1][y1] + graph.cost(next) 
      (y2, x2) = next 
      if cost_so_far[x2][y2] == 0 or new_cost < cost_so_far[x2][y2]: 
       cost_so_far[x2][y2] = new_cost 
       priority = new_cost + heuristic(goal, next) 
       frontier.put(next, priority) 
       came_from[next] = current 
    return came_from, cost_so_far 

그게 제가 발명 한 전부입니다. 나는 선택, 교차 및 돌연변이와 같은 유전자 알고리즘에 대해 다른 단계를 수행하는 방법을 모릅니다. 나는 당신이 나를 인도하고 약간의 힌트를 줄 수 있기를 바란다. (필요한 것이 무엇인지에 대한 완전한 코드가 있다면 그것도 확인하고 배우는 것이 좋다.)

+2

개인적인 견해는 ** A ***와 같은 것을 사용할 수있을 때마다 유전자 알고리즘보다는 그걸 고수해야한다는 것입니다. 이를 시도한 특별한 이유가 있습니까? –

답변

4

2D 그리드를위한 간단한 GA 기반의 방법은 염색체를 분별하는 것이다. 이동로 (이진 스트링), 예 :

00 = down 
10 = left 
01 = right 
11 = up 

chromosome 주어진 run(chromosome) 기능, (지도 코드 0) 시작점에서 동작을 수행하고, 최종 점을 리턴 도달 :

(f_y, f_x) = run(chromosome) 

Th 또한

def fitness(chromosome): 
    final = run(chromosome) 
    return 1.0 - (distance(final, goal)/max_possible_distance) 

나 :

# Returns negative values. 
# Depending on the selection scheme, it can be problematic. 
def fitness(chromosome): 
    final = run(chromosome) 
    return -distance(final, goal) 

이 두 피트니스 기능이 더 낫다 가정 전자 피트니스 기능은 목표 지점까지의 거리입니다. 지금

예 :

  1. SF 도달 마지막 포인트이며, 출발점은 G
  2. chromosome00 00 01 01 00 00 00 01 01 11 즉 인 목표점과 * 벽인↓ ↓ → → ↓ ↓ ↓ → → ↑
  3. run(S, chromosome)는 다음과 같은 방식으로 작동합니다

    기능은 단순히 불가능 이동

  4. 피트니스가 -2

표준 One point crossover/two points crossover (또는 다른 형태의)입니다 무시

|---|---|---|---|---|---| 
| S | |***| | | | 
|-|-|---|---|---|---|---| 
| | | |***| | | | 
|-|-|---|---|---|---|---| 
| +---+->***| |***|***| 
|---|-|-|---|---|---|---| 
| | | |***| F | | G | 
|---|-|-|---|-^-|---|---| 
| | +-------+ |***| | 
|---|-|-|---|---|---|---| 
사용할 수 있습니다, 예를 :

ONE POINT CROSSOVER 

00 00 01 01 00 00|00 01 01 11  PARENTS 
11 11 01 01 00 00|01 01 11 01 
-----------------^----------- 
00 00 01 01 00 00|01 01 11 01  OFFSPRING 
11 11 01 01 00 00|00 01 01 11 
대신 (위의 예에서와 같이) 불가능 움직임을 무시

  • , 계획

    |---|---|---|---|---|---| 
    | S | |***| | | | 
    |-|-|---|---|---|---|---| 
    | | | |***| | | | 
    |-|-|---|---|---|---|---| 
    | +---+->***| |***|***| 
    |---|-|-|---|---|---|---| 
    | | | |***| +-> F | G | 
    |---|-|-|---|-|-|---|---| 
    | | +-------+ |***| | 
    |---|---|---|---|---|---| 
    

    참고 :

    첫 번째 아이 (00 00 01 01 00 00 01 01 11 01)는 부모보다 큰 피트니스 (-1)가 유전자 치료 연산자을 사용하여 악의적 인 이동을 지우고 임의의 이동을 추가하여 염색체를 채 웁니다 (더 복잡하지만 사용 가능한 전체 길이를 활용 함).

  • 일반적으로 GA에서는 염색체의 길이가 고정되어 있으므로 길이가 최적 경로보다 30 ~ 40 % 길면 좋습니다.
  • 목표까지의 경로는 최대로 간주됩니다.

    def fitness(chromosome): 
         final = run(chromosome) 
         return -distance(final, goal) - length_of_path(chromosome)/100.0 
    
  • 완전히 다른 접근 라이언 레이에 의해 Using a Genetic Algorithm to Explore A*-like Pathfinding Algorithms에서 A * (자세한 내용을 최적화하기 위해 GA를 사용 : 가장 좋은 경로를 검색하면 예를 들어, 최단 경로에서 편차 피트니스 함수에 페널티 용어를 추가 필요 , Sushil J. Louis와 Chris Miles)에게 감사드립니다.

  • 인공 지능의 관점에서 가장 흥미로운 세 번째 옵션은 Genetic Programming입니다 (예를 들어, Evolving Pathfinding Algorithms Using Genetic Programming 릭 스트롬 참조).
  • 이것은 GA의 유연성의 좋은 예이지만 A *는 더 나은 방법입니다.