def process_composite_contractions(contraction, elementary_contractions,
                                   n_indices, expand_hole, base_order_map,
                                   upper_indices_set, lower_indices_set):
    """
    Process a single composite contraction expressed in terms of indices of elementary contractions.
    :param contraction: a composite contraction
    :param elementary_contractions: a list of density cumulants / hole densities
    :param n_indices: the total number of indices
    :param expand_hole: expand hole densities to Kronecker delta minus one density if True
    :param base_order_map: the index map to ordering index, e.g., {"ug0": 0, "lg0": 1, ...}, u/l for upper/lower
    :param upper_indices_set: the set of all creation operators
    :param lower_indices_set: the set of all annihilation operators
    :return: a list of contractions in terms of (sign, list_of_densities, sq_op)
    """
    list_of_densities = []
    current_order = []

    n_open = 0
    for con in contraction:
        ele_con = elementary_contractions[con]
        list_of_densities.append(ele_con)
        n_open += ele_con.n_upper

        if isinstance(ele_con, HoleDensity):
            current_order += [
                f"l{ele_con.lower_indices[0].name}",
                f"u{ele_con.upper_indices[0].name}"
            ]
        else:
            current_order += [f"u{i.name}" for i in ele_con.upper_indices]
            current_order += [
                f"l{i.name}" for i in ele_con.lower_indices[::-1]
            ]
    n_open = n_indices - 2 * n_open

    # sort the open indices
    if n_open != 0:
        contracted = set(current_order)
        open_upper_indices = IndicesSpinOrbital(
            sorted(Index(i[1:]) for i in upper_indices_set - contracted))
        open_lower_indices = IndicesSpinOrbital(
            sorted(Index(i[1:]) for i in lower_indices_set - contracted))
        current_order += [f"u{i.name}" for i in open_upper_indices]
        current_order += [f"l{i.name}" for i in open_lower_indices[::-1]]

        sq_op = SecondQuantizedOperator(open_upper_indices, open_lower_indices)
    else:
        sq_op = SecondQuantizedOperator.make_empty()

    # expand hole densities to delta - lambda_1
    sign_densities_pairs = expand_hole_densities(
        list_of_densities) if expand_hole else [(1, list_of_densities)]

    # determine sign
    sign = (-1)**Permutation([base_order_map[i]
                              for i in current_order]).inversions()

    return [(sign * _s, list_of_densities, sq_op)
            for _s, list_of_densities in sign_densities_pairs]
Exemple #2
0
def test_latex_permute_format_1():
    a = SecondQuantizedOperator("g0,g1,g2", "p0,p1,p2", 'spin-orbital')
    p_cre = [[Index(i) for i in "g0,g1,g2".split(',')]]
    p_ann = [[Index(i) for i in "p0,p1,p2".split(',')]]
    n_perm, perm, latex_str = a.latex_permute_format(p_cre, p_ann)
    assert n_perm == 1
    assert perm == ''
    assert latex_str == 'a^{ g_{0} g_{1} g_{2} }_{ p_{0} p_{1} p_{2} }'
Exemple #3
0
def test_index_init():
    with pytest.raises(ValueError):
        Index("x0")
    with pytest.raises(ValueError):
        Index("ax1")
    with pytest.raises(ValueError):
        Index("a1.25")
    with pytest.raises(TypeError):
        Index(123)
def test_indices_init():
    with pytest.raises(ValueError):
        Indices("a0 c1, P2, V8")
    with pytest.raises(ValueError):
        Indices(["a0"] * 3)
    a = Indices("a0, P2")
    assert a.indices == [Index("a0"), Index("P2")]
    assert a.size == 2
    assert a.indices_set == {Index("a0"), Index("P2")}

    a = Indices([])
    assert a == Indices("")
    assert a.size == 0
