Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

r""" 

Metric Spaces 

""" 

#***************************************************************************** 

# Copyright (C) 2015 Travis Scrimshaw <tscrim at ucdavis.edu> 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# http://www.gnu.org/licenses/ 

#****************************************************************************** 

 

from sage.misc.cachefunc import cached_method 

from sage.categories.category import Category 

from sage.categories.category_with_axiom import CategoryWithAxiom 

from sage.categories.covariant_functorial_construction import RegressiveCovariantConstructionCategory 

from sage.categories.with_realizations import WithRealizationsCategory 

 

class MetricSpacesCategory(RegressiveCovariantConstructionCategory): 

 

_functor_category = "Metric" 

 

@classmethod 

def default_super_categories(cls, category): 

""" 

Return the default super categories of ``category.Metric()``. 

 

Mathematical meaning: if `A` is a metric space in the 

category `C`, then `A` is also a topological space. 

 

INPUT: 

 

- ``cls`` -- the class ``MetricSpaces`` 

- ``category`` -- a category `Cat` 

 

OUTPUT: 

 

A (join) category 

 

In practice, this returns ``category.Metric()``, joined 

together with the result of the method 

:meth:`RegressiveCovariantConstructionCategory.default_super_categories() 

<sage.categories.covariant_functorial_construction.RegressiveCovariantConstructionCategory.default_super_categories>` 

(that is the join of ``category`` and ``cat.Metric()`` for 

each ``cat`` in the super categories of ``category``). 

 

EXAMPLES: 

 

Consider ``category=Groups()``. Then, a group `G` with a metric 

is simultaneously a topological group by itself, and a 

metric space:: 

 

sage: Groups().Metric().super_categories() 

[Category of topological groups, Category of metric spaces] 

 

This resulted from the following call:: 

 

sage: sage.categories.metric_spaces.MetricSpacesCategory.default_super_categories(Groups()) 

Join of Category of topological groups and Category of metric spaces 

""" 

return Category.join([category.Topological(), 

super(MetricSpacesCategory, cls).default_super_categories(category)]) 

 

# We currently don't have a use for this, but we probably will 

def _repr_object_names(self): 

""" 

EXAMPLES:: 

 

sage: Groups().Metric() # indirect doctest 

Join of Category of topological groups and Category of metric spaces 

""" 

return "metric {}".format(self.base_category()._repr_object_names()) 

 

class MetricSpaces(MetricSpacesCategory): 

r""" 

The category of metric spaces. 

 

A *metric* on a set `S` is a function `d : S \times S \to \RR` 

such that: 

 

- `d(a, b) \geq 0`, 

- `d(a, b) = 0` if and only if `a = b`. 

 

A metric space is a set `S` with a distinguished metric. 

 

.. RUBRIC:: Implementation 

 

Objects in this category must implement either a ``dist`` on the parent 

or the elements or ``metric`` on the parent; otherwise this will cause 

an infinite recursion. 

 

.. TODO:: 

 

- Implement a general geodesics class. 

- Implement a category for metric additive groups 

and move the generic distance `d(a, b) = |a - b|` there. 

- Incorporate the length of a geodesic as part of the default 

distance cycle. 

 

EXAMPLES:: 

 

sage: from sage.categories.metric_spaces import MetricSpaces 

sage: C = MetricSpaces() 

sage: C 

Category of metric spaces 

sage: TestSuite(C).run() 

""" 

def _repr_object_names(self): 

""" 

EXAMPLES:: 

 

sage: Sets().Metric() # indirect doctest 

Category of metric spaces 

""" 

return "metric spaces" 

 

class ParentMethods: 

def _test_metric(self, **options): 

r""" 

Test that this metric space has a properly implemented metric. 

 

INPUT: 

 

- ``options`` -- any keyword arguments accepted 

by :meth:`_tester` 

 

EXAMPLES:: 

 

sage: UHP = HyperbolicPlane().UHP() 

sage: UHP._test_metric() 

sage: elts = [UHP.random_element() for i in range(5)] 

sage: UHP._test_metric(some_elements=elts) 

""" 

tester = self._tester(**options) 

S = tester.some_elements() 

dist = self.metric() 

for a in S: 

for b in S: 

d = dist(a, b) 

if a != b: 

tester.assertGreater(d, 0) 

else: 

tester.assertEqual(d, 0) 

 

def metric(self): 

""" 

Return the metric of ``self``. 

 

EXAMPLES:: 

 

sage: UHP = HyperbolicPlane().UHP() 

sage: m = UHP.metric() 

sage: p1 = UHP.get_point(5 + 7*I) 

sage: p2 = UHP.get_point(1.0 + I) 

sage: m(p1, p2) 

2.23230104635820 

""" 

return lambda a,b: a.dist(b) 

 

def dist(self, a, b): 

""" 

Return the distance between ``a`` and ``b`` in ``self``. 

 

EXAMPLES:: 

 

sage: UHP = HyperbolicPlane().UHP() 

sage: p1 = UHP.get_point(5 + 7*I) 

sage: p2 = UHP.get_point(1.0 + I) 

sage: UHP.dist(p1, p2) 

2.23230104635820 

 

sage: PD = HyperbolicPlane().PD() 

sage: PD.dist(PD.get_point(0), PD.get_point(I/2)) 

arccosh(5/3) 

 

TESTS:: 

 

sage: RR.dist(-1, pi) 

4.14159265358979 

sage: RDF.dist(1, -1/2) 

1.5 

sage: CC.dist(3, 2) 

1.00000000000000 

sage: CC.dist(-1, I) 

1.41421356237310 

sage: CDF.dist(-1, I) 

1.4142135623730951 

""" 

return (self(a) - self(b)).abs() 

 

class ElementMethods: 

def abs(self): 

""" 

Return the absolute value of ``self``. 

 

EXAMPLES:: 

 

sage: CC(I).abs() 

1.00000000000000 

""" 

P = self.parent() 

return P.metric()(self, P.zero()) 

 

def dist(self, b): 

""" 

Return the distance between ``self`` and ``other``. 

 

EXAMPLES:: 

 

sage: UHP = HyperbolicPlane().UHP() 

sage: p1 = UHP.get_point(5 + 7*I) 

sage: p2 = UHP.get_point(1 + I) 

sage: p1.dist(p2) 

arccosh(33/7) 

""" 

return self.parent().dist(self, b) 

 

class WithRealizations(WithRealizationsCategory): 

class ParentMethods: 

def dist(self, a, b): 

""" 

Return the distance between ``a`` and ``b`` by converting them 

to a realization of ``self`` and doing the computation. 

 

EXAMPLES:: 

 

sage: H = HyperbolicPlane() 

sage: PD = H.PD() 

sage: p1 = PD.get_point(0) 

sage: p2 = PD.get_point(I/2) 

sage: H.dist(p1, p2) 

arccosh(5/3) 

""" 

R = self.a_realization() 

return R.dist(R(a), R(b)) 

 

class SubcategoryMethods: 

@cached_method 

def Complete(self): 

""" 

Return the full subcategory of the complete objects of ``self``. 

 

EXAMPLES:: 

 

sage: Sets().Metric().Complete() 

Category of complete metric spaces 

 

TESTS:: 

 

sage: TestSuite(Sets().Metric().Complete()).run() 

sage: Sets().Metric().Complete.__module__ 

'sage.categories.metric_spaces' 

""" 

return self._with_axiom('Complete') 

 

class Complete(CategoryWithAxiom): 

""" 

The category of complete metric spaces. 

"""