Пример #1
0
def csdstrs2csdaddrs(norb, neleca, nelecb, csdstrs):
    assert (len(csdstrs[0]) == len(csdstrs[1]))
    assert (len(csdstrs[0]) == len(csdstrs[2]))
    assert (len(csdstrs[0]) == len(csdstrs[3]))
    min_npair, npair_offset, npair_dconf_size, npair_sconf_size, npair_spins_size = get_csdaddrs_shape(
        norb, neleca, nelecb)
    csdaddrs = np.empty(len(csdstrs[0]), dtype=np.int32)
    for npair, offset, dconf_size, sconf_size, spins_size in zip(
            range(min_npair,
                  min(neleca, nelecb) + 1), npair_offset, npair_dconf_size,
            npair_sconf_size, npair_spins_size):
        nspins = neleca + nelecb - 2 * npair
        nup = (nspins + neleca - nelecb) // 2
        assert ((nspins + neleca - nelecb) % 2 == 0)

        idx = (csdstrs[0] == npair)
        dconf_addr = cistring.strs2addr(norb, npair, csdstrs[1, idx])
        sconf_addr = cistring.strs2addr(norb - npair, nspins, csdstrs[2, idx])
        spins_addr = cistring.strs2addr(nspins, nup, csdstrs[3, idx])

        csdaddrs[idx] = np.asarray([
            offset + (dconf * sconf_size * spins_size) +
            (sconf * spins_size) + spins
            for dconf, sconf, spins in zip(dconf_addr, sconf_addr, spins_addr)
        ],
                                   dtype=np.int32)
    return csdaddrs
