Mag-group ng mga operator term: gamitin ang estruktura ng operator
Maaaring lagyan ng group index ng isang BosonOperator ang bawat term nito. Walang sariling kahulugan ang mga tag: sinasabi lang nila kung aling mga term ang magkakasama. Ang kahulugan ng mga tag ay itinatakda ng anumang gumagamit sa mga ito. Sa package na ito, ang mga gumagamit ay ang time-evolution gate, na hinahati sa isang factor bawat group, at ang randomized na qDRIFT pass, na nagsa-sample ng buong group.
Ipinapakita ng gabay na ito kung paano magtakda ng mga group, kung paano suriin ang mga property na inaasahan ng gumagamit, at kung paano ayusin ang operator para manatiling mura ang pagpili ng ilang group mula sa malaki.
Walang kasamang awtomatikong grouping strategy ang package na ito. Ikaw mismo ang magtatakda ng mga index, batay sa alam mo tungkol sa modelo mo.
Magtakda ng mga group
Ang running example ay isang three-site na Bose-Hubbard chain. Bawat bond ay nag-aambag ng hopping pair, at ang mga on-site interaction ay bumubuo ng diagonal na piraso. Ang pinakasimpleng paraan para bumuo ng grouped na operator ay ang from_terms_with_groups(), na kumukuha ng bawat term kasama ang group index nito bilang (actions, coefficient, group) na triple. Ikaw ang magpapasya ng group sa sandaling isinusulat mo ang term, kapag alam mo pa kung bakit ito nabibilang doon:
>>> from qiskit_bosons.operators import BosonOperator, ann, cre
>>>
>>> bonds = [(0, 1), (1, 2)]
>>> terms = []
>>> for group, (left, right) in enumerate(bonds): # one group per bond
... terms.append(([cre(left), ann(right)], -1.0, group))
... terms.append(([cre(right), ann(left)], -1.0, group))
>>> for site in range(3): # the on-site interactions share one group
... terms.append(([cre(site), cre(site), ann(site), ann(site)], 1.0, len(bonds)))
>>> hamiltonian = BosonOperator.from_terms_with_groups(terms)
>>> len(hamiltonian), hamiltonian.num_groups()
(7, 3)
Iniimbak ang mga term sa pagkakasunod-sunod na ibinigay mo, kaya hindi maaaring mapunta ang mga group index sa maling term.
Ang operator na umiiral na ay kailangang i-group pagkatapos, sa pamamagitan ng pagtatakda ng groups attribute. Doon kailangan ng ingat, dahil hindi tinutukoy ng from_dict() ang pagkakasunod-sunod ng pag-iimbak nito ng mga term. Ang pagsulat ng listahan ayon sa posisyon ay maaaring magkabit ng index sa maling term. Sa halip, kunin ang bawat index mula sa mismong term:
>>> existing = BosonOperator.from_dict({tuple(actions): coeff for actions, coeff, _ in terms})
>>> existing.groups = [
... len(bonds)
... if len({mode for _, mode in term}) == 1
... else bonds.index(tuple(sorted({mode for _, mode in term})))
... for term, _ in existing.iter_terms()
... ]
>>> existing.num_groups(), existing.equiv(hamiltonian)
(3, True)
Dapat tumugma ang bilang ng mga index sa bilang ng mga term. Tinatanggihan ang anupamang iba, dahil tahimik na magtatanggal ng mga huling term ang masyadong maikling listahan saanman inuulit ang mga term kasama ang mga group nila:
>>> try:
... hamiltonian.groups = [0, 1]
... except ValueError as error:
... print(error)
expected one group index per term, but got 2 for 7 terms
Suriin ang inaasahan ng gumagamit
Tatlong function sa qiskit_bosons.operators.terms ang sumasagot sa tig-iisang makitid na tanong tungkol sa umiiral na grouping. Walang nagsasabing “tama” ang isang grouping, dahil nakadepende sa gumagamit ang pagiging tama.
Hermitian ba ang bawat group? Ito ang pinakamahalagang property. Unitary lang ang time evolution ng isang group kung Hermitian ang group, at ang nag-iisang hopping term na ay hindi. Ang pares lang kasama ang adjoint nito ang Hermitian:
>>> from qiskit_bosons.operators.terms import groups_are_hermitian
>>> groups_are_hermitian(hamiltonian)
[True, True, True]
Agad na nahuhuli ang grouping na naghahati ng hopping pair:
>>> split = BosonOperator.from_terms_with_groups(
... [(actions, coeff, index) for index, (actions, coeff, _) in enumerate(terms)]
... ) # one term per group
>>> [bool(flag) for flag in groups_are_hermitian(split)]
[False, False, False, False, True, True, True]
Nahuli ang apat na hopping term. Ang tatlong True ay ang mga on-site term na , na Hermitian na mag-isa. Puwedeng umulit ang isang mode sa loob ng isang term, at walang tinatanggal dahil doon. Sumusunod ang mga flag sa pagkakasunod-sunod ng terms, kaya mababasa ang bawat isa laban sa term na inilalarawan nito.
Pare-pareho ba ang mga coefficient? Tinitimbang ng randomized product formula ang isang group batay sa mean na magnitude ng mga coefficient nito, na tapat na paglalarawan lang sa group kung magkakapareho ang mga magnitude:
>>> from qiskit_bosons.operators.terms import group_coeff_means, groups_have_uniform_coeffs
>>> groups_have_uniform_coeffs(hamiltonian)
[True, True, True]
>>> group_coeff_means(hamiltonian)
[1.0, 1.0, 1.0]
Hindi nagpapahiwatig ang isa sa dalawang check ng isa pa: hindi nagiging Hermitian ang isang group dahil pare-pareho ang mga coefficient, at puwedeng magkakaiba ang mga magnitude sa isang Hermitian na group. Bilang default, ikinukumpara ang mga magnitude, dahil iyon ang ina-average ng group_coeff_means(). Ang Hermitian na pares na may complex na mga coefficient ay may magkaparehong magnitude pero magkaibang coefficient, kaya ang default na anyo lang ang natutugunan nito:
>>> conjugate = BosonOperator.from_terms_with_groups(
... [([cre(0), ann(1)], 1.0j, 0), ([cre(1), ann(0)], -1.0j, 0)]
... )
>>> groups_have_uniform_coeffs(conjugate)
[True]
>>> groups_have_uniform_coeffs(conjugate, abs=False)
[False]
Ang groups_are_hermitian() ay nakabatay sa is_hermitian(), na ikinukumpara ang isang operator sa adjoint nito pagkatapos ng normal ordering. Identity iyon ng untruncated na algebra, kaya ang group na pumasa ay Hermitian bilang bosonic operator. Tingnan ang Mga prinsipyo ng disenyo ng mga representasyon ng operator para malaman kung paano inaayos at ikinukumpara ang mga produkto ng ladder operator.
Ayusin ang mga term ayon sa group
Ang split_out_groups() ay nagbabalik ng isang operator para sa bawat hiniling na group. Kapag nakakalat sa buong operator ang mga term ng isang group, kailangan nitong suriin ang bawat term para mahanap ang mga ito. Kapag bumubuo ng isang tuloy-tuloy na bloke ang bawat group, binary search na lang ang ginagamit nito sa mga hangganan ng group, kaya sumusunod ang gastos ng isang lookup sa bilang ng mga group na hiniling at hindi sa bilang ng mga term na hawak.
Ang group_order() ang gumagawa ng layout na iyon. Isa itong stable sort ayon sa group index: hindi nagbabago ang value ng operator, at napapanatili ng mga term sa loob ng isang group ang relatibong pagkakasunod-sunod nila.
>>> from qiskit_bosons.operators.terms import group_order
>>> scattered = BosonOperator.from_terms_with_groups(
... [(actions, coeff, group) for (actions, coeff, _), group in zip(terms, [1, 0, 1, 0, 2, 2, 2])]
... )
>>> ordered = group_order(scattered)
>>> ordered.groups
[0, 0, 1, 1, 2, 2, 2]
>>> ordered.equiv(scattered)
True
Parehong operator ang ibinabalik ng dalawang layout; ang gastos lang ang magkaiba:
>>> request = [2, 0]
>>> all(
... a.equiv(b)
... for a, b in zip(
... scattered.split_out_groups(request), ordered.split_out_groups(request), strict=True
... )
... )
True
Mga susunod na hakbang
Dito pinipili ang grouping, sa bosonic na antas, habang nakikita pa ang istruktura ng modelo.
-
Ipinapakita ng Mag-synthesize ng Evolution gate sa bosonic space kung paano ito gagamitin para i-Trotterize ang isang evolution, at kung bakit nababawasan nito ang error na hindi kayang bawasan ng product formula sa antas ng qubit.
-
Ipinapaliwanag ng Mga prinsipyo ng disenyo ng mga representasyon ng operator ang data structure ng operator na may dala ng mga group index, at kung paano iniimbak at inaayos ang mga term nito.
-
Ang 2. Mag-group bago mag-map ay naglalapat ng grouping sa isang kumpletong modelo.