# Path: drudge/fock.py
# CR = CranChar.CR
# 
# AN = CranChar.AN
# 
# UP = SpinOneHalf.UP
# 
# DOWN = SpinOneHalf.DOWN
# 
# class SpinOneHalfGenDrudge(GenMBDrudge):
#     """Drudge for many-body problems of particles with explicit 1/2 spin.
# 
#     This is just a shallow subclass of the drudge for general many-body
#     problems, with exchange set to fermi and has explicit spin values of
#     :py:data:`UP` and :py:data:`DOWN`.
#     """
# 
#     def __init__(self, *args, **kwargs):
#         """Initialize the drudge object.
#         """
# 
#         super().__init__(*args, exch=FERMI, spin=[UP, DOWN], **kwargs)
# 
# class SpinOneHalfPartHoleDrudge(PartHoleDrudge):
#     """Drudge for the particle-hole problems with explicit one-half spin.
# 
#     This is a shallow subclass over the general particle-hole drudge without
#     explicit spin.  The spin values are given explicitly, which are set to
#     :py:data:`UP` and :py:data:`DOWN` by default.  And the double-bar of the
#     two-body interaction is disabled.  And some additional dummies traditional
#     in the field are also added.
# 
#     """
# 
#     def __init__(
#             self, *args,
#             part_orb=(
#                     Range('V', 0, Symbol('nv')),
#                     PartHoleDrudge.DEFAULT_PART_DUMMS + symbols('beta gamma')
#             ),
#             hole_orb=(
#                     Range('O', 0, Symbol('no')),
#                     PartHoleDrudge.DEFAULT_HOLE_DUMMS + symbols('u v')
#             ), spin=(UP, DOWN),
#             **kwargs
#     ):
#         """Initialize the particle-hole drudge."""
# 
#         super().__init__(
#             *args, spin=spin, dbbar=False,
#             part_orb=part_orb, hole_orb=hole_orb, **kwargs
#         )
# 
# class RestrictedPartHoleDrudge(SpinOneHalfPartHoleDrudge):
#     """Drudge for the particle-hole problems on restricted reference.
# 
#     Similar to :py:class:`SpinOneHalfPartHoldDrudge`, this drudge deals with
#     particle-hole problems with explicit one-half spin.  However, here the spin
#     quantum number is summed symbolically.  This gives **much** faster
#     derivations for theories based on restricted reference, but offers less
#     flexibility.
# 
#     .. attribute:: spin_range
# 
#         The symbolic range for spin values.
# 
#     .. attribute:: spin_dumms
# 
#         The dummies for the spin quantum number.
# 
#     .. attribute:: e_
# 
#         Tensor definition for the unitary group generators.  It should be
#         indexed with the upper and lower indices to the :math:`E` operator.  It
#         is also registered in the name archive as ``e_``.
# 
#     """
# 
#     def __init__(
#             self, *args,
#             spin_range=Range(r'\uparrow\downarrow', 0, 2),
#             spin_dumms=tuple(Symbol('sigma{}'.format(i)) for i in range(50)),
#             **kwargs
#     ):
#         """Initialize the restricted particle-hole drudge."""
# 
#         super().__init__(
#             *args, spin=(spin_range, spin_dumms), **kwargs
#         )
#         self.add_resolver({
#             UP: spin_range,
#             DOWN: spin_range
#         })
# 
#         self.spin_range = spin_range
#         self.spin_dumms = self.dumms.value[spin_range]
# 
#         sigma = self.dumms.value[spin_range][0]
#         p = Symbol('p')
#         q = Symbol('q')
#         self.e_ = TensorDef(Vec('E'), (p, q), self.sum(
#             (sigma, spin_range), self.cr[p, sigma] * self.an[q, sigma]
#         ))
#         self.set_name(e_=self.e_)


import pytest
from sympy import IndexedBase, symbols, Rational, KroneckerDelta, Integer
from drudge import (
    CR, AN, UP, DOWN, SpinOneHalfGenDrudge, SpinOneHalfPartHoleDrudge,
    RestrictedPartHoleDrudge
)
    ))
    expected = expected.simplify()

    assert res == expected


@pytest.fixture(scope='module')
def parthole(spark_ctx):
    """The fixture with a particle-hole spin one-half drudge."""
    return SpinOneHalfPartHoleDrudge(spark_ctx)


def test_spin_one_half_particle_hole_drudge_has_basic_properties(parthole):
    """Test basic properties of spin one-half particle-hole drudge."""

    dr = parthole
    p = dr.names

    assert dr.orig_ham.n_terms == 8 + 4 * 2 ** 4

    ham_terms = dr.ham.local_terms
    # Numbers are from the old PySLATA code.
    assert len([i for i in ham_terms if len(i.vecs) == 2]) == 8
    assert len([i for i in ham_terms if len(i.vecs) == 4]) == 36
    assert dr.ham.n_terms == 8 + 36


@pytest.fixture(scope='module')
def restricted_parthole(spark_ctx):
    """The fixture with a restricted particle-hole drudge."""