Пример #2
0
def tn_addrs_signs(norb, nelec, n_excite):
    '''Compute the FCI strings (address) for CIS n-excitation amplitudes and
    the signs of the coefficients when transferring the reference from physics
    vacuum to HF vacuum.
    '''
    if n_excite > nelec:
        print("Warning: Not enough occupied orbitals to excite.")
        return [0], [0]
    nocc = nelec

    hole_strs = cistring.gen_strings4orblist(range(nocc), nocc - n_excite)
    # For HF vacuum, hole operators are ordered from low-lying to high-lying
    # orbitals. It leads to the opposite string ordering.
    hole_strs = hole_strs[::-1]
    hole_sum = numpy.zeros(len(hole_strs), dtype=int)
    for i in range(nocc):
        hole_at_i = (hole_strs & (1 << i)) == 0
        hole_sum[hole_at_i] += i

    # The hole operators are listed from low-lying to high-lying orbitals
    # (from left to right).  For i-th (0-based) hole operator, the number of
    # orbitals which are higher than i determines the sign.  This number
    # equals to nocc-(i+1).  After removing the highest hole operator, nocc
    # becomes nocc-1, the sign for next hole operator j will be associated to
    # nocc-1-(j+1).  By iteratively calling this procedure, the overall sign
    # for annihilating three holes is (-1)**(3*nocc - 6 - sum i)
    sign = (-1)**(n_excite * nocc - n_excite * (n_excite + 1) // 2 - hole_sum)

    particle_strs = cistring.gen_strings4orblist(range(nocc, norb), n_excite)
    strs = hole_strs[:, None] ^ particle_strs
    addrs = cistring.strs2addr(norb, nocc, strs.ravel())
    signs = numpy.vstack([sign] * len(particle_strs)).T.ravel()
    return addrs, signs
Пример #3
0
def csdaddrs2ddaddrs (norb, neleca, nelecb, csdaddrs):
    ''' Inverse operation of ddaddrs2csdaddrs 
        ddaddrs is returned in the format of a contiguous 2d ndarray with shape (naddrs,2), where naddrs is the length of csdaddrs
    '''
    t_start = time.time ()
    csdaddrs = np.asarray (csdaddrs)
    if not csdaddrs.flags['C_CONTIGUOUS']:
        csdaddrs = np.ravel (csdaddrs, order='C')
    t0 = time.time ()
    csdstrs = csdaddrs2csdstrs (norb, neleca, nelecb, csdaddrs)
    t1 = time.time ()
    ddstrs = csdstrs2ddstrs (norb, neleca, nelecb, csdstrs)
    t2 = time.time ()
    ddaddrs = np.ascontiguousarray ([cistring.strs2addr (norb, neleca, ddstrs[0]), cistring.strs2addr (norb, nelecb, ddstrs[1])], dtype=np.int32)
    t3 = time.time ()
    t_tot = time.time () - t_start
    return ddaddrs
Пример #4
0
    def test_str2addr(self):
        self.assertEqual(cistring.str2addr(6, 3, int('0b11001' ,2)), 7)
        self.assertEqual(cistring.str2addr(6, 3, int('0b11010' ,2)), 8)
        self.assertEqual(cistring.str2addr(7, 4, int('0b110011',2)), 9)
        self.assertEqual(cistring.str2addr(6, 3, cistring.addr2str(6, 3, 7)), 7)
        self.assertEqual(cistring.str2addr(6, 3, cistring.addr2str(6, 3, 8)), 8)
        self.assertEqual(cistring.str2addr(7, 4, cistring.addr2str(7, 4, 9)), 9)

        self.assertTrue(all(numpy.arange(20) ==
                            cistring.strs2addr(6, 3, cistring.addrs2str(6, 3, range(20)))))
Пример #5
0
    def test_str2addr(self):
        self.assertEqual(cistring.str2addr(6, 3, int('0b11001', 2)), 7)
        self.assertEqual(cistring.str2addr(6, 3, int('0b11010', 2)), 8)
        self.assertEqual(cistring.str2addr(7, 4, int('0b110011', 2)), 9)
        self.assertEqual(cistring.str2addr(6, 3, cistring.addr2str(6, 3, 7)),
                         7)
        self.assertEqual(cistring.str2addr(6, 3, cistring.addr2str(6, 3, 8)),
                         8)
        self.assertEqual(cistring.str2addr(7, 4, cistring.addr2str(7, 4, 9)),
                         9)

        self.assertTrue(
            all(
                numpy.arange(20) == cistring.strs2addr(
                    6, 3, cistring.addrs2str(6, 3, range(20)))))
Пример #6
0
def to_fcivec(cisdvec, norb, nelec, frozen=0):
    '''Convert CISD coefficients to FCI coefficients'''
    if isinstance(nelec, (int, numpy.number)):
        nelecb = nelec//2
        neleca = nelec - nelecb
    else:
        neleca, nelecb = nelec

    frozena_mask = numpy.zeros(norb, dtype=bool)
    frozenb_mask = numpy.zeros(norb, dtype=bool)
    if isinstance(frozen, (int, numpy.integer)):
        nfroza = nfrozb = frozen
        frozena_mask[:frozen] = True
        frozenb_mask[:frozen] = True
    else:
        nfroza = len(frozen[0])
        nfrozb = len(frozen[1])
        frozena_mask[frozen[0]] = True
        frozenb_mask[frozen[1]] = True

#    if nfroza != nfrozb:
#        raise NotImplementedError
    nocca = numpy.count_nonzero(~frozena_mask[:neleca])
    noccb = numpy.count_nonzero(~frozenb_mask[:nelecb])
    nmo = nmoa, nmob = norb - nfroza, norb - nfrozb
    nocc = nocca, noccb
    nvira, nvirb = nmoa - nocca, nmob - noccb

    c0, c1, c2 = cisdvec_to_amplitudes(cisdvec, nmo, nocc)
    c1a, c1b = c1
    c2aa, c2ab, c2bb = c2
    t1addra, t1signa = cisd.tn_addrs_signs(nmoa, nocca, 1)
    t1addrb, t1signb = cisd.tn_addrs_signs(nmob, noccb, 1)

    na = cistring.num_strings(nmoa, nocca)
    nb = cistring.num_strings(nmob, noccb)
    fcivec = numpy.zeros((na,nb))
    fcivec[0,0] = c0
    fcivec[t1addra,0] = c1a.ravel() * t1signa
    fcivec[0,t1addrb] = c1b.ravel() * t1signb
    c2ab = c2ab.transpose(0,2,1,3).reshape(nocca*nvira,-1)
    c2ab = numpy.einsum('i,j,ij->ij', t1signa, t1signb, c2ab)
    fcivec[t1addra[:,None],t1addrb] = c2ab

    if nocca > 1 and nvira > 1:
        ooidx = numpy.tril_indices(nocca, -1)
        vvidx = numpy.tril_indices(nvira, -1)
        c2aa = c2aa[ooidx][:,vvidx[0],vvidx[1]]
        t2addra, t2signa = cisd.tn_addrs_signs(nmoa, nocca, 2)
        fcivec[t2addra,0] = c2aa.ravel() * t2signa
    if noccb > 1 and nvirb > 1:
        ooidx = numpy.tril_indices(noccb, -1)
        vvidx = numpy.tril_indices(nvirb, -1)
        c2bb = c2bb[ooidx][:,vvidx[0],vvidx[1]]
        t2addrb, t2signb = cisd.tn_addrs_signs(nmob, noccb, 2)
        fcivec[0,t2addrb] = c2bb.ravel() * t2signb

    if nfroza == nfrozb == 0:
        return fcivec

    assert(norb < 63)

    strsa = cistring.gen_strings4orblist(range(norb), neleca)
    strsb = cistring.gen_strings4orblist(range(norb), nelecb)
    na = len(strsa)
    nb = len(strsb)
    count_a = numpy.zeros(na, dtype=int)
    count_b = numpy.zeros(nb, dtype=int)
    parity_a = numpy.zeros(na, dtype=bool)
    parity_b = numpy.zeros(nb, dtype=bool)
    core_a_mask = numpy.ones(na, dtype=bool)
    core_b_mask = numpy.ones(nb, dtype=bool)

    for i in range(norb):
        if frozena_mask[i]:
            if i < neleca:
                core_a_mask &= (strsa & (1<<i)) != 0
                parity_a ^= (count_a & 1) == 1
            else:
                core_a_mask &= (strsa & (1<<i)) == 0
        else:
            count_a += (strsa & (1<<i)) != 0

        if frozenb_mask[i]:
            if i < nelecb:
                core_b_mask &= (strsb & (1<<i)) != 0
                parity_b ^= (count_b & 1) == 1
            else:
                core_b_mask &= (strsb & (1<<i)) == 0
        else:
            count_b += (strsb & (1<<i)) != 0

    sub_strsa = strsa[core_a_mask & (count_a == nocca)]
    sub_strsb = strsb[core_b_mask & (count_b == noccb)]
    addrsa = cistring.strs2addr(norb, neleca, sub_strsa)
    addrsb = cistring.strs2addr(norb, nelecb, sub_strsb)
    fcivec1 = numpy.zeros((na,nb))
    fcivec1[addrsa[:,None],addrsb] = fcivec
    fcivec1[parity_a,:] *= -1
    fcivec1[:,parity_b] *= -1
    return fcivec1
Пример #7
0
def to_fcivec(cisdvec, norb, nelec, frozen=None):
    '''Convert CISD coefficients to FCI coefficients'''
    if isinstance(nelec, (int, numpy.number)):
        nelecb = nelec // 2
        neleca = nelec - nelecb
    else:
        neleca, nelecb = nelec
        assert (neleca == nelecb)

    frozen_mask = numpy.zeros(norb, dtype=bool)
    if frozen is None:
        nfroz = 0
    elif isinstance(frozen, (int, numpy.integer)):
        nfroz = frozen
        frozen_mask[:frozen] = True
    else:
        nfroz = len(frozen)
        frozen_mask[frozen] = True

    nocc = numpy.count_nonzero(~frozen_mask[:neleca])
    nmo = norb - nfroz
    nvir = nmo - nocc
    c0, c1, c2 = cisdvec_to_amplitudes(cisdvec, nmo, nocc)
    t1addr, t1sign = tn_addrs_signs(nmo, nocc, 1)

    na = cistring.num_strings(nmo, nocc)
    fcivec = numpy.zeros((na, na))
    fcivec[0, 0] = c0
    fcivec[0, t1addr] = fcivec[t1addr, 0] = c1.ravel() * t1sign
    c2ab = c2.transpose(0, 2, 1, 3).reshape(nocc * nvir, -1)
    c2ab = numpy.einsum('i,j,ij->ij', t1sign, t1sign, c2ab)
    fcivec[t1addr[:, None], t1addr] = c2ab

    if nocc > 1 and nvir > 1:
        c2aa = c2 - c2.transpose(1, 0, 2, 3)
        ooidx = numpy.tril_indices(nocc, -1)
        vvidx = numpy.tril_indices(nvir, -1)
        c2aa = c2aa[ooidx][:, vvidx[0], vvidx[1]]
        t2addr, t2sign = tn_addrs_signs(nmo, nocc, 2)
        fcivec[0, t2addr] = fcivec[t2addr, 0] = c2aa.ravel() * t2sign

    if nfroz == 0:
        return fcivec

    assert (norb < 63)

    strs = cistring.gen_strings4orblist(range(norb), neleca)
    na = len(strs)
    count = numpy.zeros(na, dtype=int)
    parity = numpy.zeros(na, dtype=bool)
    core_mask = numpy.ones(na, dtype=bool)
    # During the loop, count saves the number of occupied orbitals that
    # lower (with small orbital ID) than the present orbital i.
    # Moving all the frozen orbitals to the beginning of the orbital list
    # (before the occupied orbitals) leads to parity odd (= True, with
    # negative sign) or even (= False, with positive sign).
    for i in range(norb):
        if frozen_mask[i]:
            if i < neleca:
                # frozen occupied orbital should be occupied
                core_mask &= (strs & (1 << i)) != 0
                parity ^= (count & 1) == 1
            else:
                # frozen virtual orbital should not be occupied.
                # parity is not needed since it's unoccupied
                core_mask &= (strs & (1 << i)) == 0
        else:
            count += (strs & (1 << i)) != 0
    sub_strs = strs[core_mask & (count == nocc)]
    addrs = cistring.strs2addr(norb, neleca, sub_strs)
    fcivec1 = numpy.zeros((na, na))
    fcivec1[addrs[:, None], addrs] = fcivec
    fcivec1[parity, :] *= -1
    fcivec1[:, parity] *= -1
    return fcivec1
Пример #8
0
def to_fcivec(cisdvec, norb, nelec, frozen=0):
    '''Convert CISD coefficients to FCI coefficients'''
    if isinstance(nelec, (int, numpy.number)):
        nelecb = nelec // 2
        neleca = nelec - nelecb
    else:
        neleca, nelecb = nelec
        assert (neleca == nelecb)

    frozen_mask = numpy.zeros(norb, dtype=bool)
    if isinstance(frozen, (int, numpy.integer)):
        nfroz = frozen
        frozen_mask[:frozen] = True
    else:
        nfroz = len(frozen)
        frozen_mask[frozen] = True

    nocc = numpy.count_nonzero(~frozen_mask[:neleca])
    nmo = norb - nfroz
    nvir = nmo - nocc
    c0, c1, c2 = cisdvec_to_amplitudes(cisdvec, nmo, nocc)
    t1addr, t1sign = t1strs(nmo, nocc)

    na = cistring.num_strings(nmo, nocc)
    fcivec = numpy.zeros((na, na))
    fcivec[0, 0] = c0
    c1 = c1[::-1].T.ravel()
    fcivec[0, t1addr] = fcivec[t1addr, 0] = c1 * t1sign
    c2ab = c2[::-1, ::-1].transpose(2, 0, 3, 1).reshape(nocc * nvir, -1)
    c2ab = numpy.einsum('i,j,ij->ij', t1sign, t1sign, c2ab)
    lib.takebak_2d(fcivec, c2ab, t1addr, t1addr)

    if nocc > 1 and nvir > 1:
        hf_str = int('1' * nocc, 2)
        for a in range(nocc, nmo):
            for b in range(nocc, a):
                for i in reversed(range(1, nocc)):
                    for j in reversed(range(i)):
                        c2aa = c2[i, j, a - nocc,
                                  b - nocc] - c2[j, i, a - nocc, b - nocc]
                        str1 = hf_str ^ (1 << j) | (1 << b)
                        c2aa *= cistring.cre_des_sign(b, j, hf_str)
                        c2aa *= cistring.cre_des_sign(a, i, str1)
                        str1 ^= (1 << i) | (1 << a)
                        addr = cistring.str2addr(nmo, nocc, str1)
                        fcivec[0, addr] = fcivec[addr, 0] = c2aa

    if nfroz == 0:
        return fcivec

    assert (norb < 63)

    strs = cistring.gen_strings4orblist(range(norb), neleca)
    na = len(strs)
    count = numpy.zeros(na, dtype=int)
    parity = numpy.zeros(na, dtype=bool)
    core_mask = numpy.ones(na, dtype=bool)
    # During the loop, count saves the number of occupied orbitals that
    # lower (with small orbital ID) than the present orbital i.
    # Moving all the frozen orbitals to the beginning of the orbital list
    # (before the occupied orbitals) leads to parity odd (= True, with
    # negative sign) or even (= False, with positive sign).
    for i in range(norb):
        if frozen_mask[i]:
            if i < neleca:
                # frozen occupied orbital should be occupied
                core_mask &= (strs & (1 << i)) != 0
                parity ^= (count & 1) == 1
            else:
                # frozen virtual orbital should not be occupied.
                # parity is not needed since it's unoccupied
                core_mask &= (strs & (1 << i)) == 0
        else:
            count += (strs & (1 << i)) != 0
    sub_strs = strs[core_mask & (count == nocc)]
    addrs = cistring.strs2addr(norb, neleca, sub_strs)
    fcivec1 = numpy.zeros((na, na))
    fcivec1[addrs[:, None], addrs] = fcivec
    fcivec1[parity, :] *= -1
    fcivec1[:, parity] *= -1
    return fcivec1
Пример #9
0
def to_fcivec(cisdvec, norb, nelec, frozen=0):
    '''Convert CISD coefficients to FCI coefficients'''
    if isinstance(nelec, (int, numpy.number)):
        nelecb = nelec//2
        neleca = nelec - nelecb
    else:
        neleca, nelecb = nelec

    frozena_mask = numpy.zeros(norb, dtype=bool)
    frozenb_mask = numpy.zeros(norb, dtype=bool)
    if isinstance(frozen, (int, numpy.integer)):
        nfroza = nfrozb = frozen
        frozena_mask[:frozen] = True
        frozenb_mask[:frozen] = True
    else:
        nfroza = len(frozen[0])
        nfrozb = len(frozen[1])
        frozena_mask[frozen[0]] = True
        frozenb_mask[frozen[1]] = True

#    if nfroza != nfrozb:
#        raise NotImplementedError
    nocca = numpy.count_nonzero(~frozena_mask[:neleca])
    noccb = numpy.count_nonzero(~frozenb_mask[:nelecb])
    nmo = nmoa, nmob = norb - nfroza, norb - nfrozb
    nocc = nocca, noccb
    nvira, nvirb = nmoa - nocca, nmob - noccb

    c0, c1, c2 = cisdvec_to_amplitudes(cisdvec, nmo, nocc)
    c1a, c1b = c1
    c2aa, c2ab, c2bb = c2
    t1addra, t1signa = cisd.tn_addrs_signs(nmoa, nocca, 1)
    t1addrb, t1signb = cisd.tn_addrs_signs(nmob, noccb, 1)

    na = cistring.num_strings(nmoa, nocca)
    nb = cistring.num_strings(nmob, noccb)
    fcivec = numpy.zeros((na,nb))
    fcivec[0,0] = c0
    fcivec[t1addra,0] = c1a.ravel() * t1signa
    fcivec[0,t1addrb] = c1b.ravel() * t1signb
    c2ab = c2ab.transpose(0,2,1,3).reshape(nocca*nvira,-1)
    c2ab = numpy.einsum('i,j,ij->ij', t1signa, t1signb, c2ab)
    fcivec[t1addra[:,None],t1addrb] = c2ab

    if nocca > 1 and nvira > 1:
        ooidx = numpy.tril_indices(nocca, -1)
        vvidx = numpy.tril_indices(nvira, -1)
        c2aa = c2aa[ooidx][:,vvidx[0],vvidx[1]]
        t2addra, t2signa = cisd.tn_addrs_signs(nmoa, nocca, 2)
        fcivec[t2addra,0] = c2aa.ravel() * t2signa
    if noccb > 1 and nvirb > 1:
        ooidx = numpy.tril_indices(noccb, -1)
        vvidx = numpy.tril_indices(nvirb, -1)
        c2bb = c2bb[ooidx][:,vvidx[0],vvidx[1]]
        t2addrb, t2signb = cisd.tn_addrs_signs(nmob, noccb, 2)
        fcivec[0,t2addrb] = c2bb.ravel() * t2signb

    if nfroza == nfrozb == 0:
        return fcivec

    assert(norb < 63)

    strsa = cistring.gen_strings4orblist(range(norb), neleca)
    strsb = cistring.gen_strings4orblist(range(norb), nelecb)
    na = len(strsa)
    nb = len(strsb)
    count_a = numpy.zeros(na, dtype=int)
    count_b = numpy.zeros(nb, dtype=int)
    parity_a = numpy.zeros(na, dtype=bool)
    parity_b = numpy.zeros(nb, dtype=bool)
    core_a_mask = numpy.ones(na, dtype=bool)
    core_b_mask = numpy.ones(nb, dtype=bool)

    for i in range(norb):
        if frozena_mask[i]:
            if i < neleca:
                core_a_mask &= (strsa & (1<<i)) != 0
                parity_a ^= (count_a & 1) == 1
            else:
                core_a_mask &= (strsa & (1<<i)) == 0
        else:
            count_a += (strsa & (1<<i)) != 0

        if frozenb_mask[i]:
            if i < nelecb:
                core_b_mask &= (strsb & (1<<i)) != 0
                parity_b ^= (count_b & 1) == 1
            else:
                core_b_mask &= (strsb & (1<<i)) == 0
        else:
            count_b += (strsb & (1<<i)) != 0

    sub_strsa = strsa[core_a_mask & (count_a == nocca)]
    sub_strsb = strsb[core_b_mask & (count_b == noccb)]
    addrsa = cistring.strs2addr(norb, neleca, sub_strsa)
    addrsb = cistring.strs2addr(norb, nelecb, sub_strsb)
    fcivec1 = numpy.zeros((na,nb))
    fcivec1[addrsa[:,None],addrsb] = fcivec
    fcivec1[parity_a,:] *= -1
    fcivec1[:,parity_b] *= -1
    return fcivec1