Exemple #5
0
def test_simplify():
    list_of_tensors = [
        make_tensor('H', "g0", "g0"),
        make_tensor('t', "h0", "p0"),
        make_tensor('t', "p1", "h1"),
        make_tensor('L', 'h0', 'g0'),
        make_tensor('L', 'g0, p1', 'p0, h1')
    ]
    a = Term(list_of_tensors, SecondQuantizedOperator.make_empty(), -1)
    a.simplify()
    assert a.is_void()

    list_of_tensors = [
        make_tensor('H', "g0", "g0"),
        make_tensor('t', "h0", "p0"),
        make_tensor('t', "p1", "h1"),
        make_tensor('L', 'g0', 'h1'),
        make_tensor('L', 'h0', 'g0'),
        make_tensor('K', 'p0', 'p1')
    ]
    a = Term(list_of_tensors, SecondQuantizedOperator.make_empty())
    a.simplify()
    assert a.list_of_tensors == [
        make_tensor('H', 'h6', 'h6'),
        make_tensor('t', 'p1', 'h3'),
        make_tensor('t', 'h4', 'p1'),
        make_tensor('L', 'h6', 'h3'),
        make_tensor('L', 'h4', 'h6')
    ]
    assert a.sq_op == SecondQuantizedOperator.make_empty()
    assert a.indices_set == {Index(i) for i in ['h6', 'p1', 'h3', 'h4']}
    assert a.diagonal_indices == {Index('h6'): 4}

    list_of_tensors = [
        make_tensor('H', "g0", "g0"),
        make_tensor('t', "h0", "p0"),
        make_tensor('t', "p1", "c1"),
        make_tensor('L', 'g0', 'c1'),
        make_tensor('K', 'p0', 'p1')
    ]
    a = Term(list_of_tensors, SecondQuantizedOperator('h0', 'g0'))
    a.simplify()
    assert a.list_of_tensors == [
        make_tensor('H', "c2", "c2"),
        make_tensor('t', "p1", "c2"),
        make_tensor('t', "h0", "p1")
    ]
    assert a.sq_op == SecondQuantizedOperator('h0', 'c2')
    assert a.indices_set == {Index(i) for i in ['c2', 'p1', 'h0']}
    assert a.diagonal_indices == {Index('c2'): 4}
def test_indices_si_latex_permute_format():
    a = IndicesSpinIntegrated(["P0", "P1", "P2", "A3"])
    part = [["P2"], ["P0", "P1"], ["A3"]]
    with pytest.raises(TypeError):
        a.latex_permute_format(part)

    part = [[Index("P2")], [Index("P0"), Index("P1")], [Index("A3")]]
    n_perm, perm_str = a.latex_permute_format(part)
    assert (n_perm, perm_str) == (12,
                                  '{\\cal P} ( P_{2} / P_{0} P_{1} / A_{3} )')

    a = IndicesSpinIntegrated(["p0", "P1", "V2", "A3"])
    with pytest.raises(ValueError):
        list(a.ambit_permute_format(part))
def test_indices_si_ambit_perm():
    a = IndicesSpinIntegrated(["P0", "P1", "V2", "A3"])
    part = [[Index("V2")], [Index("P0"), Index("P1")], [Index("A3")]]
    ref = {
        "P0,P1,V2,A3", "P0,P1,A3,V2", "P0,A3,P1,V2", "A3,P0,P1,V2",
        "P0,V2,P1,A3", "V2,P0,P1,A3", "P0,A3,V2,P1", "P0,V2,A3,P1",
        "V2,P0,A3,P1", "A3,P0,V2,P1", "A3,V2,P0,P1", "V2,A3,P0,P1"
    }
    for sign, indices_str in a.ambit_permute_format(part):
        assert sign == (-1)**a.count_permutations(Indices(indices_str))
        assert indices_str in ref
        ref.remove(indices_str)
    assert len(ref) == 0

    a = IndicesSpinIntegrated(["P0", "P1", "c2", "A3"])
    with pytest.raises(ValueError):
        list(a.ambit_permute_format(part))
Exemple #8
0
def test_multiset_permutation_2():
    a = SecondQuantizedOperator("g0,g1,g2", "p0,p1,p2", 'spin-integrated')
    p_cre = [[Index(i) for i in "g0,g1,g2".split(',')]]
    p_ann = [[Index('p0')], [Index('p1')], [Index('p2')]]
    assert a.exist_permute_format(p_cre, p_ann)
    assert a.n_multiset_permutation(p_cre, p_ann) == 6

    p_ann = [[Index('p0'), Index('p1')], [Index('p2')]]
    assert a.n_multiset_permutation(p_cre, p_ann) == 3
Exemple #9
0
def test_multiset_permutation_5():
    # n_multiset_permutation for spin-adapted operators is always one
    a = SecondQuantizedOperator("g0,v1,p2", "p0,a1,c2", 'spin-adapted')
    p_cre = [[Index('g0'), Index('v1'), Index('p2')]]
    p_ann = [[Index('p0')], [Index('a1')], [Index('c2')]]
    assert not a.exist_permute_format(p_cre, p_ann)
    assert a.n_multiset_permutation(p_cre, p_ann) == 1