# Path: drudge/fock.py
# CR = CranChar.CR
# 
# AN = CranChar.AN
# 
# UP = SpinOneHalf.UP
# 
# DOWN = SpinOneHalf.DOWN
# 
# class SpinOneHalfGenDrudge(GenMBDrudge):
#     """Drudge for many-body problems of particles with explicit 1/2 spin.
# 
#     This is just a shallow subclass of the drudge for general many-body
#     problems, with exchange set to fermi and has explicit spin values of
#     :py:data:`UP` and :py:data:`DOWN`.
#     """
# 
#     def __init__(self, *args, **kwargs):
#         """Initialize the drudge object.
#         """
# 
#         super().__init__(*args, exch=FERMI, spin=[UP, DOWN], **kwargs)
# 
# class SpinOneHalfPartHoleDrudge(PartHoleDrudge):
#     """Drudge for the particle-hole problems with explicit one-half spin.
# 
#     This is a shallow subclass over the general particle-hole drudge without
#     explicit spin.  The spin values are given explicitly, which are set to
#     :py:data:`UP` and :py:data:`DOWN` by default.  And the double-bar of the
#     two-body interaction is disabled.  And some additional dummies traditional
#     in the field are also added.
# 
#     """
# 
#     def __init__(
#             self, *args,
#             part_orb=(
#                     Range('V', 0, Symbol('nv')),
#                     PartHoleDrudge.DEFAULT_PART_DUMMS + symbols('beta gamma')
#             ),
#             hole_orb=(
#                     Range('O', 0, Symbol('no')),
#                     PartHoleDrudge.DEFAULT_HOLE_DUMMS + symbols('u v')
#             ), spin=(UP, DOWN),
#             **kwargs
#     ):
#         """Initialize the particle-hole drudge."""
# 
#         super().__init__(
#             *args, spin=spin, dbbar=False,
#             part_orb=part_orb, hole_orb=hole_orb, **kwargs
#         )
# 
# class RestrictedPartHoleDrudge(SpinOneHalfPartHoleDrudge):
#     """Drudge for the particle-hole problems on restricted reference.
# 
#     Similar to :py:class:`SpinOneHalfPartHoldDrudge`, this drudge deals with
#     particle-hole problems with explicit one-half spin.  However, here the spin
#     quantum number is summed symbolically.  This gives **much** faster
#     derivations for theories based on restricted reference, but offers less
#     flexibility.
# 
#     .. attribute:: spin_range
# 
#         The symbolic range for spin values.
# 
#     .. attribute:: spin_dumms
# 
#         The dummies for the spin quantum number.
# 
#     .. attribute:: e_
# 
#         Tensor definition for the unitary group generators.  It should be
#         indexed with the upper and lower indices to the :math:`E` operator.  It
#         is also registered in the name archive as ``e_``.
# 
#     """
# 
#     def __init__(
#             self, *args,
#             spin_range=Range(r'\uparrow\downarrow', 0, 2),
#             spin_dumms=tuple(Symbol('sigma{}'.format(i)) for i in range(50)),
#             **kwargs
#     ):
#         """Initialize the restricted particle-hole drudge."""
# 
#         super().__init__(
#             *args, spin=(spin_range, spin_dumms), **kwargs
#         )
#         self.add_resolver({
#             UP: spin_range,
#             DOWN: spin_range
#         })
# 
#         self.spin_range = spin_range
#         self.spin_dumms = self.dumms.value[spin_range]
# 
#         sigma = self.dumms.value[spin_range][0]
#         p = Symbol('p')
#         q = Symbol('q')
#         self.e_ = TensorDef(Vec('E'), (p, q), self.sum(
#             (sigma, spin_range), self.cr[p, sigma] * self.an[q, sigma]
#         ))
#         self.set_name(e_=self.e_)


# Path: tests/spin_one_half_test.py
import pytest
from sympy import IndexedBase, symbols, Rational, KroneckerDelta, Integer
from drudge import (
    CR, AN, UP, DOWN, SpinOneHalfGenDrudge, SpinOneHalfPartHoleDrudge,
    RestrictedPartHoleDrudge
)

    ))
    expected = expected.simplify()

    assert res == expected


@pytest.fixture(scope='module')
def parthole(spark_ctx):
    """The fixture with a particle-hole spin one-half drudge."""
    return SpinOneHalfPartHoleDrudge(spark_ctx)


def test_spin_one_half_particle_hole_drudge_has_basic_properties(parthole):
    """Test basic properties of spin one-half particle-hole drudge."""

    dr = parthole
    p = dr.names

    assert dr.orig_ham.n_terms == 8 + 4 * 2 ** 4

    ham_terms = dr.ham.local_terms
    # Numbers are from the old PySLATA code.
    assert len([i for i in ham_terms if len(i.vecs) == 2]) == 8
    assert len([i for i in ham_terms if len(i.vecs) == 4]) == 36
    assert dr.ham.n_terms == 8 + 36


@pytest.fixture(scope='module')
def restricted_parthole(spark_ctx):
    """The fixture with a restricted particle-hole drudge."""

    return RestrictedPartHoleDrudge(spark_ctx)