<commit_before>"""Provides functions to generate the n-legged hamiltonian in the block
diagonal form.

3-18-2017
NOT YET USABLE
"""

import spinsys as s
from spinsys.utils.globalvar import Globals as G
import scipy.sparse as ss
import numpy as np
from itertools import zip_longest, chain


def diagonals(N, W1, c1, phi1, J1, W2, c2, phi2, J2, nleg, curr_j, mode):
    """Generates the diagonal elements of the hamiltonian.

    Args: "N" number of sites
          "W1" disorder strength along the "horizontal" direction
          "c1" trancendental number along the "horizontal" direction
          "phi1" phase along the "horizontal" direction
          "J1" coupling constant between sites along the "horizontal" direction
          "W2" disorder strength along the "vertical" direction
          "c2" trancendental number along the "vertical" direction
          "phi2" phase along the "verical" direction
          "J2" coupling constant between sites along the "verical" direction
          "nleg" total number of "legs" for the lattice
          "curr_j" total spin for the current block
          "mode" "open" or "periodic" boundary conditions
    Returns: csc_matrix
    """

    # cache to ram since the interaction contribution stays the same
    #  across configurations
    # @s.utils.io.cache_ram
    # this function doesn't use "curr_j", "J1", "J2" and "nleg" per se,
    # however, the inclusion of it in the arguments helps the caching function
    # identifying the data
    def interaction(N, J1, J2, nleg, curr_j, mode):
        diagonal = np.zeros(mat_dim)
        for i, st_config in enumerate(basis_set):
            # TODO PROBLEM IS HERE
            # convert state configuration from {0, 1} to {-1, 1}
            st_config = [conv[s] for s in st_config]
            # Interaction contributions. The conversion of 0's to -1's is
            # warranted by the use of multiplication here.  A basis state of
            # [1, 1, -1, -1] in <Sz_i Sz_(i+1)> would yield 1/4 - 1/4 + 1/4 -
            # 1/4 = 0. We can achieve the same effect here if we take 1/4 *
            # [1, 1, -1, -1] * [-1, 1, 1, -1], the last two terms being the
            # current state multiplied by its shifted self element wise. The
            # results are then summed.
            # --- along horizontal ---
            if mode == 'periodic' and not l1 == 2:
                x_interaction = sum(map(lambda x, y: x * y, st_config,
                                        st_config[-l2:] + st_config[:-l2]))
            else:
                x_interaction = sum(map(lambda x, y: x * y,
                                        st_config[l2:], st_config[:-l2]))
            # --- along vertical ---
            if mode == 'peiodic' and not l2 == 2:
                cols = map(list, zip_longest(*[iter(st_config)] * l2))
                pair = chain(*list(map(lambda x: [x[-1]] + x[:-1], cols)))
                y_interaction = sum(map(lambda x, y: x * y, st_config, pair))
            else:
                non_ledge_sites = [i for n, i in enumerate(st_config)
                                   if not n % l2 == 0]
                non_redge_sites = [i for n, i in enumerate(st_config)
                                   if not (n + 1) % l2 == 0]
                y_interaction = sum(map(lambda x, y: x * y, non_redge_sites,
                                        non_ledge_sites))
            diagonal[i] = 0.25 * (J1 * x_interaction + J2 * y_interaction)
        return diagonal

    l1 = N // nleg  # number of sites along the "horizontal"
    l2 = nleg       # number of sites along the "vertical" (number of legs)

    sites_1 = np.arange(1, l1 + 1)
    sites_2 = np.arange(1, l2 + 1)
    if l1 == 1:     # field contrib=0 if length of leg=1 aka 1D
        field1 = np.zeros([1])
    else:
        field1 = W1 * np.cos(2 * np.pi * c1 * sites_1 + phi1)
    if l2 == 1:      # field contrib=0 if length of leg=1 aka 1D
        field2 = np.zeros([1])
    else:
        field2 = W2 * np.cos(2 * np.pi * c2 * sites_2 + phi2)
    field = field1.repeat(l2) + field2.repeat(l1).reshape(l2, l1).T.flatten()

    basis_set = s.half.generate_complete_basis(N, curr_j)[0]
    conv = {1: 1, 0: -1}         # dict for conversion of 0's to -1's
    mat_dim = len(basis_set)     # size of the block for the given total <Sz>
    diagonal = np.zeros(mat_dim)
    for i, st_config in enumerate(basis_set):
        # convert 0's to -1's so the basis configuration would look like
        #  [-1, -1, 1, 1] instead of [0, 0, 1, 1]
        st_config = [conv[s] for s in st_config]
        # Disorder contributions.
        disord_contrib = sum(field * st_config)
        diagonal[i] = 0.5 * disord_contrib
    diagonal += interaction(N, J1, J2, nleg, curr_j, mode)
    ind = np.arange(0, mat_dim)
    return ss.csc_matrix((diagonal, (ind, ind)), shape=[mat_dim, mat_dim])


# @s.utils.io.cache_ram
# @s.utils.io.matcache
def off_diagonals(N, J1, J2, nleg, curr_j, mode):
    """Generate the off diagonal elements of the hamiltonian.<commit_msg>Passed all 20 tests<commit_after>"""Provides functions to generate the n-legged hamiltonian in the block