Exemple #10
0
def test_latex_permute_format_2():
    a = SecondQuantizedOperator("g0,v1,p3", "p0,a1,p2", 'spin-integrated')
    p_cre = [[Index('g0')], [Index('p3')], [Index('v1')]]
    p_ann = [[Index('p0'), Index('p2')], [Index('a1')]]
    n_perm, perm, latex_str = a.latex_permute_format(p_cre, p_ann)
    assert n_perm == 18
    assert perm == '{\\cal P} ( g_{0} / p_{3} / v_{1} ) {\\cal P} ( p_{0} p_{2} / a_{1} )'
    assert latex_str == 'a^{ g_{0} v_{1} p_{3} }_{ p_{0} a_{1} p_{2} }'
Exemple #11
0
def test_perm_part_2():
    list_of_tensors = [
        make_tensor('H', 'v4, c2', 'v3, c1'),
        make_tensor('T', 'c1', 'v0'),
        make_tensor('T', 'c0, c3', 'v1, v4'),
        make_tensor('T', 'c2, c3', 'v2, v3')
    ]
    sq_op = make_sq('v2, c0', 'v0, v1')
    a = Term(list_of_tensors, sq_op)
    cre_part, ann_part = a.perm_partition_open()
    assert cre_part == [[Index('v2')], [Index('c0')]]
    assert ann_part == [[Index('v0')], [Index('v1')]]

    list_of_tensors = [
        make_tensor('H', 'v3, v4', 'v0, c3'),
        make_tensor('T', 'c0, c1', 'v1, v3'),
        make_tensor('T', 'c2, c3', 'v2, v4')
    ]
    sq_op = make_sq('v0, v1, v2', 'c0, c1, c2')
    a = Term(list_of_tensors, sq_op)
    cre_part, ann_part = a.perm_partition_open()
    assert cre_part == [[Index('v0')], [Index('v1')], [Index('v2')]]
    assert ann_part == [[Index('c0'), Index('c1')], [Index('c2')]]
Exemple #12
0
def test_perm_part_3():
    list_of_tensors = [make_tensor('H', 'g0, h1', 'p1, g0')]
    sq_op = make_sq('g0, p1', 'g0, h1')
    a = Term(list_of_tensors, sq_op, -1)
    cre_part, ann_part = a.perm_partition_open()
    assert cre_part == [[Index('g0')], [Index('p1')]]
    assert ann_part == [[Index('g0')], [Index('h1')]]

    list_of_tensors = [
        make_tensor('H', 'g0, h0, a0', 'g1, p0, p1'),
        make_tensor('t', 'p0, p1', 'a0,a1')
    ]
    sq_op = make_sq('g1, a1', 'g0, h0')
    a = Term(list_of_tensors, sq_op, -1)
    cre_part, ann_part = a.perm_partition_open()
    assert cre_part == [[Index('g1')], [Index('a1')]]
    assert ann_part == [[Index('g0')], [Index('h0')]]
Exemple #13
0
def test_perm_part_1():
    list_of_tensors = [
        make_tensor('H', 'g0, g1', 'g2, p0'),
        make_tensor('T', 'h0, h1', 'p0, p1')
    ]
    sq_op = make_sq('g0, g1, p1', 'g2, h0, h1')
    a = Term(list_of_tensors, sq_op)
    cre_part, ann_part = a.perm_partition_open()
    assert cre_part == [[Index('g0'), Index('g1')], [Index('p1')]]
    assert ann_part == [[Index('g2')], [Index('h0'), Index('h1')]]
Exemple #14
0
def test_latex_permute_format_3():
    # TODO: is this necessary?
    # ignore multiset permutations for mixed spin indices
    a = SecondQuantizedOperator("g0,v1,p2", "p0,a1,P2", 'spin-integrated')
    p_cre = [[Index('g0')], [Index('p2')], [Index('v1')]]
    p_ann = [[Index('p0'), Index('P2')], [Index('a1')]]
    n_perm, perm, latex_str = a.latex_permute_format(p_cre, p_ann)
    assert n_perm == 6
    assert perm == '{\\cal P} ( g_{0} / p_{2} / v_{1} )'
    assert latex_str == 'a^{ g_{0} v_{1} p_{2} }_{ p_{0} a_{1} P_{2} }'
Exemple #15
0
def test_ambit_permute_format_2():
    a = SecondQuantizedOperator("g0,g1,c2", "p0,p1,p2", 'spin-integrated')
    p_cre = [[Index('g0'), Index('g1')], [Index('c2')]]
    p_ann = [[Index('p0'), Index('p1'), Index('p2')]]
    ref = {(1, '["p0,p1,p2,g0,g1,c2"]'), (-1, '["p0,p1,p2,g0,c2,g1"]'),
           (1, '["p0,p1,p2,c2,g0,g1"]')}
    for pair in a.ambit_permute_format(p_cre, p_ann, cre_first=False):
        assert pair in ref
        ref.remove(pair)
    assert len(ref) == 0
