1- """
2- Abstract base class for all specialized bases.
3-
4- The Basis class is meant to specify a basis of the Hilbert space of the
5- studied system. Besides basis specific information all subclasses must
6- implement a shape variable which indicates the dimension of the used
7- Hilbert space. For a spin-1/2 Hilbert space this would be the
8- vector `[2]`. A system composed of two spins would then have a
9- shape vector `[2 2]`.
10-
11- Composite systems can be defined with help of the [`CompositeBasis`](@ref)
12- class.
13- """
14- abstract type Basis end
1+ # #
2+ # GenericBasis, CompositeBasis
3+ # #
154
165"""
176 length(b::Basis)
@@ -20,17 +9,6 @@ Total dimension of the Hilbert space.
209"""
2110Base. length (b:: Basis ) = prod (b. shape)
2211
23- """
24- basis(a)
25-
26- Return the basis of an object.
27-
28- If it's ambiguous, e.g. if an operator has a different left and right basis,
29- an [`IncompatibleBases`](@ref) error is thrown.
30- """
31- function basis end
32-
33-
3412"""
3513 GenericBasis(N)
3614
@@ -67,39 +45,6 @@ CompositeBasis(bases::Vector) = CompositeBasis((bases...,))
6745
6846Base.:(== )(b1:: T , b2:: T ) where T<: CompositeBasis = equal_shape (b1. shape, b2. shape)
6947
70- tensor (b:: Basis ) = b
71-
72- """
73- tensor(x::Basis, y::Basis, z::Basis...)
74-
75- Create a [`CompositeBasis`](@ref) from the given bases.
76-
77- Any given CompositeBasis is expanded so that the resulting CompositeBasis never
78- contains another CompositeBasis.
79- """
80- tensor (b1:: Basis , b2:: Basis ) = CompositeBasis ([length (b1); length (b2)], (b1, b2))
81- tensor (b1:: CompositeBasis , b2:: CompositeBasis ) = CompositeBasis ([b1. shape; b2. shape], (b1. bases... , b2. bases... ))
82- function tensor (b1:: CompositeBasis , b2:: Basis )
83- N = length (b1. bases)
84- shape = vcat (b1. shape, length (b2))
85- bases = (b1. bases... , b2)
86- CompositeBasis (shape, bases)
87- end
88- function tensor (b1:: Basis , b2:: CompositeBasis )
89- N = length (b2. bases)
90- shape = vcat (length (b1), b2. shape)
91- bases = (b1, b2. bases... )
92- CompositeBasis (shape, bases)
93- end
94- tensor (bases:: Basis... ) = reduce (tensor, bases)
95-
96- function Base.:^ (b:: Basis , N:: Integer )
97- if N < 1
98- throw (ArgumentError (" Power of a basis is only defined for positive integers." ))
99- end
100- tensor ([b for i= 1 : N]. .. )
101- end
102-
10348"""
10449 equal_shape(a, b)
10550
@@ -137,130 +82,6 @@ function equal_bases(a, b)
13782 return true
13883end
13984
140- """
141- Exception that should be raised for an illegal algebraic operation.
142- """
143- mutable struct IncompatibleBases <: Exception end
144-
145- const BASES_CHECK = Ref (true )
146-
147- """
148- @samebases
149-
150- Macro to skip checks for same bases. Useful for `*`, `expect` and similar
151- functions.
152- """
153- macro samebases (ex)
154- return quote
155- BASES_CHECK. x = false
156- local val = $ (esc (ex))
157- BASES_CHECK. x = true
158- val
159- end
160- end
161-
162- """
163- samebases(a, b)
164-
165- Test if two objects have the same bases.
166- """
167- samebases (b1:: Basis , b2:: Basis ) = b1== b2
168- samebases (b1:: Tuple{Basis, Basis} , b2:: Tuple{Basis, Basis} ) = b1== b2 # for checking superoperators
169-
170- """
171- check_samebases(a, b)
172-
173- Throw an [`IncompatibleBases`](@ref) error if the objects don't have
174- the same bases.
175- """
176- function check_samebases (b1, b2)
177- if BASES_CHECK[] && ! samebases (b1, b2)
178- throw (IncompatibleBases ())
179- end
180- end
181-
182-
183- """
184- multiplicable(a, b)
185-
186- Check if two objects are multiplicable.
187- """
188- multiplicable (b1:: Basis , b2:: Basis ) = b1== b2
189-
190- function multiplicable (b1:: CompositeBasis , b2:: CompositeBasis )
191- if ! equal_shape (b1. shape,b2. shape)
192- return false
193- end
194- for i= 1 : length (b1. shape)
195- if ! multiplicable (b1. bases[i], b2. bases[i])
196- return false
197- end
198- end
199- return true
200- end
201-
202- """
203- check_multiplicable(a, b)
204-
205- Throw an [`IncompatibleBases`](@ref) error if the objects are
206- not multiplicable.
207- """
208- function check_multiplicable (b1, b2)
209- if BASES_CHECK[] && ! multiplicable (b1, b2)
210- throw (IncompatibleBases ())
211- end
212- end
213-
214- """
215- reduced(a, indices)
216-
217- Reduced basis, state or operator on the specified subsystems.
218-
219- The `indices` argument, which can be a single integer or a vector of integers,
220- specifies which subsystems are kept. At least one index must be specified.
221- """
222- function reduced (b:: CompositeBasis , indices)
223- if length (indices)== 0
224- throw (ArgumentError (" At least one subsystem must be specified in reduced." ))
225- elseif length (indices)== 1
226- return b. bases[indices[1 ]]
227- else
228- return CompositeBasis (b. shape[indices], b. bases[indices])
229- end
230- end
231-
232- """
233- ptrace(a, indices)
234-
235- Partial trace of the given basis, state or operator.
236-
237- The `indices` argument, which can be a single integer or a vector of integers,
238- specifies which subsystems are traced out. The number of indices has to be
239- smaller than the number of subsystems, i.e. it is not allowed to perform a
240- full trace.
241- """
242- function ptrace (b:: CompositeBasis , indices)
243- J = [i for i in 1 : length (b. bases) if i ∉ indices]
244- length (J) > 0 || throw (ArgumentError (" Tracing over all indices is not allowed in ptrace." ))
245- reduced (b, J)
246- end
247-
248-
249- """
250- permutesystems(a, perm)
251-
252- Change the ordering of the subsystems of the given object.
253-
254- For a permutation vector `[2,1,3]` and a given object with basis `[b1, b2, b3]`
255- this function results in `[b2, b1, b3]`.
256- """
257- function permutesystems (b:: CompositeBasis , perm)
258- @assert length (b. bases) == length (perm)
259- @assert isperm (perm)
260- CompositeBasis (b. shape[perm], b. bases[perm])
261- end
262-
263-
26485# #
26586# Common bases
26687# #
@@ -366,89 +187,6 @@ SumBasis(shape, bases::Vector) = (tmp = (bases...,); SumBasis(shape, tmp))
366187SumBasis (bases:: Vector ) = SumBasis ((bases... ,))
367188SumBasis (bases:: Basis... ) = SumBasis ((bases... ,))
368189
369- == (b1:: T , b2:: T ) where T<: SumBasis = equal_shape (b1. shape, b2. shape)
370- == (b1:: SumBasis , b2:: SumBasis ) = false
371- length (b:: SumBasis ) = sum (b. shape)
372-
373- """
374- directsum(b1::Basis, b2::Basis)
375-
376- Construct the [`SumBasis`](@ref) out of two sub-bases.
377- """
378- directsum (b1:: Basis , b2:: Basis ) = SumBasis (Int[length (b1); length (b2)], Basis[b1, b2])
379- directsum (b:: Basis ) = b
380- directsum (b:: Basis... ) = reduce (directsum, b)
381- function directsum (b1:: SumBasis , b2:: Basis )
382- shape = [b1. shape;length (b2)]
383- bases = [b1. bases... ;b2]
384- return SumBasis (shape, (bases... ,))
385- end
386- function directsum (b1:: Basis , b2:: SumBasis )
387- shape = [length (b1);b2. shape]
388- bases = [b1;b2. bases... ]
389- return SumBasis (shape, (bases... ,))
390- end
391- function directsum (b1:: SumBasis , b2:: SumBasis )
392- shape = [b1. shape;b2. shape]
393- bases = [b1. bases... ;b2. bases... ]
394- return SumBasis (shape, (bases... ,))
395- end
396-
397- embed (b:: SumBasis , indices, ops) = embed (b, b, indices, ops)
398-
399- # #
400- # show methods
401- # #
402-
403- function show (stream:: IO , x:: GenericBasis )
404- if length (x. shape) == 1
405- write (stream, " Basis(dim=$(x. shape[1 ]) )" )
406- else
407- s = replace (string (x. shape), " " => " " )
408- write (stream, " Basis(shape=$s )" )
409- end
410- end
411-
412- function show (stream:: IO , x:: CompositeBasis )
413- write (stream, " [" )
414- for i in 1 : length (x. bases)
415- show (stream, x. bases[i])
416- if i != length (x. bases)
417- write (stream, " ⊗ " )
418- end
419- end
420- write (stream, " ]" )
421- end
422-
423- function show (stream:: IO , x:: SpinBasis )
424- d = denominator (x. spinnumber)
425- n = numerator (x. spinnumber)
426- if d == 1
427- write (stream, " Spin($n )" )
428- else
429- write (stream, " Spin($n /$d )" )
430- end
431- end
432-
433- function show (stream:: IO , x:: FockBasis )
434- if iszero (x. offset)
435- write (stream, " Fock(cutoff=$(x. N) )" )
436- else
437- write (stream, " Fock(cutoff=$(x. N) , offset=$(x. offset) )" )
438- end
439- end
440-
441- function show (stream:: IO , x:: NLevelBasis )
442- write (stream, " NLevel(N=$(x. N) )" )
443- end
444-
445- function show (stream:: IO , x:: SumBasis )
446- write (stream, " [" )
447- for i in 1 : length (x. bases)
448- show (stream, x. bases[i])
449- if i != length (x. bases)
450- write (stream, " ⊕ " )
451- end
452- end
453- write (stream, " ]" )
454- end
190+ Base.:(== )(b1:: T , b2:: T ) where T<: SumBasis = equal_shape (b1. shape, b2. shape)
191+ Base.:(== )(b1:: SumBasis , b2:: SumBasis ) = false
192+ Base. length (b:: SumBasis ) = sum (b. shape)
0 commit comments