From 77e6d52c6ef2e0ce22b53b72f9ecf45a8fe915a6 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Sat, 7 Dec 2019 23:49:34 -0600 Subject: [PATCH 01/11] corrects the usage of isl_aff_move_dims --- islpy/__init__.py | 5 +++-- test/test_isl.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index d5dd79a..7257ed0 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1145,11 +1145,12 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): if src_dt == tgt_dt: assert src_idx > tgt_idx - # isl requires move_dims to be between different types. + # isl requires move_dims to be between different types and + # one of dim_type.in_ and one of dim_type.param. # Not sure why. Let's make it happy. other_dt = dim_type.param if src_dt == other_dt: - other_dt = dim_type.out + other_dt = dim_type.in_ other_dt_dim = obj.dim(other_dt) obj = obj.move_dims(other_dt, other_dt_dim, src_dt, src_idx, 1) diff --git a/test/test_isl.py b/test/test_isl.py index 9e18953..e7bd80a 100644 --- a/test/test_isl.py +++ b/test/test_isl.py @@ -320,6 +320,15 @@ def test_pass_numpy_int(): print(c1) +def test_isl_align_two(): + a1 = isl.Aff("[start, end, t] -> { [(32)] }") + a2 = isl.Aff("[end, start] -> { [(0)] }") + + assert isl.align_two(a1, a2) == ( + isl.Aff("[end, start, t] -> { [(32)] }"), + isl.Aff("[end, start, t] -> { [(0)] }")) + + if __name__ == "__main__": import sys if len(sys.argv) > 1: -- GitLab From a1db58a540afc27327b3a5b735584f1f64888f55 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Sat, 7 Dec 2019 23:54:37 -0600 Subject: [PATCH 02/11] better var naming --- test/test_isl.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_isl.py b/test/test_isl.py index e7bd80a..476796d 100644 --- a/test/test_isl.py +++ b/test/test_isl.py @@ -321,12 +321,12 @@ def test_pass_numpy_int(): def test_isl_align_two(): - a1 = isl.Aff("[start, end, t] -> { [(32)] }") - a2 = isl.Aff("[end, start] -> { [(0)] }") + a1 = isl.Aff("[t0, t1, t2] -> { [(32)] }") + a2 = isl.Aff("[t1, t0] -> { [(0)] }") assert isl.align_two(a1, a2) == ( - isl.Aff("[end, start, t] -> { [(32)] }"), - isl.Aff("[end, start, t] -> { [(0)] }")) + isl.Aff("[t1, t0, t2] -> { [(32)] }"), + isl.Aff("[t1, t0, t2] -> { [(0)] }")) if __name__ == "__main__": -- GitLab From 5ce929a3fc609cf663bd5bfe36453b7c724d89ca Mon Sep 17 00:00:00 2001 From: "[6~" Date: Mon, 9 Dec 2019 10:35:39 -0600 Subject: [PATCH 03/11] Move creation of rich comparisons below creation of implicit self upcasts --- islpy/__init__.py | 82 +++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index 7257ed0..581c124 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -245,45 +245,6 @@ def _add_functionality(): # }}} - # {{{ rich comparisons - - def obj_eq(self, other): - assert self.get_ctx() == other.get_ctx(), ( - "Equality-comparing two objects from different ISL Contexts " - "will likely lead to entertaining (but never useful) results. " - "In particular, Spaces with matching names will no longer be " - "equal.") - - return self.is_equal(other) - - def obj_ne(self, other): - return not self.__eq__(other) - - for cls in ALL_CLASSES: - if hasattr(cls, "is_equal"): - cls.__eq__ = obj_eq - cls.__ne__ = obj_ne - - def obj_lt(self, other): - return self.is_strict_subset(other) - - def obj_le(self, other): - return self.is_subset(other) - - def obj_gt(self, other): - return other.is_strict_subset(self) - - def obj_ge(self, other): - return other.is_subset(self) - - for cls in [BasicSet, BasicMap, Set, Map]: - cls.__lt__ = obj_lt - cls.__le__ = obj_le - cls.__gt__ = obj_gt - cls.__ge__ = obj_ge - - # }}} - # {{{ Python set-like behavior def obj_or(self, other): @@ -976,6 +937,49 @@ def _add_functionality(): # }}} + # ORDERING DEPENDENCY: The availability of some of the 'is_equal' + # used by rich comparison below depends on the self upcasts created + # above. + + # {{{ rich comparisons + + def obj_eq(self, other): + assert self.get_ctx() == other.get_ctx(), ( + "Equality-comparing two objects from different ISL Contexts " + "will likely lead to entertaining (but never useful) results. " + "In particular, Spaces with matching names will no longer be " + "equal.") + + return self.is_equal(other) + + def obj_ne(self, other): + return not self.__eq__(other) + + for cls in ALL_CLASSES: + if hasattr(cls, "is_equal"): + cls.__eq__ = obj_eq + cls.__ne__ = obj_ne + + def obj_lt(self, other): + return self.is_strict_subset(other) + + def obj_le(self, other): + return self.is_subset(other) + + def obj_gt(self, other): + return other.is_strict_subset(self) + + def obj_ge(self, other): + return other.is_subset(self) + + for cls in [BasicSet, BasicMap, Set, Map]: + cls.__lt__ = obj_lt + cls.__le__ = obj_le + cls.__gt__ = obj_gt + cls.__ge__ = obj_ge + + # }}} + # {{{ project_out_except def obj_project_out_except(obj, names, types): -- GitLab From 2974b9c4f52076d2738d40c22d9fad1a4c7f22fe Mon Sep 17 00:00:00 2001 From: "[6~" Date: Mon, 9 Dec 2019 10:36:38 -0600 Subject: [PATCH 04/11] Fix a broken conditional in test_isl_align_two --- islpy/__init__.py | 3 +-- test/test_isl.py | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index 581c124..1f324ab 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1116,8 +1116,7 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): tgt_space = tgt.space else: tgt_space = tgt - if (not obj_bigger_ok - or obj.space.dim(dim_type.param) == tgt_space.dim(dim_type.param)): + if obj_bigger_ok: return obj.align_params(tgt_space) if None in tgt_names: diff --git a/test/test_isl.py b/test/test_isl.py index 476796d..7c83567 100644 --- a/test/test_isl.py +++ b/test/test_isl.py @@ -324,9 +324,9 @@ def test_isl_align_two(): a1 = isl.Aff("[t0, t1, t2] -> { [(32)] }") a2 = isl.Aff("[t1, t0] -> { [(0)] }") - assert isl.align_two(a1, a2) == ( - isl.Aff("[t1, t0, t2] -> { [(32)] }"), - isl.Aff("[t1, t0, t2] -> { [(0)] }")) + a1_aligned, a2_aligned = isl.align_two(a1, a2) + assert a1_aligned == isl.Aff("[t1, t0, t2] -> { [(32)] }") + assert a2_aligned == isl.Aff("[t1, t0, t2] -> { [(0)] }") if __name__ == "__main__": -- GitLab From 4617c23f37931fb839a30533d255447da1e62303 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Thu, 19 Dec 2019 16:56:39 -0600 Subject: [PATCH 05/11] use obj.align_params for Sets --- islpy/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index 1f324ab..f4c4626 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1111,13 +1111,17 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): # the 'param' dim_type, and we are not allowed to move dims around in there. # We'll make isl do the work, using align_params. - if tgt_dt == dim_type.param and isinstance(obj, (Aff, PwAff)): + if tgt_dt == dim_type.param and isinstance(obj, (Set, BasicSet, Aff, PwAff)): if not isinstance(tgt, Space): tgt_space = tgt.space else: tgt_space = tgt + if obj_bigger_ok: return obj.align_params(tgt_space) + else: + raise NotImplementedError("align_dim_types for %s if" + " 'obj_bigger_ok' is False" % type(obj).__name__) if None in tgt_names: all_nones = [None] * len(tgt_names) -- GitLab From fc374fc55ac4fe7e1cc722698eb3930bdc78c9af Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Thu, 19 Dec 2019 16:59:06 -0600 Subject: [PATCH 06/11] adds test for checking alignment of basic sets --- test/test_isl.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/test_isl.py b/test/test_isl.py index 7c83567..cfc06fe 100644 --- a/test/test_isl.py +++ b/test/test_isl.py @@ -328,6 +328,13 @@ def test_isl_align_two(): assert a1_aligned == isl.Aff("[t1, t0, t2] -> { [(32)] }") assert a2_aligned == isl.Aff("[t1, t0, t2] -> { [(0)] }") + b1 = isl.BasicSet("[n0, n1, n2] -> { [i0, i1] : }") + b2 = isl.BasicSet("[n0, n2, n1, n3] -> { [i1, i0, i2] : }") + + b1_aligned, b2_aligned = isl.align_two(b1, b2) + assert b1_aligned == isl.BasicSet("[n0, n2, n1, n3] -> { [i1, i0, i2] : }") + assert b2_aligned == isl.BasicSet("[n0, n2, n1, n3] -> { [i1, i0, i2] : }") + if __name__ == "__main__": import sys -- GitLab From dffeafbe302f614a5d8533d3b82759cc072cacf3 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Thu, 19 Dec 2019 17:03:11 -0600 Subject: [PATCH 07/11] cleans unnecessary diff --- islpy/__init__.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index f4c4626..748e1bb 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1111,7 +1111,7 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): # the 'param' dim_type, and we are not allowed to move dims around in there. # We'll make isl do the work, using align_params. - if tgt_dt == dim_type.param and isinstance(obj, (Set, BasicSet, Aff, PwAff)): + if tgt_dt == dim_type.param and isinstance(obj, (Aff, PwAff)): if not isinstance(tgt, Space): tgt_space = tgt.space else: @@ -1152,12 +1152,11 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): if src_dt == tgt_dt: assert src_idx > tgt_idx - # isl requires move_dims to be between different types and - # one of dim_type.in_ and one of dim_type.param. + # isl requires move_dims to be between different types # Not sure why. Let's make it happy. other_dt = dim_type.param if src_dt == other_dt: - other_dt = dim_type.in_ + other_dt = dim_type.out other_dt_dim = obj.dim(other_dt) obj = obj.move_dims(other_dt, other_dt_dim, src_dt, src_idx, 1) -- GitLab From 843c3ce5c7dd734a89c351d6ba68494b7889d942 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Thu, 19 Dec 2019 17:07:47 -0600 Subject: [PATCH 08/11] grammar --- islpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index 748e1bb..44273f6 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1152,7 +1152,7 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): if src_dt == tgt_dt: assert src_idx > tgt_idx - # isl requires move_dims to be between different types + # isl requires move_dims to be between different types. # Not sure why. Let's make it happy. other_dt = dim_type.param if src_dt == other_dt: -- GitLab From 4c5aee06889c0af2953a89b86639d822ec3739e9 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Thu, 19 Dec 2019 17:11:52 -0600 Subject: [PATCH 09/11] apparently the not implemented error is wrongly placed --- islpy/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index 44273f6..b8b4226 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1119,9 +1119,6 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): if obj_bigger_ok: return obj.align_params(tgt_space) - else: - raise NotImplementedError("align_dim_types for %s if" - " 'obj_bigger_ok' is False" % type(obj).__name__) if None in tgt_names: all_nones = [None] * len(tgt_names) -- GitLab From 2f0ceb075f46d88a81cd3039b475d777428c2d90 Mon Sep 17 00:00:00 2001 From: Kaushik Kulkarni Date: Fri, 20 Dec 2019 00:41:31 -0600 Subject: [PATCH 10/11] always use align_params provided by ISL --- islpy/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index b8b4226..64f1e7c 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1117,8 +1117,7 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): else: tgt_space = tgt - if obj_bigger_ok: - return obj.align_params(tgt_space) + return obj.align_params(tgt_space) if None in tgt_names: all_nones = [None] * len(tgt_names) -- GitLab From 5b48c52b39553aa12698180ac104b583ae27dd58 Mon Sep 17 00:00:00 2001 From: "[6~" Date: Wed, 8 Jan 2020 10:12:33 -0600 Subject: [PATCH 11/11] Fix, test align_spaces logic for Aff,PwAff --- islpy/__init__.py | 84 +++++++++++++++++++++++++++-------------------- test/test_isl.py | 12 +++++++ 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/islpy/__init__.py b/islpy/__init__.py index 64f1e7c..6f54ba1 100644 --- a/islpy/__init__.py +++ b/islpy/__init__.py @@ -1106,46 +1106,56 @@ def _set_dim_id(obj, dt, idx, id): return _back_to_basic(obj.set_dim_id(dt, idx, id), obj) -def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): +def _align_dim_type(template_dt, obj, template, obj_bigger_ok, obj_names, + template_names): + + # {{{ deal with Aff, PwAff + # The technique below will not work for PwAff et al, because there is *only* # the 'param' dim_type, and we are not allowed to move dims around in there. # We'll make isl do the work, using align_params. - if tgt_dt == dim_type.param and isinstance(obj, (Aff, PwAff)): - if not isinstance(tgt, Space): - tgt_space = tgt.space + if template_dt == dim_type.param and isinstance(obj, (Aff, PwAff)): + if not isinstance(template, Space): + template_space = template.space else: - tgt_space = tgt + template_space = template - return obj.align_params(tgt_space) + if not obj_bigger_ok: + if (obj.dim(template_dt) > template.dim(template_dt) + or not set(obj.get_var_dict()) <= set(template.get_var_dict())): + raise Error("obj has leftover dimensions after alignment") + return obj.align_params(template_space) + + # }}} - if None in tgt_names: - all_nones = [None] * len(tgt_names) - if tgt_names == all_nones and obj_names == all_nones: + if None in template_names: + all_nones = [None] * len(template_names) + if template_names == all_nones and obj_names == all_nones: # that's ok return obj - raise RuntimeError("tgt may not contain any unnamed dimensions") + raise Error("template may not contain any unnamed dimensions") obj_names = set(obj_names) - set([None]) - tgt_names = set(tgt_names) - set([None]) + template_names = set(template_names) - set([None]) - names_in_both = obj_names & tgt_names + names_in_both = obj_names & template_names tgt_idx = 0 - while tgt_idx < tgt.dim(tgt_dt): - tgt_id = tgt.get_dim_id(tgt_dt, tgt_idx) + while tgt_idx < template.dim(template_dt): + tgt_id = template.get_dim_id(template_dt, tgt_idx) tgt_name = tgt_id.name if tgt_name in names_in_both: - if (obj.dim(tgt_dt) > tgt_idx - and tgt_name == obj.get_dim_name(tgt_dt, tgt_idx)): + if (obj.dim(template_dt) > tgt_idx + and tgt_name == obj.get_dim_name(template_dt, tgt_idx)): pass else: src_dt, src_idx = obj.get_var_dict()[tgt_name] - if src_dt == tgt_dt: + if src_dt == template_dt: assert src_idx > tgt_idx # isl requires move_dims to be between different types. @@ -1156,33 +1166,34 @@ def _align_dim_type(tgt_dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names): other_dt_dim = obj.dim(other_dt) obj = obj.move_dims(other_dt, other_dt_dim, src_dt, src_idx, 1) - obj = obj.move_dims(tgt_dt, tgt_idx, other_dt, other_dt_dim, 1) + obj = obj.move_dims( + template_dt, tgt_idx, other_dt, other_dt_dim, 1) else: - obj = obj.move_dims(tgt_dt, tgt_idx, src_dt, src_idx, 1) + obj = obj.move_dims(template_dt, tgt_idx, src_dt, src_idx, 1) # names are same, make Ids the same, too - obj = _set_dim_id(obj, tgt_dt, tgt_idx, tgt_id) + obj = _set_dim_id(obj, template_dt, tgt_idx, tgt_id) tgt_idx += 1 else: - obj = obj.insert_dims(tgt_dt, tgt_idx, 1) - obj = _set_dim_id(obj, tgt_dt, tgt_idx, tgt_id) + obj = obj.insert_dims(template_dt, tgt_idx, 1) + obj = _set_dim_id(obj, template_dt, tgt_idx, tgt_id) tgt_idx += 1 - if tgt_idx < obj.dim(tgt_dt) and not obj_bigger_ok: - raise ValueError("obj has leftover dimensions") + if tgt_idx < obj.dim(template_dt) and not obj_bigger_ok: + raise Error("obj has leftover dimensions after alignment") return obj -def align_spaces(obj, tgt, obj_bigger_ok=False, across_dim_types=None): +def align_spaces(obj, template, obj_bigger_ok=False, across_dim_types=None): """ - Try to make the space in which *obj* lives the same as that of *tgt* by + Try to make the space in which *obj* lives the same as that of *template* by adding/matching named dimensions. :param obj_bigger_ok: If *True*, no error is raised if the resulting *obj* - has more dimensions than *tgt*. + has more dimensions than *template*. """ if across_dim_types is not None: @@ -1193,15 +1204,15 @@ def align_spaces(obj, tgt, obj_bigger_ok=False, across_dim_types=None): have_any_param_domains = ( isinstance(obj, (Set, BasicSet)) - and isinstance(tgt, (Set, BasicSet)) - and (obj.is_params() or tgt.is_params())) + and isinstance(template, (Set, BasicSet)) + and (obj.is_params() or template.is_params())) if have_any_param_domains: if obj.is_params(): obj = type(obj).from_params(obj) - if tgt.is_params(): - tgt = type(tgt).from_params(tgt) + if template.is_params(): + template = type(template).from_params(template) - if isinstance(tgt, EXPR_CLASSES): + if isinstance(template, EXPR_CLASSES): dim_types = _CHECK_DIM_TYPES[:] dim_types.remove(dim_type.out) else: @@ -1212,14 +1223,15 @@ def align_spaces(obj, tgt, obj_bigger_ok=False, across_dim_types=None): for dt in dim_types for i in range(obj.dim(dt)) ] - tgt_names = [ - tgt.get_dim_name(dt, i) + template_names = [ + template.get_dim_name(dt, i) for dt in dim_types - for i in range(tgt.dim(dt)) + for i in range(template.dim(dt)) ] for dt in dim_types: - obj = _align_dim_type(dt, obj, tgt, obj_bigger_ok, obj_names, tgt_names) + obj = _align_dim_type( + dt, obj, template, obj_bigger_ok, obj_names, template_names) return obj diff --git a/test/test_isl.py b/test/test_isl.py index cfc06fe..da461ce 100644 --- a/test/test_isl.py +++ b/test/test_isl.py @@ -309,6 +309,18 @@ def test_align_spaces(): result = isl.align_spaces(m1, m2) assert result.get_var_dict() == m2.get_var_dict() + a1 = isl.Aff("[t0, t1, t2] -> { [(32)] }") + a2 = isl.Aff("[t1, t0] -> { [(0)] }") + + with pytest.raises(isl.Error): + a1_aligned = isl.align_spaces(a1, a2) + + a1_aligned = isl.align_spaces(a1, a2, obj_bigger_ok=True) + a2_aligned = isl.align_spaces(a2, a1) + + assert a1_aligned == isl.Aff("[t1, t0, t2] -> { [(32)] }") + assert a2_aligned == isl.Aff("[t1, t0, t2] -> { [(0)] }") + def test_pass_numpy_int(): np = pytest.importorskip("numpy") -- GitLab