def process_composite_categorized(com_cat, ele_con, compatible,
                                  upper_indices_set, lower_indices_set,
                                  base_order_map, n_indices, expand_hole):
    """
    Process one composite categorized contraction.
    :param com_cat: a list of connected operator indices
    :param ele_con: an ElementaryContractionCategorized object
    :param compatible: compatible elementary contractions
    :param upper_indices_set: the set of all creation operators
    :param lower_indices_set: the set of all annihilation operators
    :param base_order_map: the Index map to ordering index
    :param n_indices: the total number of cre and ann operators
    :param expand_hole: expand hole densities to Kronecker delta minus one density if True
    :return: a list of contractions in terms of (sign, list_of_densities, sq_op)
    """
    n_open = n_indices - sum(len(i) for i in com_cat)
    out = []

    for coded_cons in ele_con.composite_contractions(Counter(com_cat),
                                                     compatible):
        contractions = [ele_con.decode(i) for i in coded_cons]

        # cre/ann ordering of the current composite contraction
        current_order = []
        for con in contractions:
            if isinstance(con, HoleDensity):
                current_order += [
                    f"l{con.lower_indices[0].name}",
                    f"u{con.upper_indices[0].name}"
                ]
            else:
                current_order += [f"u{i.name}" for i in con.upper_indices]
                current_order += [
                    f"l{i.name}" for i in con.lower_indices[::-1]
                ]

        # sort open indices
        if n_open != 0:
            contracted = set(current_order)
            open_upper = IndicesSpinOrbital(
                sorted(Index(i[1:]) for i in upper_indices_set - contracted))
            open_lower = IndicesSpinOrbital(
                sorted(Index(i[1:]) for i in lower_indices_set - contracted))
            current_order += [f"u{i.name}" for i in open_upper]
            current_order += [f"l{i.name}" for i in open_lower[::-1]]

            sq_op = SecondQuantizedOperator(open_upper, open_lower)
        else:
            sq_op = SecondQuantizedOperator.make_empty()

        # determine sign of current ordering
        sign = (-1)**Permutation([base_order_map[i]
                                  for i in current_order]).inversions()

        # expand hole density to delta - 1-cumulant
        sign_densities = expand_hole_densities(
            contractions) if expand_hole else [(1, contractions)]

        # append results
        out += [(sign * _s, cons, sq_op) for _s, cons in sign_densities]

    return out
Exemple #17
0
def test_index_ne_2():
    assert Index("a0") != Index("a20")
Exemple #18
0
def test_multiset_permutation_4():
    a = SecondQuantizedOperator("g0,v1,p2", "p0,a1,c2", 'spin-orbital')
    p_cre = [[Index('g0'), Index('v1'), Index('p2')]]
    p_ann = [[Index('p0'), Index('a1'), Index('c2')]]
    assert not a.exist_permute_format(p_cre, p_ann)
    assert a.n_multiset_permutation(p_cre, p_ann) == 1
Exemple #19
0
def test_multiset_permutation_3():
    a = SecondQuantizedOperator("g0,v1,p2", "p0,a1,p2", 'spin-integrated')
    p_cre = [[Index('g0')], [Index('v1')], [Index('p2')]]
    p_ann = [[Index('p0'), Index('p2')], [Index('a1')]]
    assert a.exist_permute_format(p_cre, p_ann)
    assert a.n_multiset_permutation(p_cre, p_ann) == 18
Exemple #20
0
def test_index_gt():
    assert Index("H0") > Index("a4")
Exemple #21
0
def test_multiset_permutation_1():
    a = SecondQuantizedOperator("g0,g1,g2", "p0,p1,p2", 'spin-orbital')
    p_cre = [[Index(i) for i in "g0,g1,g2".split(',')]]
    p_ann = [[Index(i) for i in "p0,p1,p2".split(',')]]
    assert not a.exist_permute_format(p_cre, p_ann)
    assert a.n_multiset_permutation(p_cre, p_ann) == 1
def test_indices_so_ambit_perm():
    a = IndicesSpinOrbital(["p0", "p1", "v2", "a3"])
    part = [[Index("p0"), Index("p1")], [Index("v2")], [Index("a3")]]
    for sign, indices_str in a.ambit_permute_format(part):
        assert sign == (-1)**a.count_permutations(Indices(indices_str))
