Using FermionicOperators

Fulqrum uses FermionicOperator to describe operators derived from fermionic systems comprised primarily of ladder operators. In reality, the FermionicOperator class shares the same data structures as QubitOperator, and the only real difference comes in the ability to use repeated indices and several different methods attached to the operator. As such, almost all of the building routines are the same as those for QubitOperator but using the ladder operators + and -

[1]:
import fulqrum as fq

Constructing fermionic operators

A simple single-term fermionic operator, here with a width of 14 from an LiH example, can be expressed as:

[2]:
fq.FermionicOperator(14, [("++--", [0, 0, 1, 5], -0.018)])
[2]:
<FermionicOperator[('+:0 +:0 -:1 -:5', (-0.018+0j))], width=14>

If we take the same operator, but reverse the indices, then we get:

[3]:
fq.FermionicOperator(14, [("++--", [5, 1, 0, 0], -0.018)])
[3]:
<FermionicOperator[('-:0 -:0 +:1 +:5', (0.018-0j))], width=14>

Notice that the coefficient has changed sign. This is because the `FermionicOperator`` automatically index sorts the operators from low to high index, and commutation relations will modify signs.

Note that things like creating multi-term operators and combining operators follow in the same manner as QubitOperator

Constructing operators from data files

Usually it is not optimal to create Fermionic operators by hand. Rather, in many cases the operator definition comes from a file that is generated by another piece of software, e.g. quantum chemistry frameworks. For example, here we load an operator generated by PySCF from a JSON file:

[4]:
fop = fq.FermionicOperator.from_json("./data/lih.json")

Additional information about operator IO from files can be found in the “Saving and Loading operators” section.

Fermionic to qubit system transformations

Fulqrum solves every system in the qubit representation. Therefore, FermionicOperator Hamiltonians need to be mapped to QubitOperator Hamiltionians. This is done using a Jordan-Wigner transformation over an extended alphabet:

[5]:
op = fop.extended_jw_transformation()
op
[5]:
<QubitOperator[('', (1.5875316327600002+0j)), ('1:0', (-4.967732288374651+0j)), ('1:6', (-4.967732288374651+0j)), ('1:1', (-1.7548076405756867+0j)), ('1:7', (-1.7548076405756867+0j)), ('1:2', (-1.1812532412470829+0j)), ('1:8', (-1.1812532412470829+0j)), ('1:3', (-1.2007233089159732+0j)), ('1:9', (-1.2007233089159732+0j)), ('1:4', (-1.2007233089159732+0j)), ('1:10', (-1.2007233089159732+0j)), ('1:5', (-0.9457979824776613+0j)), ('1:11', (-0.9457979824776613+0j)), ('1:3 1:11', (0.2726131593772075+0j)), ('1:7 1:10', (0.27395792620390064+0j)), ('1:9 1:11', (0.2569246345868977+0j)), ('1:4 1:11', (0.2726131593772075+0j)), ('1:9 1:10', (0.26249936769660187+0j)), ('1:4 1:10', (0.31312456597262295+0j)), ('1:5 1:10', (0.2726131593772075+0j)), ('1:3 1:5', (0.2569246345868977+0j)), ('1:0 1:5', (0.3757840362595566+0j)), ('1:10 1:11', (0.2569246345868977+0j)), ('1:1 1:9', (0.30086904161844075+0j)), ('1:1 1:4', (0.27395792620390064+0j)), ('1:1 1:10', (0.30086904161844075+0j)), ('1:1 1:5', (0.3381609563972292+0j)), ('1:1 1:11', (0.46210198589061025+0j)), ('1:0 1:7', (0.4700323613830192+0j)), ('1:7 1:9', (0.2739579262039006+0j)), ('1:4 1:7', (0.30086904161844075+0j)), ('1:3 1:10', (0.27937443378860893+0j)), ('+:6 -:7', (0.14689500990413493+0j)), ('-:7 +:8', (0.04174210386247552+0j)), ('-:1 +:2', (0.04174210386247552+0j)), ('+:7 -:8', (0.04174210386247541+0j)), ('+:0 -:1', (0.14689500990413493+0j)), ('-:6 +:7', (0.1468950099041349+0j)), ('1:0 1:6', (1.6531756203466976+0j)), ('+:1 -:2', (0.04174210386247541+0j)), ('-:0 +:1', (0.1468950099041349+0j)), ('1:0 1:11', (0.3815749357621703+0j)), ('1:0 1:4', (0.3866206153123675+0j)), ('1:0 1:10', (0.3967428212067269+0j)), ('1:3 1:4', (0.26249936769660187+0j)), ('1:0 1:9', (0.3967428212067269+0j)), ('1:3 1:9', (0.31312456597262295+0j)), ('1:4 1:9', (0.27937443378860893+0j)), ('1:5 1:9', (0.2726131593772075+0j)), ('1:4 1:5', (0.2569246345868977+0j)), ('1:2 1:8', (0.340603034088326+0j)), ('1:8 1:11', (0.21745337622544536+0j)), ('1:0 1:3', (0.38662061531236747+0j)), ('1:1 1:3', (0.27395792620390064+0j)), ('1:5 1:7', (0.46210198589061025+0j)), ('1:7 1:11', (0.3381609563972292+0j)), ('1:0 1:2', (0.37738710921823815+0j)), ('1:2 1:6', (0.3981911768171463+0j)), ('1:1 1:2', (0.23750997432824672+0j)), ('1:2 1:7', (0.2464567211231602+0j)), ('1:6 1:7', (0.4387719275548865+0j)), ('1:6 1:8', (0.37738710921823815+0j)), ('1:2 1:9', (0.2832160834377335+0j)), ('1:2 1:4', (0.2408328924990534+0j)), ('1:2 1:10', (0.2832160834377335+0j)), ('1:2 1:5', (0.21745337622544536+0j)), ('1:2 1:11', (0.24336203987980187+0j)), ('1:0 1:8', (0.3981911768171463+0j)), ('1:2 1:3', (0.2408328924990534+0j)), ('1:8 1:10', (0.2408328924990534+0j)), ('1:5 1:8', (0.24336203987980187+0j)), ('1:6 1:9', (0.38662061531236747+0j)), ('1:4 1:6', (0.3967428212067269+0j)), ('1:5 1:6', (0.3815749357621703+0j)), ('1:6 1:11', (0.3757840362595566+0j)), ('1:0 1:1', (0.4387719275548865+0j)), ('1:1 1:7', (0.5282910830560855+0j)), ('1:6 1:10', (0.3866206153123675+0j)), ('1:1 1:8', (0.2464567211231602+0j)), ('1:7 1:8', (0.23750997432824672+0j)), ('1:3 1:7', (0.30086904161844075+0j)), ('1:3 1:8', (0.2832160834377335+0j)), ('1:8 1:9', (0.2408328924990534+0j)), ('1:5 1:11', (0.4413865071755077+0j)), ('1:4 1:8', (0.2832160834377335+0j)), ('1:3 1:6', (0.3967428212067269+0j)), ('1:1 1:6', (0.4700323613830192+0j)), ('-:7 +:8 1:9', (-0.018240387107158126+0j)), ('+:0 -:1 1:3', (-0.013941468300143353+0j)), ('1:3 -:7 +:8', (0.0011053878368261314+0j)), ('1:2 -:7 +:8', (-0.0012873819875408453+0j)), ('-:1 +:2 1:8', (-0.0012873819875408453+0j)), ('-:1 +:2 1:3', (-0.018240387107158126+0j)), ('1:0 -:7 +:8', (0.005060272503874282+0j)), ('1:3 +:6 -:7', (-0.0057489959203788615+0j)), ('+:0 -:1 1:8', (-0.016496339989327095+0j)), ('+:1 -:2 1:8', (-0.0012873819875408453+0j)), ('-:7 +:8 1:11', (-0.006468004432162718+0j)), ('1:0 +:7 -:8', (0.005060272503874282+0j)), ('+:0 -:1 1:6', (-0.16149841331635922+0j)) + 531 more terms], width=12>

The resulting operator is now expressed in terms of Z, 0, 1, -, + operators. The resulting operator is also of type = 2, indicating that it is a qubit operator derived from a Fermionic Hamiltonian:

[6]:
op.type
[6]:
2

This type information is used to dispatch to the correct, optimized solver routine.

[ ]: