17
17
and apply the following steps:
18
18
19
19
Finding "row's max.", a column vector equal to [9, 5, 7], and use if to compute a boolean
20
- matrix in which each cell (i,j) is `True` if this cell's value is the maximum value it
21
- its own row. This second operation is done using `match `:
22
- [ 9 ] match [ 9 8 7 ] = [ O . . ]
23
- [ 5 ] [ 5 3 2 ] [ O . . ]
24
- [ 7 ] [ 6 6 7 ] [ . . O ]
20
+ matrix in which each cell (i,j) is `True` if this cell's value is the maximum value of
21
+ its own row. This second operation is done using `flag_projected_matches `:
22
+ [ 9 ] flag_projected_matches [ 9 8 7 ] = [ O . . ]
23
+ [ 5 ] [ 5 3 2 ] [ O . . ] = A
24
+ [ 7 ] [ 6 6 7 ] [ . . O ]
25
25
26
+ ("O" match, "." otherwise)
26
27
27
28
The same is done for "column's min.", we first compute the row vector representing min.
28
- column values and then compute the boolean mask using `match `:
29
- [ 5 3 2 ] match [ 9 8 7 ] = [ . . . ]
30
- [ 5 3 2 ] [ O O O ]
31
- [ 6 6 7 ] [ . . . ]
29
+ column values and then compute the boolean mask using `flag_projected_matches `:
30
+ [ 5 3 2 ] flag_projected_matches [ 9 8 7 ] = [ . . . ]
31
+ [ 5 3 2 ] [ O O O ] = B
32
+ [ 6 6 7 ] [ . . . ]
32
33
33
-
34
- Once we have these two boolean matrix, we just need to find cells where both conditions
35
- are met to find Saddle points (using the logical `&` operator):
34
+ Once we have these two boolean matrix, in order to find Saddle points we just need
35
+ to find cells for which both conditions (A and B) are met (using the logical `&` operator):
36
36
[ O . . ] & [ . . . ] = [ . . . ]
37
37
[ O . . ] [ O O O ] [ O . . ]
38
38
[ . . O ] [ . . . ] [ . . . ]
39
39
40
40
Finally, Saddle points coordinates are retrieved using the `where` method on this last matrix:
41
- [ . . . ]
42
- [ O . . ] where {(1, 0)}
43
- [ . . . ]
41
+ [ . . . ]
42
+ where [ O . . ] = {(1, 0)}
43
+ [ . . . ]
44
44
"""
45
45
from enum import Enum
46
46
from collections import namedtuple
@@ -52,9 +52,9 @@ def saddle_points(data):
52
52
and less than or equal to every element in its column.
53
53
"""
54
54
matrix = Matrix2D (data )
55
- rows_maximums = matrix .axis_map_reduce (Matrix2D .Axes .ROW , max )
55
+ rows_maximums = matrix .axis_reduce (Matrix2D .Axes .ROW , max )
56
56
is_max_in_row = matrix .flag_projected_matches (rows_maximums )
57
- columns_minimums = matrix .axis_map_reduce (Matrix2D .Axes .COLUMN , min )
57
+ columns_minimums = matrix .axis_reduce (Matrix2D .Axes .COLUMN , min )
58
58
is_min_in_col = matrix .flag_projected_matches (columns_minimums )
59
59
is_saddle = is_max_in_row & is_min_in_col
60
60
saddle_indexes = set (is_saddle .where ())
@@ -121,7 +121,7 @@ def T(self):
121
121
self ._transpose = Matrix2D (list (map (list , zip (* self ))))
122
122
return self ._transpose
123
123
124
- def axis_map_reduce (self , axis , function ):
124
+ def axis_reduce (self , axis , function ):
125
125
"""Reduce the matrix using `function`. The optional parameter `axis`
126
126
allows to reduce only along the given axis.
127
127
@@ -138,17 +138,17 @@ def axis_map_reduce(self, axis, function):
138
138
def flag_projected_matches (self , vector ):
139
139
"""Each row/column of the input matrix is compared to the input `vector`:
140
140
141
- Row matching:
141
+ Rows matching:
142
142
143
- [1 2 3] match [1 5 3] = [O . O]
144
- [4 5 3] [. O O]
143
+ [1 2 3] flag_projected_matches [1 5 3] = [O . O]
144
+ [4 5 3] [. O O]
145
145
146
- Column matching:
146
+ Columns matching:
147
147
148
- [1 2 3] match [1] = [O . .]
149
- [4 5 6] [5] [. O .]
148
+ [1 2 3] flag_projected_matches [1] = [O . .]
149
+ [4 5 6] [5] [. O .]
150
150
151
- O shows matched items, . shows unmatched items (either it matched the vector/scalar or not).
151
+ O shows matched items, . shows unmatched items (either it matched the vector or not).
152
152
The function returns a matrix where matched cells contain `True` while unmatched ones contain `False`.
153
153
"""
154
154
return self .map_cells (lambda coordinates , cell : cell == vector [vector .projected_coordinates (coordinates )])
@@ -165,8 +165,8 @@ def all(self, condition=lambda x: x):
165
165
all (condition (cell ) for _ , cell in self .enumerate_cells ())
166
166
167
167
def map_cells (self , function ):
168
- """Returns a matrix in which `function` has been applied to all element .
169
- `function` will be called with three arguments (on each cell):
168
+ """Returns a matrix in which `function` has been applied to all elements .
169
+ `function` will be called with the three following arguments (on each cell):
170
170
- the `cell` value,
171
171
- the row index and the
172
172
- the column index.
@@ -186,9 +186,7 @@ def __eq__(self, other):
186
186
return False
187
187
return self .map_cells (lambda coordinates , cell : cell == other [coordinates ]).all ()
188
188
189
- def _binary_operation (self , other , operation = None ):
190
- if not operation :
191
- raise ValueError ("Please provide a function." )
189
+ def _binary_operation (self , other , operation ):
192
190
return Matrix2D ([[operation (a , b ) for (a , b ) in zip (* rows )] for rows in zip (self , other )])
193
191
194
192
def __and__ (self , other ):
0 commit comments