Commit a03f891a authored by Daniel Boeckenhoff's avatar Daniel Boeckenhoff Committed by Daniel Boeckenhoff
Browse files

paths work

parent d4100705
......@@ -332,9 +332,10 @@ class AbstractNdarray(np.ndarray):
Simply give the file name to save
>>> p.save(out_file.name)
>>> _ = out_file.seek(0)
>>> _ = out_file.seek(0) # this is only necessary in the test
>>> p1 = tfields.Points3D.load(out_file.name)
>>> assert p.equal(p1)
>>> assert p.coord_sys == p1.coord_sys
The fully nested structure of a TensorMaps object is reconstructed
>>> out_file_maps = NamedTemporaryFile(suffix='.npz')
......@@ -2161,7 +2162,138 @@ class TensorMaps(TensorFields):
"""
maps_list = tfields.lib.sets.disjoint_group_indices(self.maps[mp_idx])
return (0, maps_list)
return (mp_idx, maps_list)
def paths(self, mp_idx):
"""
Find the minimal amount of graphs building the original graph with
maximum of two links per node i.e.
o-----o o-----o
\ / \ /
\ / \ /
o--o--o o--o 8--o
| |
| = | + +
o o o
/ \ / \
/ \ / \
o o o o
where 8 is a duplicated node (one has two links and one has only one.)
Examples:
>>> import tfields
>>> import numpy as np
Ascii figure above:
>>> a = tfields.TensorMaps([[1, 0], [3, 0], [2, 2], [0, 4], [2, 4],
... [4, 4], [1, 6], [3, 6], [2, 2]],
... maps=[[[0, 2], [2, 4], [3, 4], [5, 4],
... [1, 8], [6, 4], [6, 7], [7, 4]]])
>>> paths = a.paths(0)
>>> assert paths[0].equal([[ 1., 0.],
... [ 2., 2.],
... [ 2., 4.],
... [ 0., 4.]])
>>> assert paths[0].maps[0].equal([[ 0., 1., 2., 3.]])
>>> assert paths[1].equal([[ 4., 4.],
... [ 2., 4.],
... [ 1., 6.],
... [ 3., 6.],
... [ 2., 4.]])
>>> assert paths[2].equal([[ 3., 0.],
... [ 2., 2.]])
Note:
The Longest path problem is a NP-hard problem.
"""
obj = self.cleaned()
flat_map = np.array(obj.maps[mp_idx].flat)
values, counts = np.unique(flat_map, return_counts=True)
counts = {v: n for v, n in zip(values, counts)}
# last is a helper
last = np.full(max(flat_map) + 1, -3, dtype=int)
duplicat_indices = []
d_index = len(obj)
for i, val in enumerate(flat_map.copy()):
if counts[val] > 2:
# The first two occurences are uncritical
if last[val] < -1:
last[val] += 1
continue
# Now we talk about nodes with more than two edges
if last[val] == -1:
# append a point and re-link
duplicat_indices.append(val)
flat_map[i] = d_index
last[val] = d_index
d_index += 1
else:
# last occurence of val was a duplicate, so we use the same
# value again.
flat_map[i] = last[val]
last[val] = -1
if duplicat_indices:
duplicates = obj[duplicat_indices]
obj = type(obj).merged(obj, duplicates)
obj.maps = [tfields.Tensors(flat_map.reshape(-1, *obj.maps[mp_idx].shape[1:]))]
paths = obj.parts(obj.disjoint_map(0))
# paths = [paths[2]] # this path did not work previously - debugging # with vessel
# remove duplicate map entries and sort
sorted_paths = []
for path in paths:
# find start index
values, counts = np.unique(path.maps[0].flat, return_counts=True)
first_node = None
for v, c in zip(values, counts):
if c == 1:
first_node = v
break
edges = [list(edge) for edge in path.maps[0]]
if first_node is None:
first_node = 0 # edges[0][0]
path = path[list(range(len(path))) + [0]]
found_first_node = False
for edge in edges:
if first_node in edge:
if found_first_node:
edge[edge.index(first_node)] = len(path) - 1
break
else:
found_first_node = True
# follow the edges until you hit the end
chain = [first_node]
visited = set()
n_edges = len(edges)
node = first_node
while len(visited) < n_edges:
for i, edge in enumerate(edges):
if i in visited:
continue
if node not in edge:
continue
# found edge
visited.add(i)
if edge.index(node) != 0:
edge = list(reversed(edge))
chain.extend(edge[1:])
node = edge[-1]
path = path[chain]
path.maps[0] = tfields.TensorFields([sorted(chain)])
sorted_paths.append(path)
paths = sorted_paths
return paths
class Container(AbstractNdarray):
......@@ -2200,6 +2332,21 @@ class Container(AbstractNdarray):
if __name__ == '__main__': # pragma: no cover
# a = tfields.TensorMaps([[1, 0], [3, 0], [2, 2], [0, 4], [2, 4],
# [4, 4], [1, 6], [3, 6], [2, 2]],
# maps=[[[0, 2], [2, 4], [3, 4], [5, 4],
# [1, 8], [6, 4], [6, 7], [7, 4]]])
# a = tfields.TensorMaps([[0, 0], [1, 1], [2, 2], [0, 0], [4, 4], [5, 5], [0, 0]],
# maps=[[[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]])
# a = tfields.TensorMaps([[0, 0], [1, 1], [2, 2], [0, 0], [4, 4], [5, 5], [0, 0],
# [3, 3], [8, 8], [5, 5], [4, 4], [5,5],[8,8]],
# maps=[[[1, 2], [2, 3], [3, 4], [0, 1], [4, 5], [7, 8], [9, 10], [11, 12]]])
# paths = a.paths(0)
# print([p for p in paths])
# print([p.maps for p in paths])
# quit()
import doctest
doctest.testmod()
# doctest.run_docstring_examples(TensorFields.__getitem__, globals())
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment