From 0ceeb8b8bdcf6bdc030210a2135613ca61a0da1f Mon Sep 17 00:00:00 2001 From: Daniel Knuettel Date: Tue, 20 Feb 2024 17:56:51 +0100 Subject: [PATCH 1/3] made ot_singlet compatible to other datatype objects --- lib/gpt/core/object_type/__init__.py | 2 +- lib/gpt/core/object_type/container.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gpt/core/object_type/__init__.py b/lib/gpt/core/object_type/__init__.py index f7b4c3a2..e90f5045 100644 --- a/lib/gpt/core/object_type/__init__.py +++ b/lib/gpt/core/object_type/__init__.py @@ -38,7 +38,7 @@ def gpt_object(first, ot): ### # Container objects without (lie) group structure def singlet(grid): - return gpt_object(grid, ot_singlet) + return gpt_object(grid, ot_singlet()) def matrix_color(grid, ndim): diff --git a/lib/gpt/core/object_type/container.py b/lib/gpt/core/object_type/container.py index 6dfca493..d2decff8 100644 --- a/lib/gpt/core/object_type/container.py +++ b/lib/gpt/core/object_type/container.py @@ -68,10 +68,10 @@ class ot_singlet(ot_base): "ot_singlet": (lambda: ot_singlet, None), } - def data_otype(self=None): + def data_otype(self): return ot_singlet - def identity(): + def identity(self): return 1.0 From 5bff988134ad36a66297c855f719215061c97a4c Mon Sep 17 00:00:00 2001 From: Daniel Knuettel Date: Wed, 21 Feb 2024 11:15:05 +0100 Subject: [PATCH 2/3] made ot_singlet compatible to other ot's; singlet types are singleton now --- lib/gpt/core/expr.py | 2 +- .../object_type/complex_additive_group.py | 10 ++--- lib/gpt/core/object_type/container.py | 37 ++++++++++++++----- .../core/object_type/real_additive_group.py | 10 ++--- lib/gpt/core/object_type/u_1.py | 6 +-- lib/gpt/create/sparse_grid.py | 2 +- lib/gpt/ml/layer/nearest_neighbor.py | 2 +- 7 files changed, 44 insertions(+), 25 deletions(-) diff --git a/lib/gpt/core/expr.py b/lib/gpt/core/expr.py index 267140bd..263380c6 100644 --- a/lib/gpt/core/expr.py +++ b/lib/gpt/core/expr.py @@ -247,7 +247,7 @@ def get_otype_from_expression(e): bare_otype = None for coef, term in e.val: if len(term) == 0: - t_otype = gpt.ot_singlet + t_otype = gpt.ot_singlet() else: t_otype = None t_adj = False diff --git a/lib/gpt/core/object_type/complex_additive_group.py b/lib/gpt/core/object_type/complex_additive_group.py index d1ffaac2..f7889e91 100644 --- a/lib/gpt/core/object_type/complex_additive_group.py +++ b/lib/gpt/core/object_type/complex_additive_group.py @@ -30,13 +30,13 @@ class ot_complex_additive_group(ot_singlet): def __init__(self): self.__name__ = "ot_complex_additive_group" - self.data_alias = lambda: ot_singlet + self.data_alias = lambda: ot_singlet() self.rmtab = { - "ot_singlet": (lambda: ot_singlet, None), + "ot_singlet": (lambda: ot_singlet(), None), } self.mtab = { self.__name__: (lambda: self, None), - "ot_singlet": (lambda: ot_singlet, None), + "ot_singlet": (lambda: ot_singlet(), None), } # this is always multiplicative identity, not neutral element of group @@ -87,7 +87,7 @@ def __init__(self, n): } self.otab = {self.__name__: (lambda: ot_matrix_complex_additive_group(n), [])} self.itab = { - self.__name__: (lambda: ot_singlet, (0, 0)), + self.__name__: (lambda: ot_singlet(), (0, 0)), } self.cache = {} @@ -119,7 +119,7 @@ def coordinates(self, l, c=None): assert l.otype.__name__ == self.__name__ if c is None: r = [None] * self.shape[0] * 2 - a = gpt.separate_indices(l, (0, lambda: ot_singlet), self.cache) + a = gpt.separate_indices(l, (0, lambda: ot_singlet()), self.cache) for i in a: r[i[0]] = gpt.component.real(a[i]) r[i[0] + self.shape[0]] = gpt.component.imag(a[i]) diff --git a/lib/gpt/core/object_type/container.py b/lib/gpt/core/object_type/container.py index d2decff8..44505b6d 100644 --- a/lib/gpt/core/object_type/container.py +++ b/lib/gpt/core/object_type/container.py @@ -65,11 +65,30 @@ class ot_singlet(ot_base): colortrace = (None, None, None) v_otype = ["ot_singlet"] mtab = { - "ot_singlet": (lambda: ot_singlet, None), + "ot_singlet": (lambda: ot_singlet(), None), } + # FIXME: I am not sure if this is a good idea wrt. parellelism. + # Make singlet and all its derived subclasses singleton. + _instance = None + def __new__(cls, *args, **kwargs): + if not isinstance(cls._instance, cls): + cls._instance = object.__new__(cls, *args, **kwargs) + return cls._instance + + # There are many LoCs like + # res.otype == g.ot_singlet + # This will allow this behaviour to continue. + def __eq__(self, o): + if isinstance(o, type): + return type(self) == o + # This works because singleton. + if self is o: + return True + return o.__eq__(self) + def data_otype(self): - return ot_singlet + return ot_singlet() def identity(self): return 1.0 @@ -84,7 +103,7 @@ def __init__(self, ndim): self.shape = (ndim, ndim) self.transposed = (1, 0) self.spintrace = (None, None, None) # do nothing - self.colortrace = (0, 1, lambda: ot_singlet) + self.colortrace = (0, 1, lambda: ot_singlet()) self.v_otype = ["ot_mcolor%d" % ndim] # cgpt data types self.mtab = { self.__name__: (lambda: self, (1, 0)), @@ -115,7 +134,7 @@ def __init__(self, ndim): } self.otab = {self.__name__: (lambda: ot_matrix_color(ndim), [])} self.itab = { - self.__name__: (lambda: ot_singlet, (0, 0)), + self.__name__: (lambda: ot_singlet(), (0, 0)), } def compose(self, a, b): @@ -133,7 +152,7 @@ def __init__(self, ndim): self.nfloats = 2 * ndim * ndim self.shape = (ndim, ndim) self.transposed = (1, 0) - self.spintrace = (0, 1, lambda: ot_singlet) + self.spintrace = (0, 1, lambda: ot_singlet()) self.colortrace = (None, None, None) # do nothing self.v_otype = ["ot_mspin%d" % ndim] self.mtab = { @@ -197,7 +216,7 @@ def __init__(self, ndim): "ot_singlet": (lambda: self, None), } self.otab = {self.__name__: (lambda: ot_matrix_spin(ndim), [])} - self.itab = {self.__name__: (lambda: ot_singlet, (0, 0))} + self.itab = {self.__name__: (lambda: ot_singlet(), (0, 0))} def compose(self, a, b): return a + b @@ -269,7 +288,7 @@ def __init__(self, spin_ndim, color_ndim): ), } self.itab = { - self.__name__: (lambda: ot_singlet, ([0, 1], [0, 1])), + self.__name__: (lambda: ot_singlet(), ([0, 1], [0, 1])), } self.mtab = { "ot_singlet": (lambda: self, None), @@ -346,7 +365,7 @@ def __init__(self, n): "ot_singlet": (lambda: self, None), } self.itab = { - self.__name__: (lambda: ot_singlet, (0, 0)), + self.__name__: (lambda: ot_singlet(), (0, 0)), } @@ -367,7 +386,7 @@ def __init__(self, n): self.shape = (n, n) self.transposed = (1, 0) self.spintrace = (None, None, None) - self.colortrace = (0, 1, lambda: ot_singlet) + self.colortrace = (0, 1, lambda: ot_singlet()) self.vector_type = ot_vector_singlet(n) self.mtab = { self.__name__: (lambda: self, (1, 0)), diff --git a/lib/gpt/core/object_type/real_additive_group.py b/lib/gpt/core/object_type/real_additive_group.py index 7cb5dcb2..e5b29e5a 100644 --- a/lib/gpt/core/object_type/real_additive_group.py +++ b/lib/gpt/core/object_type/real_additive_group.py @@ -30,13 +30,13 @@ class ot_real_additive_group(ot_singlet): def __init__(self): self.__name__ = "ot_real_additive_group" - self.data_alias = lambda: ot_singlet + self.data_alias = lambda: ot_singlet() self.rmtab = { - "ot_singlet": (lambda: ot_singlet, None), + "ot_singlet": (lambda: ot_singlet(), None), } self.mtab = { self.__name__: (lambda: self, None), - "ot_singlet": (lambda: ot_singlet, None), + "ot_singlet": (lambda: ot_singlet(), None), } # this is always multiplicative identity, not neutral element of group @@ -87,7 +87,7 @@ def __init__(self, n): } self.otab = {self.__name__: (lambda: ot_matrix_real_additive_group(n), [])} self.itab = { - self.__name__: (lambda: ot_singlet, (0, 0)), + self.__name__: (lambda: ot_singlet(), (0, 0)), } self.cache = {} @@ -114,7 +114,7 @@ def coordinates(self, l, c=None): assert l.otype.__name__ == self.__name__ if c is None: r = [None] * self.shape[0] - a = gpt.separate_indices(l, (0, lambda: ot_singlet), self.cache) + a = gpt.separate_indices(l, (0, lambda: ot_singlet()), self.cache) for i in a: r[i[0]] = a[i] return r diff --git a/lib/gpt/core/object_type/u_1.py b/lib/gpt/core/object_type/u_1.py index fb0724f9..936b845c 100644 --- a/lib/gpt/core/object_type/u_1.py +++ b/lib/gpt/core/object_type/u_1.py @@ -34,13 +34,13 @@ def identity(self): def __init__(self, name): self.__name__ = name - self.data_alias = lambda: ot_singlet + self.data_alias = lambda: ot_singlet() self.rmtab = { - "ot_singlet": (lambda: ot_singlet, None), + "ot_singlet": (lambda: ot_singlet(), None), } self.mtab = { self.__name__: (lambda: self, None), - "ot_singlet": (lambda: ot_singlet, None), + "ot_singlet": (lambda: ot_singlet(), None), } diff --git a/lib/gpt/create/sparse_grid.py b/lib/gpt/create/sparse_grid.py index d24d7d28..99e28328 100644 --- a/lib/gpt/create/sparse_grid.py +++ b/lib/gpt/create/sparse_grid.py @@ -26,7 +26,7 @@ def coordinates(src, position, spacing): def zn(src, position, spacing, rng, n): - singlet = gpt.lattice(src.grid, gpt.ot_singlet) + singlet = gpt.lattice(src.grid, gpt.ot_singlet()) singlet.checkerboard(src.checkerboard()) pos = coordinates(src, position, spacing) singlet_full = gpt.lattice(singlet) diff --git a/lib/gpt/ml/layer/nearest_neighbor.py b/lib/gpt/ml/layer/nearest_neighbor.py index e4c67ae4..24145490 100644 --- a/lib/gpt/ml/layer/nearest_neighbor.py +++ b/lib/gpt/ml/layer/nearest_neighbor.py @@ -22,7 +22,7 @@ class nearest_neighbor(cshift): - def __init__(self, grid, ot_input=g.ot_singlet, ot_weights=g.ot_singlet, activation=sigmoid): + def __init__(self, grid, ot_input=g.ot_singlet(), ot_weights=g.ot_singlet(), activation=sigmoid): nd = grid.nd super().__init__( grid, From a6253caa1bcd085572a8cf556077c415bb6d6112 Mon Sep 17 00:00:00 2001 From: Daniel Knuettel Date: Mon, 11 Mar 2024 10:44:00 +0100 Subject: [PATCH 3/3] added ot_base.is_singlet to get rid of lattice.otype.data_otype() == gpt.ot_singlet --- lib/gpt/core/coordinates.py | 2 +- lib/gpt/core/expr.py | 2 +- lib/gpt/core/lattice.py | 4 ++-- lib/gpt/core/object_type/base.py | 1 + lib/gpt/core/object_type/container.py | 20 +------------------- lib/gpt/core/tensor.py | 4 ++-- lib/gpt/core/util.py | 2 +- 7 files changed, 9 insertions(+), 26 deletions(-) diff --git a/lib/gpt/core/coordinates.py b/lib/gpt/core/coordinates.py index abb03a75..73757b1f 100644 --- a/lib/gpt/core/coordinates.py +++ b/lib/gpt/core/coordinates.py @@ -131,7 +131,7 @@ def mat_backward(dst, src): def coordinate_mask(field, mask): assert isinstance(mask, numpy.ndarray) - assert field.otype.data_otype() == gpt.ot_singlet + assert field.otype.is_singlet x = gpt.coordinates(field) field[x] = mask.astype(field.grid.precision.complex_dtype).reshape((len(mask), 1)) diff --git a/lib/gpt/core/expr.py b/lib/gpt/core/expr.py index 263380c6..d4fb82a1 100644 --- a/lib/gpt/core/expr.py +++ b/lib/gpt/core/expr.py @@ -113,7 +113,7 @@ def __mul__(self, l): if uf & gpt.factor_unary.BIT_CONJ != 0: lhs = lhs.conj() res = gpt.tensor(np.tensordot(lhs, l.array, axes=mt[1]), mt[0]()) - if res.otype == gpt.ot_singlet: + if res.otype.is_singlet: res = complex(res.array) return res assert 0 diff --git a/lib/gpt/core/lattice.py b/lib/gpt/core/lattice.py index 10eeae6c..93b2f26f 100644 --- a/lib/gpt/core/lattice.py +++ b/lib/gpt/core/lattice.py @@ -288,8 +288,8 @@ def __itruediv__(self, expr): return self def __lt__(self, other): - assert self.otype.data_otype() == gpt.ot_singlet - assert other.otype.data_otype() == gpt.ot_singlet + assert self.otype.is_singlet + assert other.otype.is_singlet res = gpt.lattice(self) params = {"operator": "<"} cgpt.binary(res.v_obj[0], self.v_obj[0], other.v_obj[0], params) diff --git a/lib/gpt/core/object_type/base.py b/lib/gpt/core/object_type/base.py index 9f60fe8d..35bdc3ee 100644 --- a/lib/gpt/core/object_type/base.py +++ b/lib/gpt/core/object_type/base.py @@ -36,6 +36,7 @@ class ot_base: # list of object types to which I can convert and converter function ctab = {} + is_singlet = False # safe cast of data_alias def data_otype(self): diff --git a/lib/gpt/core/object_type/container.py b/lib/gpt/core/object_type/container.py index 44505b6d..f70b320c 100644 --- a/lib/gpt/core/object_type/container.py +++ b/lib/gpt/core/object_type/container.py @@ -67,25 +67,7 @@ class ot_singlet(ot_base): mtab = { "ot_singlet": (lambda: ot_singlet(), None), } - - # FIXME: I am not sure if this is a good idea wrt. parellelism. - # Make singlet and all its derived subclasses singleton. - _instance = None - def __new__(cls, *args, **kwargs): - if not isinstance(cls._instance, cls): - cls._instance = object.__new__(cls, *args, **kwargs) - return cls._instance - - # There are many LoCs like - # res.otype == g.ot_singlet - # This will allow this behaviour to continue. - def __eq__(self, o): - if isinstance(o, type): - return type(self) == o - # This works because singleton. - if self is o: - return True - return o.__eq__(self) + is_singlet = True def data_otype(self): return ot_singlet() diff --git a/lib/gpt/core/tensor.py b/lib/gpt/core/tensor.py index 9ef9a5ee..27c87265 100644 --- a/lib/gpt/core/tensor.py +++ b/lib/gpt/core/tensor.py @@ -75,7 +75,7 @@ def adj(self): return tensor(np.transpose(self.array.conj(), self.otype.transposed), self.otype) def reduced(self): - if self.otype.data_otype() == gpt.ot_singlet: + if self.otype.is_singlet: return complex(self.array) return self @@ -92,7 +92,7 @@ def trace(self, t): if ct[0] is not None: res = tensor(np.trace(res.array, offset=0, axis1=ct[0], axis2=ct[1]), ct[2]()) - if res.otype == gpt.ot_singlet: + if res.otype.is_singlet: res = complex(res.array) return res diff --git a/lib/gpt/core/util.py b/lib/gpt/core/util.py index d4b03c41..e04c47d1 100644 --- a/lib/gpt/core/util.py +++ b/lib/gpt/core/util.py @@ -52,7 +52,7 @@ def to_num(x): # tensor def value_to_tensor(val, otype): - if otype.data_otype() == gpt.ot_singlet: + if otype.is_singlet: # this is not ideal, can we do a subclass of complex that preserves otype info? return complex(val) return gpt.tensor(val, otype)