graph: spath: Fix documentation indentation.

This commit is contained in:
Stefan van der Walt
2010-01-01 13:01:56 +02:00
parent b7706e6550
commit 93c90377c3
2 changed files with 56 additions and 45 deletions
+14 -9
View File
@@ -1,29 +1,34 @@
# -*- python -*-
import _mcp
cimport _mcp
cdef extern from "math.h":
double fabs(double f)
cdef class MCP_Diff(_mcp.MCP):
"""MCP_Diff(costs, offsets=None, fully_connected=True)
Find minimum-difference paths through an n-d costs array.
See the documentation for MCP for full details. This class differs from
See the documentation for MCP for full details. This class differs from
MCP in that the cost of a path is not simply the sum of the costs along
that path.
This class instead assumes that the cost of moving from one point to
another is the absolute value of the difference in the costs between the
two points
two points.
"""
def __init__(self, costs, offsets=None, fully_connected=True):
"""__init__(costs, offsets=None, fully_connected=True)
See class documentation.
"""
_mcp.MCP.__init__(self, costs, offsets, fully_connected)
self.use_start_cost = 0
cdef _mcp.FLOAT_C _travel_cost(self, _mcp.FLOAT_C old_cost, _mcp.FLOAT_C new_cost, _mcp.FLOAT_C offset_length):
cdef _mcp.FLOAT_C _travel_cost(self, _mcp.FLOAT_C old_cost,
_mcp.FLOAT_C new_cost,
_mcp.FLOAT_C offset_length):
return fabs(old_cost - new_cost)
+42 -36
View File
@@ -4,70 +4,76 @@ import _spath
def shortest_path(arr, reach=1, axis=-1, output_indexlist=False):
"""Find the shortest path through an n-d array from one side to another.
Parameters
----------
arr : ndarray of float64
reach : int, optional
By default (``reach = 1``), the shortest path can only move
one row up or down for every step it moves forward (i.e.,
the path gradient is limited to 1). `reach` defines the
number of elements that can be skipped along each non-axis
dimension at each step.
Parameters
----------
arr : ndarray of float64
reach : int, optional
By default (``reach = 1``), the shortest path can only move
one row up or down for every step it moves forward (i.e.,
the path gradient is limited to 1). `reach` defines the
number of elements that can be skipped along each non-axis
dimension at each step.
axis : int, optional
The axis along which the path must always move forward (default -1)
output_indexlist: bool, optional
See return value `p` for explanation.
Returns
-------
p : iterable of int
For each step along `axis`, the coordinate of the shortest path.
If `output_indexlist` is True, then the path is returned as a list of
n-d tuples that index into `arr`. If False, then the path is returned
as an array listing the coordinates of the path along the non-axis
dimensions for each step along the axis dimension. That is,
`p.shape == (arr.shape[axis], arr.ndim-1)` except that p is squeezed
before returning so if `arr.ndim == 2`, then
`p.shape == (arr.shape[axis],)`
cost : float
Cost of path. This is the absolute sum of all the
differences along the path.
"""
Returns
-------
p : iterable of int
For each step along `axis`, the coordinate of the shortest path.
If `output_indexlist` is True, then the path is returned as a list of
n-d tuples that index into `arr`. If False, then the path is returned
as an array listing the coordinates of the path along the non-axis
dimensions for each step along the axis dimension. That is,
`p.shape == (arr.shape[axis], arr.ndim-1)` except that p is squeezed
before returning so if `arr.ndim == 2`, then
`p.shape == (arr.shape[axis],)`
cost : float
Cost of path. This is the absolute sum of all the
differences along the path.
"""
# First: calculate the valid moves from any given position. Basically,
# always move +1 along the given axis, and then can move anywhere within
# always move +1 along the given axis, and then can move anywhere within
# a grid defined by the reach.
if axis < 0:
if axis < 0:
axis += arr.ndim
offset_ind_shape = (2*reach + 1,) * (arr.ndim - 1)
offset_indices = np.indices(offset_ind_shape) - reach
offset_indices = np.insert(offset_indices, axis, np.ones(offset_ind_shape), axis=0)
offset_indices = np.insert(offset_indices, axis,
np.ones(offset_ind_shape), axis=0)
offset_size = np.multiply.reduce(offset_ind_shape)
offsets = np.reshape(offset_indices, (arr.ndim, offset_size), order='F').T
# Valid starting positions are anywhere on the hyperplane defined by
# Valid starting positions are anywhere on the hyperplane defined by
# position 0 on the given axis. Ending positions are anywhere on the
# hyperplane at position -1 along the same.
non_axis_shape = arr.shape[:axis] + arr.shape[axis+1:]
non_axis_indices = np.indices(non_axis_shape)
non_axis_size = np.multiply.reduce(non_axis_shape)
start_indices = np.insert(non_axis_indices, axis, np.zeros(non_axis_shape), axis=0)
start_indices = np.insert(non_axis_indices, axis,
np.zeros(non_axis_shape), axis=0)
starts = np.reshape(start_indices, (arr.ndim, non_axis_size), order='F').T
end_indices = np.insert(non_axis_indices, axis, -np.ones(non_axis_shape), axis=0)
end_indices = np.insert(non_axis_indices, axis, -np.ones(non_axis_shape),
axis=0)
ends = np.reshape(end_indices, (arr.ndim, non_axis_size), order='F').T
# Find the minimum-cost path to one of the end-points
m = _spath.MCP_Diff(arr, offsets=offsets)
costs, traceback = m.find_costs(starts, ends, find_all_ends=False)
# Figure out which end-point was found
for end in ends:
cost = costs[tuple(end)]
if cost != np.inf:
break
traceback = m.traceback(end)
if not output_indexlist:
traceback = np.array(traceback)
traceback = np.concatenate([traceback[:,:axis], traceback[:,axis+1:]], axis=1)
traceback = np.concatenate([traceback[:,:axis], traceback[:,axis+1:]],
axis=1)
traceback = np.squeeze(traceback)
return traceback, cost