Exemple #23
0
def test_index_ge():
    assert Index("P1") >= Index("P1")
Exemple #24
0
def test_index_le():
    assert Index("p0") <= Index("p1")
def test_indices_get():
    with pytest.raises(IndexError):
        assert Indices([])[0]
    assert Indices("p0, p1, a0, h0, g4, g1, c1, v2")[2] == Index("a0")
Exemple #26
0
def test_index_ne_1():
    assert Index("a0") != Index("P0")
Exemple #27
0
def test_index_spin():
    assert Index("G1").is_beta()
    assert not Index("g1").is_beta()
    assert Index("a0").to_beta() == Index("A0")
    assert Index("p0").to_alpha() == Index("p0")
def compute_operator_contractions_general(ops_list,
                                          max_cu=3,
                                          max_n_open=6,
                                          min_n_open=0,
                                          expand_hole=True,
                                          n_process=1,
                                          batch_size=1):
    """
    Generate operator contractions for a list of SQOperator (disconnected contractions are included).
    :param ops_list: a list of SecondQuantizedOperator to be contracted
    :param max_cu: max level of cumulant
    :param max_n_open: max number of open indices for contractions kept for return
    :param min_n_open: min number of open indices for contractions kept for return
    :param expand_hole: expand hole density to Kronecker delta and 1-cumulant if True
    :param n_process: the number of processes launched by multiprocessing
    :param batch_size: the chunk size for multiprocessing
    :return: a list of contractions in terms of (sign, list_of_densities, sq_op)
    """
    max_cu_allowed = check_max_cu(ops_list, max_cu)

    # original ordering of the second-quantized operators
    base_order_map, upper_indices_set, lower_indices_set = generate_base_order_map(
        ops_list)
    n_indices = len(base_order_map)

    # un-contracted term
    if min_n_open <= n_indices <= max_n_open:
        sq_op = SecondQuantizedOperator(
            sorted(Index(i[1:]) for i in upper_indices_set),
            sorted(Index(i[1:]) for i in lower_indices_set))
        current_order = [base_order_map[f"u{i.name}"] for i in sq_op.cre_ops]
        current_order += [
            base_order_map[f"l{i.name}"] for i in sq_op.ann_ops[::-1]
        ]
        sign = (-1)**Permutation(current_order).inversions()
        yield [(sign, [], sq_op)]

    # max/min numbers of contracted indices
    max_n_con, min_n_con = n_indices - min_n_open, n_indices - max_n_open

    elementary_contractions = compute_elementary_contractions_list(
        ops_list, max_cu_allowed)
    compatible = compute_compatible_elementary_contractions_list(
        elementary_contractions)

    n_ele_con = len(elementary_contractions)
    if n_ele_con > 1000:
        sys.setrecursionlimit(n_ele_con)

    if n_process == 1:
        for con in composite_contractions_backtrack(set(range(n_ele_con)),
                                                    set(), compatible, 0,
                                                    elementary_contractions,
                                                    (min_n_con, max_n_con)):
            yield process_composite_contractions(con, elementary_contractions,
                                                 n_indices, expand_hole,
                                                 base_order_map,
                                                 upper_indices_set,
                                                 lower_indices_set)
    else:
        composite = [
            list(i)
            for i in composite_contractions_backtrack(set(range(
                n_ele_con)), set(), compatible, 0, elementary_contractions, (
                    min_n_con, max_n_con))
        ]

        n_process = min(n_process, multiprocessing.cpu_count())
        if batch_size == 0:
            n_upper, n_lower = len(upper_indices_set), len(lower_indices_set)
            batch_size = estimate_batch_size(n_upper, n_lower, max_n_con,
                                             min_n_con, n_process)

        with multiprocessing.Pool(n_process, maxtasksperchild=1000) as pool:
            tasks = [(process_composite_contractions,
                      (con, elementary_contractions, n_indices, expand_hole,
                       base_order_map, upper_indices_set, lower_indices_set))
                     for con in composite]

            imap_unordered_it = pool.imap_unordered(calculate_star,
                                                    tasks,
                                                    chunksize=batch_size)
            for results in imap_unordered_it:
                yield results
Exemple #29
0
def test_index_lt():
    assert Index("h0") < Index("G2")
def test_indices_so_latex_perm():
    part = [[Index("g2")], [Index("p0"), Index("p1")], [Index("a4")]]
    n_perm, perm = IndicesSpinOrbital("p0, p1, g2, a4").latex_permute_format(
        part)
    assert n_perm == 12
    assert perm == "{\\cal P} ( g_{2} / p_{0} p_{1} / a_{4} )"