Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/geometry/hyperplane_arrangement/affine_subspace.py
8817 views
1
"""
2
Affine Subspaces of a Vector Space
3
4
An affine subspace of a vector space is a translation of a linear
5
subspace. The affine subspaces here are only used internally in
6
hyperplane arrangements. You should not use them for interactive work
7
or return them to the user.
8
9
EXAMPLES::
10
11
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
12
sage: a = AffineSubspace([1,0,0,0], QQ^4)
13
sage: a.dimension()
14
4
15
sage: a.point()
16
(1, 0, 0, 0)
17
sage: a.linear_part()
18
Vector space of dimension 4 over Rational Field
19
sage: a
20
Affine space p + W where:
21
p = (1, 0, 0, 0)
22
W = Vector space of dimension 4 over Rational Field
23
sage: b = AffineSubspace((1,0,0,0), matrix(QQ, [[1,2,3,4]]).right_kernel())
24
sage: c = AffineSubspace((0,2,0,0), matrix(QQ, [[0,0,1,2]]).right_kernel())
25
sage: b.intersection(c)
26
Affine space p + W where:
27
p = (-3, 2, 0, 0)
28
W = Vector space of degree 4 and dimension 2 over Rational Field
29
Basis matrix:
30
[ 1 0 -1 1/2]
31
[ 0 1 -2 1]
32
sage: b < a
33
True
34
sage: c < b
35
False
36
sage: A = AffineSubspace([8,38,21,250], VectorSpace(GF(19),4))
37
sage: A
38
Affine space p + W where:
39
p = (8, 0, 2, 3)
40
W = Vector space of dimension 4 over Finite Field of size 19
41
42
TESTS::
43
44
sage: A = AffineSubspace([2], VectorSpace(QQ, 1))
45
sage: A.point()
46
(2)
47
sage: A.linear_part()
48
Vector space of dimension 1 over Rational Field
49
sage: A.linear_part().basis_matrix()
50
[1]
51
sage: A = AffineSubspace([], VectorSpace(QQ, 0))
52
sage: A.point()
53
()
54
sage: A.linear_part()
55
Vector space of dimension 0 over Rational Field
56
sage: A.linear_part().basis_matrix()
57
[]
58
"""
59
60
#*****************************************************************************
61
# Copyright (C) 2013 David Perkinson <[email protected]>
62
# Volker Braun <[email protected]>
63
#
64
# Distributed under the terms of the GNU General Public License (GPL)
65
# as published by the Free Software Foundation; either version 2 of
66
# the License, or (at your option) any later version.
67
# http://www.gnu.org/licenses/
68
#*****************************************************************************
69
70
from sage.structure.sage_object import SageObject
71
from sage.matrix.constructor import vector
72
73
74
class AffineSubspace(SageObject):
75
"""
76
An affine subspace.
77
78
INPUT:
79
80
- ``p`` -- list/tuple/iterable representing a point on the
81
affine space
82
83
- ``V`` -- vector subspace
84
85
OUTPUT:
86
87
Affine subspace parallel to ``V`` and passing through ``p``.
88
89
EXAMPLES::
90
91
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
92
sage: a = AffineSubspace([1,0,0,0], VectorSpace(QQ,4))
93
sage: a
94
Affine space p + W where:
95
p = (1, 0, 0, 0)
96
W = Vector space of dimension 4 over Rational Field
97
"""
98
def __init__(self, p, V):
99
r"""
100
Construct an :class:`AffineSubspace`.
101
102
TESTS::
103
104
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
105
sage: a = AffineSubspace([1,0,0,0], VectorSpace(QQ,4))
106
sage: TestSuite(a).run()
107
sage: AffineSubspace(0, VectorSpace(QQ,4)).point()
108
(0, 0, 0, 0)
109
"""
110
R = V.base_ring()
111
from sage.categories.all import Fields
112
if R not in Fields():
113
R = R.fraction_field()
114
V = V.change_ring(R)
115
self._base_ring = R
116
self._linear_part = V
117
p = V.ambient_vector_space()(p)
118
p.set_immutable()
119
self._point = p
120
121
def __hash__(self):
122
"""
123
Return a hash value.
124
125
EXAMPLES::
126
127
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
128
sage: a = AffineSubspace([1,0,0,0], VectorSpace(QQ,4))
129
sage: a.__hash__() # random output
130
-3713096828371451969
131
"""
132
# note that the point is not canonically chosen, but the linear part is
133
return hash(self._linear_part)
134
135
def _repr_(self):
136
r"""
137
String representation for an :class:`AffineSubspace`.
138
139
OUTPUT:
140
141
A string.
142
143
EXAMPLES::
144
145
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
146
sage: a = AffineSubspace([1,0,0,0],VectorSpace(QQ,4))
147
sage: a
148
Affine space p + W where:
149
p = (1, 0, 0, 0)
150
W = Vector space of dimension 4 over Rational Field
151
"""
152
return "Affine space p + W where:\n p = "+str(self._point)+"\n W = "+str(self._linear_part)
153
154
def __eq__(self, other):
155
r"""
156
Test whether ``self`` is equal to ``other``.
157
158
INPUT:
159
160
- ``other`` -- an :class:`AffineSubspace`
161
162
OUTPUT:
163
164
A boolean.
165
166
EXAMPLES::
167
168
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
169
sage: a = AffineSubspace([1,0,0], matrix([[1,0,0]]).right_kernel())
170
sage: b = AffineSubspace([2,0,0], matrix([[1,0,0]]).right_kernel())
171
sage: c = AffineSubspace([1,1,0], matrix([[1,0,0]]).right_kernel())
172
sage: a == b
173
False
174
sage: a == c
175
True
176
"""
177
V = self._linear_part
178
W = other._linear_part
179
return V == W and self._point - other._point in V
180
181
def __ne__(self, other):
182
r"""
183
Test whether ``self`` is not equal to ``other``.
184
185
INPUT:
186
187
- ``other`` -- an :class:`AffineSubspace`
188
189
OUTPUT:
190
191
A boolean.
192
193
EXAMPLES::
194
195
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
196
sage: a = AffineSubspace([1,0,0],matrix([[1,0,0]]).right_kernel())
197
sage: b = AffineSubspace([2,0,0],matrix([[1,0,0]]).right_kernel())
198
sage: a == b
199
False
200
sage: a != b
201
True
202
sage: a != a
203
False
204
"""
205
return not self == other
206
207
def __le__(self, other):
208
r"""
209
Test whether ``self`` is an affine subspace of ``other``.
210
211
INPUT:
212
213
- ``other`` -- an :class:`AffineSubspace`
214
215
OUTPUT:
216
217
A boolean.
218
219
EXAMPLES::
220
221
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
222
sage: V = VectorSpace(QQ, 3)
223
sage: W1 = V.subspace([[1,0,0],[0,1,0]])
224
sage: W2 = V.subspace([[1,0,0]])
225
sage: a = AffineSubspace([1,2,3], W1)
226
sage: b = AffineSubspace([1,2,3], W2)
227
sage: a <= b
228
False
229
sage: a <= a
230
True
231
sage: b <= a
232
True
233
"""
234
V = self._linear_part
235
W = other._linear_part
236
return V.is_subspace(W) and self._point-other._point in W
237
238
def __lt__(self, other):
239
r"""
240
Test whether ``self`` is a proper affine subspace of ``other``.
241
242
INPUT:
243
244
- ``other`` -- an :class:`AffineSubspace`
245
246
OUTPUT:
247
248
A boolean.
249
250
EXAMPLES::
251
252
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
253
sage: V = VectorSpace(QQ, 3)
254
sage: W1 = V.subspace([[1,0,0], [0,1,0]])
255
sage: W2 = V.subspace([[1,0,0]])
256
sage: a = AffineSubspace([1,2,3], W1)
257
sage: b = AffineSubspace([1,2,3], W2)
258
sage: a < b
259
False
260
sage: a < a
261
False
262
sage: b < a
263
True
264
"""
265
if self._linear_part == other._linear_part:
266
return False
267
return self.__le__(other)
268
269
def __contains__(self, q):
270
r"""
271
Test whether the point ``q`` is in the affine space.
272
273
INPUT:
274
275
- ``q`` -- point as a list/tuple/iterable
276
277
OUTPUT:
278
279
A boolean.
280
281
EXAMPLES::
282
283
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
284
sage: a = AffineSubspace([1,0,0], matrix([[1,0,0]]).right_kernel())
285
sage: (1,1,0) in a
286
True
287
sage: (0,0,0) in a
288
False
289
"""
290
q = vector(self._base_ring, q)
291
return self._point - q in self._linear_part
292
293
def linear_part(self):
294
r"""
295
Return the linear part of the affine space.
296
297
OUTPUT:
298
299
A vector subspace of the ambient space.
300
301
EXAMPLES::
302
303
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
304
sage: A = AffineSubspace([2,3,1], matrix(QQ, [[1,2,3]]).right_kernel())
305
sage: A.linear_part()
306
Vector space of degree 3 and dimension 2 over Rational Field
307
Basis matrix:
308
[ 1 0 -1/3]
309
[ 0 1 -2/3]
310
sage: A.linear_part().ambient_vector_space()
311
Vector space of dimension 3 over Rational Field
312
"""
313
return self._linear_part
314
315
def point(self):
316
r"""
317
Return a point ``p`` in the affine space.
318
319
OUTPUT:
320
321
A point of the affine space as a vector in the ambient space.
322
323
EXAMPLES::
324
325
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
326
sage: A = AffineSubspace([2,3,1], VectorSpace(QQ,3))
327
sage: A.point()
328
(2, 3, 1)
329
"""
330
return self._point
331
332
def dimension(self):
333
r"""
334
Return the dimension of the affine space.
335
336
OUTPUT:
337
338
An integer.
339
340
EXAMPLES::
341
342
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
343
sage: a = AffineSubspace([1,0,0,0],VectorSpace(QQ,4))
344
sage: a.dimension()
345
4
346
"""
347
return self.linear_part().dimension()
348
349
def intersection(self, other):
350
r"""
351
Return the intersection of ``self`` with ``other``.
352
353
INPUT:
354
355
- ``other`` -- an :class:`AffineSubspace`
356
357
OUTPUT:
358
359
A new affine subspace, (or ``None`` if the intersection is
360
empty).
361
362
EXAMPLES::
363
364
sage: from sage.geometry.hyperplane_arrangement.affine_subspace import AffineSubspace
365
sage: V = VectorSpace(QQ,3)
366
sage: U = V.subspace([(1,0,0), (0,1,0)])
367
sage: W = V.subspace([(0,1,0), (0,0,1)])
368
sage: A = AffineSubspace((0,0,0), U)
369
sage: B = AffineSubspace((1,1,1), W)
370
sage: A.intersection(B)
371
Affine space p + W where:
372
p = (1, 1, 0)
373
W = Vector space of degree 3 and dimension 1 over Rational Field
374
Basis matrix:
375
[0 1 0]
376
sage: C = AffineSubspace((0,0,1), U)
377
sage: A.intersection(C)
378
sage: C = AffineSubspace((7,8,9), U.complement())
379
sage: A.intersection(C)
380
Affine space p + W where:
381
p = (7, 8, 0)
382
W = Vector space of degree 3 and dimension 0 over Rational Field
383
Basis matrix:
384
[]
385
sage: A.intersection(C).intersection(B)
386
387
sage: D = AffineSubspace([1,2,3], VectorSpace(GF(5),3))
388
sage: E = AffineSubspace([3,4,5], VectorSpace(GF(5),3))
389
sage: D.intersection(E)
390
Affine space p + W where:
391
p = (3, 4, 0)
392
W = Vector space of dimension 3 over Finite Field of size 5
393
"""
394
if self.linear_part().ambient_vector_space() != \
395
other.linear_part().ambient_vector_space():
396
raise ValueError('incompatible ambient vector spaces')
397
m = self.linear_part().matrix()
398
n = other.linear_part().matrix()
399
p = self.point()
400
q = other.point()
401
M = m.stack(n)
402
v = q - p
403
try:
404
t = M.solve_left(v)
405
except ValueError:
406
return None # empty intersection
407
new_p = p + t[:m.nrows()]*m
408
new_V = self.linear_part().intersection(other._linear_part)
409
return AffineSubspace(new_p, new_V)
410
411
412