dna: Change suit pathing not to depend on ctypes, but still use it if available.
This commit is contained in:
parent
9030daccf9
commit
9d1292072b
1 changed files with 44 additions and 16 deletions
|
@ -1,6 +1,35 @@
|
||||||
from DNAParser import *
|
from DNAParser import *
|
||||||
import DNAStoreSuitPoint
|
import DNAStoreSuitPoint
|
||||||
import ctypes
|
|
||||||
|
# Helpers for uint16 bytearray access:
|
||||||
|
try:
|
||||||
|
import ctypes
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# No ctypes! Use a slightly slower class based on bytearray().
|
||||||
|
|
||||||
|
class uint16array(object):
|
||||||
|
def __init__(self, size, initial=None):
|
||||||
|
if initial is None:
|
||||||
|
self.__array = bytearray(size * 2)
|
||||||
|
else:
|
||||||
|
self.__array = bytearray(initial for x in xrange(size * 2))
|
||||||
|
|
||||||
|
def __getitem__(self, index):
|
||||||
|
hi, lo = self.__array[index*2:index*2+2]
|
||||||
|
return hi*256 + lo
|
||||||
|
|
||||||
|
def __setitem__(self, index, value):
|
||||||
|
self.__array[index*2:index*2+2] = divmod(value, 256)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# ctypes! Wrap the uint16 array type in a convenience function:
|
||||||
|
|
||||||
|
def uint16array(size, initial=None):
|
||||||
|
array = (ctypes.c_uint16 * size)()
|
||||||
|
if initial is not None:
|
||||||
|
ctypes.memset(array, initial, ctypes.sizeof(array))
|
||||||
|
return array
|
||||||
|
|
||||||
class DNASuitGraph(object):
|
class DNASuitGraph(object):
|
||||||
def __init__(self, points, edges):
|
def __init__(self, points, edges):
|
||||||
|
@ -11,12 +40,11 @@ class DNASuitGraph(object):
|
||||||
self._point2outboundEdges = {}
|
self._point2outboundEdges = {}
|
||||||
self._point2inboundEdges = {}
|
self._point2inboundEdges = {}
|
||||||
|
|
||||||
self._table = (ctypes.c_uint16*4 * len(points)*len(points))()
|
self._table = uint16array(4 * len(points)*len(points), 0xFF)
|
||||||
ctypes.memset(self._table, 0xFF, ctypes.sizeof(self._table))
|
|
||||||
|
|
||||||
if points:
|
if points:
|
||||||
highestId = max(point.id for point in points)
|
highestId = max(point.id for point in points)
|
||||||
self._id2index = (ctypes.c_uint16 * (highestId+1))()
|
self._id2index = uint16array(highestId+1)
|
||||||
|
|
||||||
for i,point in enumerate(points):
|
for i,point in enumerate(points):
|
||||||
self._pointId2point[point.id] = point
|
self._pointId2point[point.id] = point
|
||||||
|
@ -32,7 +60,7 @@ class DNASuitGraph(object):
|
||||||
self._point2outboundEdges.setdefault(a, []).append(edge)
|
self._point2outboundEdges.setdefault(a, []).append(edge)
|
||||||
self._point2inboundEdges.setdefault(b, []).append(edge)
|
self._point2inboundEdges.setdefault(b, []).append(edge)
|
||||||
|
|
||||||
visited = (ctypes.c_uint16*len(points))()
|
visited = bytearray(len(points))
|
||||||
for i, point in enumerate(points):
|
for i, point in enumerate(points):
|
||||||
for neighbor in self.getOriginPoints(point):
|
for neighbor in self.getOriginPoints(point):
|
||||||
self.addLink(neighbor, point, 1, point, False, visited)
|
self.addLink(neighbor, point, 1, point, False, visited)
|
||||||
|
@ -48,16 +76,16 @@ class DNASuitGraph(object):
|
||||||
|
|
||||||
visited[pointIndex] += 1
|
visited[pointIndex] += 1
|
||||||
|
|
||||||
entry = self._table[pointIndex][destinationIndex]
|
entry = pointIndex*len(self.points) + destinationIndex
|
||||||
|
|
||||||
existingDistance = entry[3] if unbounded else entry[1]
|
existingDistance = self._table[entry*4 + 3] if unbounded else self._table[entry*4 + 1]
|
||||||
if distance < existingDistance:
|
if distance < existingDistance:
|
||||||
if not unbounded:
|
if not unbounded:
|
||||||
entry[0] = neighborIndex
|
self._table[entry*4 + 0] = neighborIndex
|
||||||
entry[1] = distance
|
self._table[entry*4 + 1] = distance
|
||||||
else:
|
else:
|
||||||
entry[2] = neighborIndex
|
self._table[entry*4 + 2] = neighborIndex
|
||||||
entry[3] = distance
|
self._table[entry*4 + 3] = distance
|
||||||
|
|
||||||
# We've just updated our link. If we're traversable, announce the
|
# We've just updated our link. If we're traversable, announce the
|
||||||
# new route to all of our neighbors:
|
# new route to all of our neighbors:
|
||||||
|
@ -97,12 +125,12 @@ class DNASuitGraph(object):
|
||||||
path = [startPoint]
|
path = [startPoint]
|
||||||
|
|
||||||
while at != end or minPathLen > 0:
|
while at != end or minPathLen > 0:
|
||||||
boundedNext, boundedDistance, unboundedNext, unboundedDistance = self._table[at][end]
|
entry = at*len(self.points) + end
|
||||||
|
|
||||||
if minPathLen <= boundedDistance <= maxPathLen:
|
if minPathLen <= self._table[entry*4 + 1] <= maxPathLen:
|
||||||
at = boundedNext
|
at = self._table[entry*4 + 0]
|
||||||
elif unboundedDistance <= maxPathLen:
|
elif self._table[entry*4 + 3] <= maxPathLen:
|
||||||
at = unboundedNext
|
at = self._table[entry*4 + 2]
|
||||||
else:
|
else:
|
||||||
# No path exists!
|
# No path exists!
|
||||||
return None
|
return None
|
||||||
|
|
Loading…
Reference in a new issue