Skip to content

Commit

Permalink
Make Interface.get_common_ports() faster using set operations per #41.
Browse files Browse the repository at this point in the history
  • Loading branch information
lebedov committed Mar 18, 2015
1 parent 517cdf2 commit fa0416b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 18 deletions.
32 changes: 18 additions & 14 deletions neurokernel/pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,25 +598,29 @@ def get_common_ports(self, a, i, b, t=None):
-----
The number of levels of the returned port identifiers is equal to the
maximum number of levels of this Interface instance.
"""
# If the number of levels in the indexes of his interface and i differ,
# the index will be padded with an extra level (see
# _merge_on_interfaces() method); we therefore need to discard any pad
# levels here:
data_merged = self._merge_on_interfaces(a, i, b)
for n in xrange(max(self.num_levels, i.num_levels)-1,
min(self.num_levels, i.num_levels)-1, -1):
data_merged.reset_index(str(n), inplace=True)
data_merged.drop(str(n), axis=1, inplace=True)
The order of the returned port identifiers is not guaranteed.
"""

if t is None:
return data_merged.index.tolist()
x = self.data[self.data['interface'] == a]
y = i.data[i.data['interface'] == b]
else:
return data_merged[data_merged.apply(lambda row: \
(row['type_x'] == row['type_y']) and \
(row['type_x'] == t), axis=1)].index.tolist()
x = self.data[(self.data['interface'] == a) & (self.data['type'] == t)]
y = i.data[(i.data['interface'] == b) & (i.data['type'] == t)]
if isinstance(x.index, pd.MultiIndex):
x_list = [tuple(a for a in b if a != '') \
for b in x.index]
else:
x_list = [(a,) for a in x.index]
if isinstance(y.index, pd.MultiIndex):
y_list = [tuple(a for a in b if a != '') \
for b in y.index]
else:
y_list = [(a,) for a in y.index]

return list(set(x_list).intersection(y_list))

def is_compatible(self, a, i, b, allow_subsets=False):
"""
Check whether two interfaces can be connected.
Expand Down
42 changes: 38 additions & 4 deletions tests/test_pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,16 @@ def test_equals(self):
assert not j.equals(i)

def test_get_common_ports(self):
# Without type:
# Without type, single level:
i = Interface('/foo,/bar,/baz')
i['/*', 'interface'] = 0
j = Interface('/bar,/baz,/qux')
j['/*', 'interface'] = 0
assert i.get_common_ports(0, j, 0, 'spike') == []
self.assertItemsEqual(i.get_common_ports(0, j, 0),
[('bar',), ('baz',)])

# Without type, multiple levels:
i = Interface('/foo[0:6]')
i['/*', 'interface'] = 0
j = Interface('/foo[3:9]')
Expand All @@ -61,7 +70,15 @@ def test_get_common_ports(self):
self.assertItemsEqual(i.get_common_ports(0, j, 0),
[('foo', 3), ('foo', 4), ('foo', 5)])

# With type:
# With type, single level:
i = Interface('/foo,/bar,/baz')
i['/foo,/bar', 'interface', 'type'] = [0, 'spike']
j = Interface('/bar,/baz,/qux')
j['/bar,/baz', 'interface', 'type'] = [0, 'spike']
self.assertItemsEqual(i.get_common_ports(0, j, 0, 'spike'),
[('bar',)])

# With type, multiple levels:
i = Interface('/foo[0:6]')
i['/foo[3,4]', 'interface', 'type'] = [0, 'spike']
j = Interface('/foo[3:9]')
Expand All @@ -71,7 +88,16 @@ def test_get_common_ports(self):


def test_get_common_ports_unequal_num_levels(self):
# Without type:
# Without type, some with only one level:
i = Interface('/foo[0:6],/bar')
i['/*', 'interface'] = 0
j = Interface('/bar,/baz')
j['/*', 'interface'] = 0
assert i.get_common_ports(0, j, 0, 'spike') == []
self.assertItemsEqual(i.get_common_ports(0, j, 0),
[('bar',)])

# Without type, more than one level:
i = Interface('/foo[0:6],/bar[0:2]/baz')
i['/*', 'interface'] = 0
j = Interface('/foo[3:9]')
Expand All @@ -80,7 +106,15 @@ def test_get_common_ports_unequal_num_levels(self):
self.assertItemsEqual(i.get_common_ports(0, j, 0),
[('foo', 3), ('foo', 4), ('foo', 5)])

# With type:
# With type, some with only one level:
i = Interface('/foo[0:6],/bar,/baz')
i['/foo[3,4],/bar', 'interface', 'type'] = [0, 'spike']
j = Interface('/bar,/baz,/qux')
j['/bar,/baz', 'interface', 'type'] = [0, 'spike']
self.assertItemsEqual(i.get_common_ports(0, j, 0, 'spike'),
[('bar',)])

# With type, more than one level:
i = Interface('/foo[0:6],/bar[0:2]/baz')
i['/foo[3,4]', 'interface', 'type'] = [0, 'spike']
j = Interface('/foo[3:9]')
Expand Down

0 comments on commit fa0416b

Please sign in to comment.