여러 노드에 장애물이있는 주어진 격자에서 해밀턴 경로를 찾으려고합니다. 내 문제는 내 코드가 며칠 동안 실행되었으며 아직 끝나지 않은 것입니다. 이 문제는 NP-Complete 지역에 있지만, 내가 보는 것에서는 충분한 시간이 부족하다는 것이 내 문제인지 확신 할 수 없습니다.장애물 격자 및 파이썬 재귀 경로의 해밀턴 경로
필자의 접근 방식은 파이썬에서 재귀를 사용하여 그리드를 통해 만들 수있는 모든 왼쪽, 오른쪽, 위, 아래 움직임의 가능한 순서로 Depth First Search를 수행하는 것입니다. 나는 해밀턴 경로 문제에 대한 다른 방법을 연구했지만, 내가 한 일에 더 복잡했고, 작은 그리드가 필요하다고 생각하지 않았다.
다음은 내가 찾고있는 그리드이다. 0은 열린 노드이고 1은 장애물이며 S는 시작입니다.
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,1,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,1,0,0,1,0,1,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,S]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,1,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
다음은 실행중인 함수의 현재 그리드 출력이며, 1은 현재 방문한 노드를 나타냅니다.
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1]
[1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 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, 0, 1, 1, 1, 1, 0, 0, 1, 0]
[1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0]
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1]
그러나 초당 약 50000 단계에서도 코드는 결코 오른쪽 하단 모서리를 검사하는 것을 멈추지 않는 것처럼 보입니다. 예를 들어, 노드 (3, 1) 및 (3, 2)에서의 2 개의 O는 결코 도달되지 않았다.
이렇게하면 다음과 같은 질문이 생깁니다. 13x9 그리드 만 시도하는 경우에도 NP-Hard의 표준 증상입니까? 파이썬 재귀 제한에 도달하여 내 코드가 끝내 동일한 DFS 분기를 다시 실행하게합니까? 내가 놓친 다른 것이 있습니까?
이 내 검색 방법의 단순화 된 버전입니다 : 하나는 해밀턴 경로를 형성 할 때까지
#examines options of steps at current marker cell and iterates path attempts
def tryStep():
global path #list of grid movements
global marker #current cell in examination
set marker to traveled
if whole grid is Traveled:
print path data
end program
#map is incomplete, advance a step
else:
if can move Up:
repeat tryStep()
if can move left:
repeat tryStep()
if can move down:
repeat tryStep()
if can move right:
repeat tryStep()
#Failure condition reached, must backup a step
set marker cell to untraveled
if length of path is 0:
print 'no path exists'
end program
last = path.pop()
if last == "up":
move marker cell down
if last == "left":
move marker cell right
if last == "down":
move marker cell up
if last == "right":
move marker cell left
return
따라서, 코드, 그리드를 통해 가능한 모든 경로를 통해 반복해야한다.
'''
Created on Aug 30, 2014
@author: Owner
'''
#Search given grid for hamiltonian path
import datetime
#takes grid cord and returns value
def getVal(x,y):
global mapWidth
global mapHeight
global mapOccupancy
if (((x < mapWidth) and (x >-1)) and (y < mapHeight and y >-1)):
return mapOccupancy[y][x]
else:
#print "cell not in map"
return 1
return
#sets given coord cell value to visted
def travVal(x,y):
global mapWidth
global mapHeight
global mapOccupancy
if (((x < mapWidth) and (x >-1)) and ((y < mapHeight) and (y >-1)))== True:
mapOccupancy[y][x] = 1
else:
#print "cell not in map"
return 1
return
#sets given coord cell value to open
def clearVal(x,y):
if (((x < mapWidth) and (x > -1)) and ((y < mapHeight) and (y > -1)))==True:
mapOccupancy[y][x] = 0
else:
#print "cell not in map"
return 1
return
#checks if entire map has been traveled
def mapTraveled():
isFull = False
endLoop= False
complete = True
for row in mapOccupancy:
if endLoop ==True:
isFull = False
complete = False
break
for cell in row:
if cell == 0:
complete = False
endLoop = True
break
if complete == True:
isFull = True
return isFull
#examines options of steps at current marker cell and iterates path attempts
def tryStep():
global path
global marker
global goalCell
global timeEnd
global timeStart
global printCount
travVal(marker[0],marker[1])
printCount += 1
#only print current map Occupancy every 100000 steps
if printCount >= 100000:
printCount = 0
print ''
print marker
for row in mapOccupancy:
print row
if mapTraveled():
print 'map complete'
print "path found"
print marker
print path
for row in mapOccupancy:
print row
print timeStart
timeEnd= datetime.datetime.now()
print timeEnd
while True:
a=5
#if map is incomplete, advance a step
else:
#Upwards
if getVal(marker[0],marker[1]-1) == 0:
marker = [marker[0],marker[1]-1]
#print "step: " + str(marker[0])+' '+ str(marker[1])
path.append('up')
tryStep()
#left wards
if getVal(marker[0]-1,marker[1]) == 0:
marker = [marker[0]-1,marker[1]]
#print "step: " + str(marker[0])+' '+ str(marker[1])
path.append('left')
tryStep()
# down wards
if getVal(marker[0],marker[1]+1) == 0:
marker = [marker[0],marker[1]+1]
#print "step: " + str(marker[0])+' '+ str(marker[1])
path.append('down')
tryStep()
#right wards
if getVal(marker[0]+1,marker[1]) == 0:
marker = [marker[0]+1,marker[1]]
# print "step: " + str(marker[0])+' '+ str(marker[1])
path.append('right')
tryStep()
#Failure condition reached, must backup steps
clearVal(m[0],m[1])
last = path.pop()
#print 'backing a step from:'
#print last
if last == "up":
marker = [marker[0],marker[1]+1]
if last == "left":
marker = [marker[0]+1,marker[1]]
if last == "down":
marker = [marker[0],marker[1]-1]
if last == "right":
marker = [marker[0]-1,marker[1]]
return
if __name__ == '__main__':
global timeStart
timeStart = datetime.datetime.now()
print timeStart
global timeEnd
timeEnd= datetime.datetime.now()
global printCount
printCount = 0
global mapHeight
mapHeight = 9
global mapWidth
mapWidth =13
#occupancy grid setup
r0= [0,0,0,0,0,0,0,0,0,0,0,0,0]
r1= [0,0,0,0,0,0,1,0,0,0,0,0,0]
r2= [0,0,0,0,0,0,0,0,0,0,0,0,0]
r3= [0,0,0,1,0,0, 1 ,0,1,0,0,0,0]
r4= [0,0,0,0,0,0,0,0,0,0,0,0, 0]
r5= [0,0,0,0,0,0,0,0,0,0,0,0,0]
r6= [0,0,0,0,0,0,1,0,0,0,0,0,0]
r7= [0,0,0,0,0,0,0,0,0,0,0,0,0]
r8= [0,0,0,0,0,0,0,0,0,0,0,0,0]
global mapOccupancy
mapOccupancy = [r0,r1,r2,r3,r4,r5,r6,r7,r8]
#record of current trail attempt
global path
path = []
#marker for iterating through grid
global marker
start = [12,4]
#start =[0,2]
m = start
global goalCell
goalCell = [6,3]
print marker
tryStep()
#no path avalible if this point is reached
print'destination is unreachable'
print 'last path: '
for row in mapOccupancy:
print row
print path
print m
print mapOccupancy
print timeStart
timeEnd= datetime.datetime.now()
print timeEnd
재귀 한계에 도달하면 예외가 발생하므로 조용히 무시하지 않는 한 여기에 해당하지 않아야합니다. – uselpa
2^(13 * 9)는 매우 거칠지 만 가능한 경로의 수에 대한 합리적인 추정으로 보입니다. 매우 큰 숫자입니다. – wookie919