diff --git a/src/sage/combinat/root_system/ambient_space.py b/src/sage/combinat/root_system/ambient_space.py index 5fe5e161575..0d00c45273f 100644 --- a/src/sage/combinat/root_system/ambient_space.py +++ b/src/sage/combinat/root_system/ambient_space.py @@ -369,8 +369,7 @@ def _repr_(self): def inner_product(self, lambdacheck): """ - The scalar product with elements of the coroot lattice - embedded in the ambient space. + The scalar product with elements of the ambient space. EXAMPLES:: @@ -379,15 +378,32 @@ def inner_product(self, lambdacheck): (-1, 0, 0) sage: a.inner_product(a) 2 + + TESTS: + + Verify that :issue:`15325` (A) is fixed:: + + sage: rt = RootSystem(['E', 8]) + sage: lat = rt.root_lattice() + sage: spc = rt.ambient_space() + sage: spc.simple_root(1).scalar(lat.simple_coroot(2)) + 0 """ + if self.parent() is not lambdacheck.parent(): + try: + # see if lambdacheck can be converted to the ambient space + lambdacheck = self.parent()(lambdacheck) + except (TypeError, ValueError): + raise TypeError(f"unable to coerce {lambdacheck} into {self.parent()}") + + # self and lambdacheck both belong to the same ambient space, so use the inner product there self_mc = self._monomial_coefficients lambdacheck_mc = lambdacheck._monomial_coefficients result = self.parent().base_ring().zero() for t,c in lambdacheck_mc.items(): - if t not in self_mc: - continue - result += c*self_mc[t] + if t in self_mc: + result += c*self_mc[t] return result scalar = inner_product diff --git a/src/sage/combinat/root_system/root_space.py b/src/sage/combinat/root_system/root_space.py index 96a68eacc0f..14f5ed4ab23 100644 --- a/src/sage/combinat/root_system/root_space.py +++ b/src/sage/combinat/root_system/root_space.py @@ -260,13 +260,34 @@ def scalar(self, lambdacheck): [-1 2 -1 0] [ 0 -1 2 -1] [ 0 0 -2 2] + + TESTS: + + Verify that :issue:`15325` (A) is fixed:: + + sage: rt = RootSystem(['E', 8]) + sage: lat = rt.root_lattice() + sage: spc = rt.ambient_space() + sage: lat.simple_root(1).scalar(spc.simple_coroot(2)) + 0 + + Verify that directionality is correct for roots of different lengths:: + + sage: lat = RootSystem(['B', 3]).root_lattice() + sage: lat.simple_root(2).scalar(lat.simple_coroot(3)) + -2 """ - # Find some better test - if not (lambdacheck in self.parent().coroot_lattice() or lambdacheck in self.parent().coroot_space()): - raise TypeError("%s is not in a coroot lattice/space" % (lambdacheck)) - zero = self.parent().base_ring().zero() - cartan_matrix = self.parent().dynkin_diagram() - return sum( (sum( (lambdacheck[i]*s for i,s in cartan_matrix.column(j)), zero) * c for j,c in self), zero) + if lambdacheck in self.parent().coroot_lattice() or lambdacheck in self.parent().coroot_space(): + # This is the mathematically canonical case, where we use the Cartan matrix to find the scalar product + zero = self.parent().base_ring().zero() + cartan_matrix = self.parent().dynkin_diagram() + return sum( (sum( (lambdacheck[i]*s for i,s in cartan_matrix.column(j)), zero) * c for j,c in self), zero) + + if lambdacheck in self.parent().root_system.ambient_space(): + # lambdacheck lives in the ambient space of the root space, so we take the usual dot product in the ambient space + return self.to_ambient().dot_product(lambdacheck) + + raise TypeError(f"{lambdacheck} is not in a coroot lattice/space") def is_positive_root(self): """