Parameters
As discussed in previous sections, ansatzes are typically defined by a set of parameters. These parameters are handled in InQuanto by means of the two classes: SymbolSet
and
SymbolDict
. Both represent symbolic parameters – the difference between them is that SymbolDict
associates each parameter with a specific value, whereas SymbolSet
does not. In essence, both are wrappers over a Python dict
data structure (with the
SymbolSet
values set to None
and non-accessible), ensuring consistency in the order in which
symbols are added. The keys of a SymbolSet
or SymbolDict
are sympy.Symbol
objects, and thus may be manipulated or created using the SymPy library if required.
Additional convenience methods for SymbolSet
and SymbolDict
are also included. In general, when an ansatz
is being constructed, its state_symbols
member variable represents a SymbolSet
object - just a set of symbolic parameters, without any values assigned. One can also retrieve a
SymbolSet
object from the symbolic operator objects using the free_symbols()
method:
from inquanto.operators import FermionOperatorList
operator = FermionOperatorList.from_string("d0 [(1.0, F2^ F0 F3^ F1)], d1 [(1.0, F4^ F0 F5^ F1)]")
symbols = operator.free_symbols()
print(symbols)
{d0, d1}
and substitute free symbols with the numeric values using the .subs()
method:
from sympy import Symbol
operator.subs({Symbol("d0"): 0.9, Symbol("d1"): 0.1})
print(operator)
d0 [(1.0, F2^ F0 F3^ F1 )],
d1 [(1.0, F4^ F0 F5^ F1 )]
When initiating an Algorithm
object, it is common to pass initial values for ansatz parameters.
Here, convenience methods such as construct_from_array()
, construct_zeros()
and
construct_random()
can be used to convert a SymbolSet
object to a SymbolDict
object, with each symbol being mapped to its value. The order of symbols is maintained in this conversion. For example, with the custom circuit constructed above:
from inquanto.ansatzes import RealRestrictedBasisRotationAnsatz
my_ansatz = RealRestrictedBasisRotationAnsatz(2)
random_param = my_ansatz.state_symbols.construct_random()
print(random_param)
{phi_0: 0.9417154046806644, phi_1: -1.3965781047011498, theta_1_0: -0.6797144480784211}
If necessary, a SymbolDict
object can be manipulated in the same way as an ordinary Python
dict
, i.e. by updating, adding or removing elements:
from inquanto.core import SymbolDict
sd = SymbolDict(a=1, b=2)
sd["b"] = 3
sd["c"] = 2
sd.discard("a")
print(sd)
{b: 3, c: 2}