diagonal form.

3-18-2017
"""

import spinsys as s
from spinsys.utils.globalvar import Globals as G
import scipy.sparse as ss
import numpy as np
from itertools import zip_longest, chain


def diagonals(N, W1, c1, phi1, J1, W2, c2, phi2, J2, nleg, curr_j, mode):
    """Generates the diagonal elements of the hamiltonian.

    Args: "N" number of sites
          "W1" disorder strength along the "horizontal" direction
          "c1" trancendental number along the "horizontal" direction
          "phi1" phase along the "horizontal" direction
          "J1" coupling constant between sites along the "horizontal" direction
          "W2" disorder strength along the "vertical" direction
          "c2" trancendental number along the "vertical" direction
          "phi2" phase along the "verical" direction
          "J2" coupling constant between sites along the "verical" direction
          "nleg" total number of "legs" for the lattice
          "curr_j" total spin for the current block
          "mode" "open" or "periodic" boundary conditions
    Returns: csc_matrix
    """

    # cache to ram since the interaction contribution stays the same
    #  across configurations
    @s.utils.io.cache_ram
    # this function doesn't use "curr_j", "J1", "J2" and "nleg" per se,
    # however, the inclusion of it in the arguments helps the caching function
    # identifying the data
    def interaction(N, J1, J2, nleg, curr_j, mode):
        diagonal = np.zeros(mat_dim)
        for i, st_config in enumerate(basis_set):
            # convert state configuration from {0, 1} to {-1, 1}
            st_config = [conv[s] for s in st_config]
            # Interaction contributions. The conversion of 0's to -1's is
            # warranted by the use of multiplication here.  A basis state of
            # [1, 1, -1, -1] in <Sz_i Sz_(i+1)> would yield 1/4 - 1/4 + 1/4 -
            # 1/4 = 0. We can achieve the same effect here if we take 1/4 *
            # [1, 1, -1, -1] * [-1, 1, 1, -1], the last two terms being the
            # current state multiplied by its shifted self element wise. The
            # results are then summed.
            # --- along horizontal ---
            if mode == 'periodic' and not l1 == 2:
                x_interaction = sum(map(lambda x, y: x * y, st_config,
                                        st_config[-l2:] + st_config[:-l2]))
            else:
                x_interaction = sum(map(lambda x, y: x * y,
                                        st_config[l2:], st_config[:-l2]))
            # --- along vertical ---
            if mode == 'periodic' and not l2 == 2:
                cols = map(list, zip_longest(*[iter(st_config)] * l2))
                pair = chain(*list(map(lambda x: [x[-1]] + x[:-1], cols)))
                y_interaction = sum(map(lambda x, y: x * y, st_config, pair))
            else:
                non_ledge_sites = [i for n, i in enumerate(st_config)
                                   if not n % l2 == 0]
                non_redge_sites = [i for n, i in enumerate(st_config)
                                   if not (n + 1) % l2 == 0]
                y_interaction = sum(map(lambda x, y: x * y, non_redge_sites,
                                        non_ledge_sites))
            diagonal[i] = 0.25 * (J1 * x_interaction + J2 * y_interaction)
        return diagonal

    l1 = N // nleg  # number of sites along the "horizontal"
    l2 = nleg       # number of sites along the "vertical" (number of legs)

    sites_1 = np.arange(1, l1 + 1)
    sites_2 = np.arange(1, l2 + 1)
    if l1 == 1:     # field contrib=0 if length of leg=1 aka 1D
        field1 = np.zeros([1])
    else:
        field1 = W1 * np.cos(2 * np.pi * c1 * sites_1 + phi1)
    if l2 == 1:      # field contrib=0 if length of leg=1 aka 1D
        field2 = np.zeros([1])
    else:
        field2 = W2 * np.cos(2 * np.pi * c2 * sites_2 + phi2)
    field = field1.repeat(l2) + field2.repeat(l1).reshape(l2, l1).T.flatten()

    basis_set = s.half.generate_complete_basis(N, curr_j)[0]
    conv = {1: 1, 0: -1}         # dict for conversion of 0's to -1's
    mat_dim = len(basis_set)     # size of the block for the given total <Sz>
    diagonal = np.zeros(mat_dim)
    for i, st_config in enumerate(basis_set):
        # convert 0's to -1's so the basis configuration would look like
        #  [-1, -1, 1, 1] instead of [0, 0, 1, 1]
        st_config = [conv[s] for s in st_config]
        # Disorder contributions.
        disord_contrib = sum(field * st_config)
        diagonal[i] = 0.5 * disord_contrib
    diagonal += interaction(N, J1, J2, nleg, curr_j, mode)
    ind = np.arange(0, mat_dim)
    return ss.csc_matrix((diagonal, (ind, ind)), shape=[mat_dim, mat_dim])


@s.utils.io.cache_ram
@s.utils.io.matcache
def off_diagonals(N, J1, J2, nleg, curr_j, mode):
    """Generate the off diagonal elements of the hamiltonian.
{'fraction_non_alphanumeric': 0.10803794308537194, 'fraction_numerical': 0.02895656515227159, 'mean_word_length': 2.0620605319474166, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6262238', 'n_tokens_mistral': 3355, 'n_tokens_neox': 3160, 'n_words': 1117}