diff --git a/.nojekyll b/.nojekyll index 9454f81..2b060d8 100644 --- a/.nojekyll +++ b/.nojekyll @@ -1 +1 @@ -e183e519 \ No newline at end of file +cb39cde6 \ No newline at end of file diff --git a/FAQ.html b/FAQ.html index 90cc173..63f95e2 100644 --- a/FAQ.html +++ b/FAQ.html @@ -210,7 +210,7 @@
Categories
-
+
diff --git a/Researches/Eigensolver/Eigensolver.html b/Researches/Eigensolver/Eigensolver.html index 9db81b7..5fbff6a 100644 --- a/Researches/Eigensolver/Eigensolver.html +++ b/Researches/Eigensolver/Eigensolver.html @@ -388,11 +388,11 @@

Projection Method

1
-The circuit list consists of the circuits preparing the i-th state. The addition is not an actual addition, but the concatenation operator for quantum circuits. +The circuit list consists of the circuits preparing the i-th state. The addition is not an actual addition, but the concatenation operator for quantum circuits.
2
-This is the 0-projector. +This is the 0-projector.
@@ -895,7 +895,7 @@

Chemistry example

1
-This is the given circuit, which consists of two rotations and two correlations. Thus, we are particularly able to analize the correlators and study their behaviour. +This is the given circuit, which consists of two rotations and two correlations. Thus, we are particularly able to analize the correlators and study their behaviour.
diff --git a/Researches/Eigensolver/Eigensolver.pdf b/Researches/Eigensolver/Eigensolver.pdf index fa652eb..4ba0d9f 100644 Binary files a/Researches/Eigensolver/Eigensolver.pdf and b/Researches/Eigensolver/Eigensolver.pdf differ diff --git a/Researches/quantum_classifier/quantum_classifier.html b/Researches/quantum_classifier/quantum_classifier.html index fa5d9c3..e108f42 100644 --- a/Researches/quantum_classifier/quantum_classifier.html +++ b/Researches/quantum_classifier/quantum_classifier.html @@ -322,31 +322,31 @@

1
-Initialize tunable variables, that will be optimized later +Initialize tunable variables, that will be optimized later
2
-Create a unitary/quantum circuit using a given problem structure +Create a unitary/quantum circuit using a given problem structure
3
-Define an Observable whose expectation we want to measure +Define an Observable whose expectation we want to measure
4
-Define the Objective/Loss function we want to minimize as the expectation value of the Observable after applying the Unitary +Define the Objective/Loss function we want to minimize as the expectation value of the Observable after applying the Unitary
5
-Define some initial values for the variables we want to optimize +Define some initial values for the variables we want to optimize
6
-Minimize the Objective through one of many different minimization methods to compute optimal variable assignments +Minimize the Objective through one of many different minimization methods to compute optimal variable assignments
7
-Return the calculated parameters of the circuit and the minimal value of the Objective +Return the calculated parameters of the circuit and the minimal value of the Objective

@@ -615,15 +615,15 @@

3.4 Loss function

1
-We iterate through the training data and calculate the impact of that datapoint on the loss function +We iterate through the training data and calculate the impact of that datapoint on the loss function
2
-The fidelity between the circuit result and the correct label state is expressed as a expectation value +The fidelity between the circuit result and the correct label state is expressed as a expectation value
3
-A value in \([0,1]\) gets added based on how good the current datapoint is treated by the circuit +A value in \([0,1]\) gets added based on how good the current datapoint is treated by the circuit
diff --git a/Tutorials/AdaptiveMethods/jupyter_notebook.html b/Tutorials/AdaptiveMethods/jupyter_notebook.html index d705ab9..4e79a90 100644 --- a/Tutorials/AdaptiveMethods/jupyter_notebook.html +++ b/Tutorials/AdaptiveMethods/jupyter_notebook.html @@ -4521,7 +4521,7 @@ ,[50,"__ccd_conversion_marking",[46,"a"],[22,[30,[28,[17,[15,"a"],"conversionRules"]],[20,[17,[17,[15,"a"],"conversionRules"],"length"],0]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[52,"b",["require","internal.copyPreHit"]],[52,"c",["require","internal.evaluateBooleanExpression"]],[52,"d",["require","internal.registerCcdCallback"]],[52,"e","is_conversion"],[52,"f","is_first_visit"],[52,"g","is_first_visit_conversion"],[52,"h","is_session_start"],[52,"i","is_session_start_conversion"],[52,"j","first_visit"],[52,"k","session_start"],[41,"l"],[41,"m"],["d",[17,[15,"a"],"instanceDestinationId"],[51,"",[7,"n"],[52,"o",[8,"preHit",[15,"n"]]],[65,"p",[17,[15,"a"],"conversionRules"],[46,[22,["c",[17,[15,"p"],"matchingRules"],[15,"o"]],[46,[2,[15,"n"],"setMetadata",[7,[15,"e"],true]],[4]]]]],[22,[2,[15,"n"],"getMetadata",[7,[15,"f"]]],[46,[22,[28,[15,"l"]],[46,[53,[52,"p",["b",[15,"n"],[8,"omitHitData",true,"omitMetadata",true]]],[2,[15,"p"],"setEventName",[7,[15,"j"]]],[3,"l",[8,"preHit",[15,"p"]]]]]],[65,"p",[17,[15,"a"],"conversionRules"],[46,[22,["c",[17,[15,"p"],"matchingRules"],[15,"l"]],[46,[2,[15,"n"],"setMetadata",[7,[15,"g"],true]],[4]]]]]]],[22,[2,[15,"n"],"getMetadata",[7,[15,"h"]]],[46,[22,[28,[15,"m"]],[46,[53,[52,"p",["b",[15,"n"],[8,"omitHitData",true,"omitMetadata",true]]],[2,[15,"p"],"setEventName",[7,[15,"k"]]],[3,"m",[8,"preHit",[15,"p"]]]]]],[65,"p",[17,[15,"a"],"conversionRules"],[46,[22,["c",[17,[15,"p"],"matchingRules"],[15,"m"]],[46,[2,[15,"n"],"setMetadata",[7,[15,"i"],true]],[4]]]]]]]]],[2,[15,"a"],"gtmOnSuccess",[7]],[36]] ,[50,"__ccd_em_download",[46,"a"],[50,"r",[46,"x"],[36,[1,[15,"x"],[21,[2,[2,[15,"x"],"toLowerCase",[7]],"match",[7,[15,"q"]]],[45]]]]],[50,"s",[46,"x"],[52,"y",[2,[17,[15,"x"],"pathname"],"split",[7,"."]]],[52,"z",[39,[18,[17,[15,"y"],"length"],1],[16,[15,"y"],[37,[17,[15,"y"],"length"],1]],""]],[36,[16,[2,[15,"z"],"split",[7,"/"]],0]]],[50,"t",[46,"x"],[36,[39,[12,[2,[17,[15,"x"],"pathname"],"substring",[7,0,1]],"/"],[17,[15,"x"],"pathname"],[0,"/",[17,[15,"x"],"pathname"]]]]],[50,"u",[46,"x"],[41,"y"],[3,"y",""],[22,[1,[15,"x"],[17,[15,"x"],"href"]],[46,[53,[41,"z"],[3,"z",[2,[17,[15,"x"],"href"],"indexOf",[7,"#"]]],[3,"y",[39,[23,[15,"z"],0],[17,[15,"x"],"href"],[2,[17,[15,"x"],"href"],"substring",[7,0,[15,"z"]]]]]]]],[36,[15,"y"]]],[50,"w",[46,"x"],[52,"y",[8]],[43,[15,"y"],[15,"j"],true],[43,[15,"y"],[15,"f"],true],[43,[15,"x"],"eventMetadata",[15,"y"]]],[52,"b",[13,[41,"$0"],[3,"$0",["require","internal.getFlags"]],["$0"]]],[52,"c",["require","internal.getProductSettingsParameter"]],[52,"d",["require","templateStorage"]],[52,"e",[15,"__module_ccdEmDownloadActivity"]],[52,"f","speculative"],[52,"g","ae_block_downloads"],[52,"h","file_download"],[52,"i","isRegistered"],[52,"j","em_event"],[52,"k",[17,[15,"a"],"instanceDestinationId"]],[22,["c",[15,"k"],[15,"g"]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[2,[15,"e"],"registerDownloadActivityCallback",[7,[15,"k"],[17,[15,"a"],"includeParams"]]],[22,[2,[15,"d"],"getItem",[7,[15,"i"]]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[52,"l",["require","internal.addDataLayerEventListener"]],[52,"m",["require","internal.enableAutoEventOnLinkClick"]],[52,"n",["require","internal.getDestinationIds"]],[52,"o",["require","parseUrl"]],[52,"p",["require","internal.sendGtagEvent"]],[52,"q",[0,"^(pdf|xlsx?|docx?|txt|rtf|csv|exe|key|pp(s|t|tx)|7z|pkg|rar|gz|zip|avi|","mov|mp4|mpe?g|wmv|midi?|mp3|wav|wma)$"]],[52,"v",["m",[8,"checkValidation",true]]],[22,[28,[15,"v"]],[46,[2,[15,"a"],"gtmOnFailure",[7]],[36]]],[2,[15,"d"],"setItem",[7,[15,"i"],true]],["l","gtm.linkClick",[51,"",[7,"x","y"],["y"],[52,"z",[8,"eventId",[16,[15,"x"],"gtm.uniqueEventId"]]],[22,[16,[15,"b"],"enableDeferAllEnhancedMeasurement"],[46,[43,[15,"z"],"deferrable",true]]],[52,"ba",[16,[15,"x"],"gtm.elementUrl"]],[52,"bb",["o",[15,"ba"]]],[22,[28,[15,"bb"]],[46,[36]]],[52,"bc",["s",[15,"bb"]]],[22,[28,["r",[15,"bc"]]],[46,[36]]],[52,"bd",[8,"link_id",[16,[15,"x"],"gtm.elementId"],"link_url",["u",[15,"bb"]],"link_text",[16,[15,"x"],"gtm.elementText"],"file_name",["t",[15,"bb"]],"file_extension",[15,"bc"]]],["w",[15,"z"]],["p",["n"],[15,"h"],[15,"bd"],[15,"z"]]],[15,"v"]],[2,[15,"a"],"gtmOnSuccess",[7]]] ,[50,"__ccd_em_form",[46,"a"],[50,"t",[46,"ba"],[52,"bb",[30,[16,[15,"ba"],[15,"l"]],[8]]],[43,[15,"bb"],"event_usage",[7,8]],[43,[15,"ba"],[15,"l"],[15,"bb"]]],[50,"u",[46,"ba","bb"],[52,"bc",[30,[16,[15,"ba"],[15,"l"]],[8]]],[43,[15,"bc"],[15,"k"],true],[43,[15,"bc"],[15,"f"],true],[22,[1,[15,"o"],[16,[15,"bb"],"gtm.formCanceled"]],[46,[43,[15,"bc"],[15,"m"],true]]],[43,[15,"ba"],[15,"l"],[15,"bc"]]],[50,"v",[46,"ba","bb","bc"],[52,"bd",[2,["r"],"filter",[7,[51,"",[7,"bf"],[36,[20,[2,[15,"bf"],"indexOf",[7,"AW-"]],0]]]]]],[22,[18,[17,[15,"bd"],"length"],0],[46,["s",[15,"bd"],[15,"ba"],[15,"bb"],[15,"bc"]]]],[52,"be",[2,["r"],"filter",[7,[51,"",[7,"bf"],[36,[21,[2,[15,"bf"],"indexOf",[7,"AW-"]],0]]]]]],[22,[18,[17,[15,"be"],"length"],0],[46,[22,[16,[15,"b"],"enableDeferAllEnhancedMeasurement"],[46,[43,[15,"bc"],"deferrable",true]]],["s",[15,"be"],[15,"ba"],[15,"bb"],[15,"bc"]]]]],[52,"b",[13,[41,"$0"],[3,"$0",["require","internal.getFlags"]],["$0"]]],[52,"c",["require","internal.getProductSettingsParameter"]],[52,"d",["require","templateStorage"]],[52,"e",[15,"__module_ccdEmFormActivity"]],[52,"f","speculative"],[52,"g","ae_block_form"],[52,"h","form_submit"],[52,"i","form_start"],[52,"j","isRegistered"],[52,"k","em_event"],[52,"l","eventMetadata"],[52,"m","form_event_canceled"],[52,"n",[17,[15,"a"],"instanceDestinationId"]],[52,"o",[28,[28,[16,[15,"b"],"enableFormSkipValidation"]]]],[22,["c",[15,"n"],[15,"g"]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[2,[15,"e"],"registerFormActivityCallback",[7,[17,[15,"a"],"instanceDestinationId"],[17,[15,"a"],"skipValidation"],[17,[15,"a"],"includeParams"]]],[22,[2,[15,"d"],"getItem",[7,[15,"j"]]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[2,[15,"d"],"setItem",[7,[15,"j"],true]],[52,"p",["require","internal.addFormInteractionListener"]],[52,"q",["require","internal.addFormSubmitListener"]],[52,"r",["require","internal.getDestinationIds"]],[52,"s",["require","internal.sendGtagEvent"]],[52,"w",[8]],[52,"x",[51,"",[7,"ba","bb"],[22,[15,"bb"],[46,["bb"]]],[52,"bc",[16,[15,"ba"],"gtm.elementId"]],[22,[16,[15,"w"],[15,"bc"]],[46,[36]]],[43,[15,"w"],[15,"bc"],true],[52,"bd",[8,"form_id",[15,"bc"],"form_name",[16,[15,"ba"],"gtm.interactedFormName"],"form_destination",[16,[15,"ba"],"gtm.elementUrl"],"form_length",[16,[15,"ba"],"gtm.interactedFormLength"],"first_field_id",[16,[15,"ba"],"gtm.interactedFormFieldId"],"first_field_name",[16,[15,"ba"],"gtm.interactedFormFieldName"],"first_field_type",[16,[15,"ba"],"gtm.interactedFormFieldType"],"first_field_position",[16,[15,"ba"],"gtm.interactedFormFieldPosition"]]],[52,"be",[8,"eventId",[17,[15,"a"],"gtmEventId"]]],["t",[15,"be"]],["u",[15,"be"],[15,"ba"]],["v",[15,"i"],[15,"bd"],[15,"be"]]]],[52,"y",[16,[15,"b"],"useEnableAutoEventOnFormApis"]],[52,"z",[51,"",[7,"ba","bb"],["x",[15,"ba"],[44]],[52,"bc",[8,"form_id",[16,[15,"ba"],"gtm.elementId"],"form_name",[16,[15,"ba"],"gtm.interactedFormName"],"form_destination",[16,[15,"ba"],"gtm.elementUrl"],"form_length",[16,[15,"ba"],"gtm.interactedFormLength"],"form_submit_text",[39,[15,"y"],[16,[15,"ba"],"gtm.formSubmitElementText"],[16,[15,"ba"],"gtm.formSubmitButtonText"]]]],[43,[15,"bc"],"event_callback",[15,"bb"]],[52,"bd",[8,"eventId",[17,[15,"a"],"gtmEventId"]]],["t",[15,"bd"]],["u",[15,"bd"],[15,"ba"]],["v",[15,"h"],[15,"bc"],[15,"bd"]]]],[22,[15,"y"],[46,[53,[52,"ba",["require","internal.addDataLayerEventListener"]],[52,"bb",["require","internal.enableAutoEventOnFormSubmit"]],[52,"bc",["require","internal.enableAutoEventOnFormInteraction"]],[52,"bd",["bc"]],[22,[28,[15,"bd"]],[46,[2,[15,"a"],"gtmOnFailure",[7]],[36]]],["ba","gtm.formInteract",[15,"x"],[15,"bd"]],[52,"be",["bb",[8,"checkValidation",[28,[15,"o"]],"waitForTags",false]]],[22,[28,[15,"be"]],[46,[2,[15,"a"],"gtmOnFailure",[7]],[36]]],["ba","gtm.formSubmit",[15,"z"],[15,"be"]]]],[46,["p",[15,"x"]],["q",[15,"z"],[8,"waitForCallbacks",false,"checkValidation",[28,[15,"o"]]]]]],[2,[15,"a"],"gtmOnSuccess",[7]]] - ,[50,"__ccd_em_outbound_click",[46,"a"],[50,"s",[46,"y"],[22,[28,[15,"y"]],[46,[36,[44]]]],[41,"z"],[3,"z",""],[22,[1,[15,"y"],[17,[15,"y"],"href"]],[46,[53,[41,"ba"],[3,"ba",[2,[17,[15,"y"],"href"],"indexOf",[7,"#"]]],[3,"z",[39,[23,[15,"ba"],0],[17,[15,"y"],"href"],[2,[17,[15,"y"],"href"],"substring",[7,0,[15,"ba"]]]]]]]],[36,[15,"z"]]],[50,"t",[46,"y"],[22,[28,[15,"y"]],[46,[36,[44]]]],[41,"z"],[3,"z",[17,[15,"y"],"hostname"]],[52,"ba",[2,[15,"z"],"match",[7,"^www\\d*\\."]]],[22,[1,[15,"ba"],[16,[15,"ba"],0]],[46,[3,"z",[2,[15,"z"],"substring",[7,[17,[16,[15,"ba"],0],"length"]]]]]],[36,[15,"z"]]],[50,"u",[46,"y"],[22,[28,[15,"y"]],[46,[36,false]]],[52,"z",[2,[17,[15,"y"],"hostname"],"toLowerCase",[7]]],[41,"ba"],[3,"ba",[2,["t",["q",["p"]]],"toLowerCase",[7]]],[41,"bb"],[3,"bb",[37,[17,[15,"z"],"length"],[17,[15,"ba"],"length"]]],[22,[1,[18,[15,"bb"],0],[29,[2,[15,"ba"],"charAt",[7,0]],"."]],[46,[32,[15,"bb"],[3,"bb",[37,[15,"bb"],1]]],[3,"ba",[0,".",[15,"ba"]]]]],[22,[1,[19,[15,"bb"],0],[12,[2,[15,"z"],"indexOf",[7,[15,"ba"],[15,"bb"]]],[15,"bb"]]],[46,[36,false]]],[36,true]],[50,"x",[46,"y"],[52,"z",[8]],[43,[15,"z"],[15,"j"],true],[43,[15,"z"],[15,"f"],true],[43,[15,"y"],"eventMetadata",[15,"z"]]],[52,"b",[13,[41,"$0"],[3,"$0",["require","internal.getFlags"]],["$0"]]],[52,"c",["require","internal.getProductSettingsParameter"]],[52,"d",["require","templateStorage"]],[52,"e",[15,"__module_ccdEmOutboundClickActivity"]],[52,"f","speculative"],[52,"g","ae_block_outbound_click"],[52,"h","click"],[52,"i","isRegistered"],[52,"j","em_event"],[52,"k",[17,[15,"a"],"instanceDestinationId"]],[22,["c",[15,"k"],[15,"g"]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[2,[15,"e"],"registerOutbackClickActivityCallback",[7,[15,"k"],[17,[15,"a"],"includeParams"]]],[22,[2,[15,"d"],"getItem",[7,[15,"i"]]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[52,"l",["require","internal.addDataLayerEventListener"]],[52,"m",["require","internal.enableAutoEventOnLinkClick"]],[52,"n",["require","internal.getDestinationIds"]],[52,"o",["require","internal.getRemoteConfigParameter"]],[52,"p",["require","getUrl"]],[52,"q",["require","parseUrl"]],[52,"r",["require","internal.sendGtagEvent"]],[52,"v",["o",[15,"k"],"cross_domain_conditions"]],[52,"w",["m",[8,"affiliateDomains",[15,"v"],"checkValidation",true,"waitForTags",false]]],[22,[28,[15,"w"]],[46,[2,[15,"a"],"gtmOnFailure",[7]],[36]]],[2,[15,"d"],"setItem",[7,[15,"i"],true]],["l","gtm.linkClick",[51,"",[7,"y","z"],[52,"ba",["q",[16,[15,"y"],"gtm.elementUrl"]]],[22,[28,["u",[15,"ba"]]],[46,["z"],[36]]],[52,"bb",[8,"link_id",[16,[15,"y"],"gtm.elementId"],"link_classes",[16,[15,"y"],"gtm.elementClasses"],"link_url",["s",[15,"ba"]],"link_domain",["t",[15,"ba"]],"outbound",true]],[43,[15,"bb"],"event_callback",[15,"z"]],[52,"bc",[8,"eventId",[16,[15,"y"],"gtm.uniqueEventId"]]],[22,[16,[15,"b"],"enableDeferAllEnhancedMeasurement"],[46,[43,[15,"bc"],"deferrable",true]]],["x",[15,"bc"]],["r",["n"],[15,"h"],[15,"bb"],[15,"bc"]]],[15,"w"]],[2,[15,"a"],"gtmOnSuccess",[7]]] + ,[50,"__ccd_em_outbound_click",[46,"a"],[50,"s",[46,"y"],[22,[28,[15,"y"]],[46,[36,[44]]]],[41,"z"],[3,"z",""],[22,[1,[15,"y"],[17,[15,"y"],"href"]],[46,[53,[41,"ba"],[3,"ba",[2,[17,[15,"y"],"href"],"indexOf",[7,"#"]]],[3,"z",[39,[23,[15,"ba"],0],[17,[15,"y"],"href"],[2,[17,[15,"y"],"href"],"substring",[7,0,[15,"ba"]]]]]]]],[36,[15,"z"]]],[50,"t",[46,"y"],[22,[28,[15,"y"]],[46,[36,[44]]]],[41,"z"],[3,"z",[17,[15,"y"],"hostname"]],[52,"ba",[2,[15,"z"],"match",[7,"^www\\d*\\."]]],[22,[1,[15,"ba"],[16,[15,"ba"],0]],[46,[3,"z",[2,[15,"z"],"substring",[7,[17,[16,[15,"ba"],0],"length"]]]]]],[36,[15,"z"]]],[50,"u",[46,"y"],[22,[28,[15,"y"]],[46,[36,false]]],[52,"z",[2,[17,[15,"y"],"hostname"],"toLowerCase",[7]]],[22,[1,[17,[15,"b"],"enableGa4OutboundClicksFix"],[28,[15,"z"]]],[46,[36,false]]],[41,"ba"],[3,"ba",[2,["t",["q",["p"]]],"toLowerCase",[7]]],[41,"bb"],[3,"bb",[37,[17,[15,"z"],"length"],[17,[15,"ba"],"length"]]],[22,[1,[18,[15,"bb"],0],[29,[2,[15,"ba"],"charAt",[7,0]],"."]],[46,[32,[15,"bb"],[3,"bb",[37,[15,"bb"],1]]],[3,"ba",[0,".",[15,"ba"]]]]],[22,[1,[19,[15,"bb"],0],[12,[2,[15,"z"],"indexOf",[7,[15,"ba"],[15,"bb"]]],[15,"bb"]]],[46,[36,false]]],[36,true]],[50,"x",[46,"y"],[52,"z",[8]],[43,[15,"z"],[15,"j"],true],[43,[15,"z"],[15,"f"],true],[43,[15,"y"],"eventMetadata",[15,"z"]]],[52,"b",[13,[41,"$0"],[3,"$0",["require","internal.getFlags"]],["$0"]]],[52,"c",["require","internal.getProductSettingsParameter"]],[52,"d",["require","templateStorage"]],[52,"e",[15,"__module_ccdEmOutboundClickActivity"]],[52,"f","speculative"],[52,"g","ae_block_outbound_click"],[52,"h","click"],[52,"i","isRegistered"],[52,"j","em_event"],[52,"k",[17,[15,"a"],"instanceDestinationId"]],[22,["c",[15,"k"],[15,"g"]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[2,[15,"e"],"registerOutbackClickActivityCallback",[7,[15,"k"],[17,[15,"a"],"includeParams"]]],[22,[2,[15,"d"],"getItem",[7,[15,"i"]]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[52,"l",["require","internal.addDataLayerEventListener"]],[52,"m",["require","internal.enableAutoEventOnLinkClick"]],[52,"n",["require","internal.getDestinationIds"]],[52,"o",["require","internal.getRemoteConfigParameter"]],[52,"p",["require","getUrl"]],[52,"q",["require","parseUrl"]],[52,"r",["require","internal.sendGtagEvent"]],[52,"v",["o",[15,"k"],"cross_domain_conditions"]],[52,"w",["m",[8,"affiliateDomains",[15,"v"],"checkValidation",true,"waitForTags",false]]],[22,[28,[15,"w"]],[46,[2,[15,"a"],"gtmOnFailure",[7]],[36]]],[2,[15,"d"],"setItem",[7,[15,"i"],true]],["l","gtm.linkClick",[51,"",[7,"y","z"],[52,"ba",["q",[16,[15,"y"],"gtm.elementUrl"]]],[22,[28,["u",[15,"ba"]]],[46,["z"],[36]]],[52,"bb",[8,"link_id",[16,[15,"y"],"gtm.elementId"],"link_classes",[16,[15,"y"],"gtm.elementClasses"],"link_url",["s",[15,"ba"]],"link_domain",["t",[15,"ba"]],"outbound",true]],[43,[15,"bb"],"event_callback",[15,"z"]],[52,"bc",[8,"eventId",[16,[15,"y"],"gtm.uniqueEventId"]]],[22,[16,[15,"b"],"enableDeferAllEnhancedMeasurement"],[46,[43,[15,"bc"],"deferrable",true]]],["x",[15,"bc"]],["r",["n"],[15,"h"],[15,"bb"],[15,"bc"]]],[15,"w"]],[2,[15,"a"],"gtmOnSuccess",[7]]] ,[50,"__ccd_em_page_view",[46,"a"],[50,"s",[46,"t"],[52,"u",[8]],[43,[15,"u"],[15,"k"],true],[43,[15,"u"],[15,"g"],true],[43,[15,"t"],"eventMetadata",[15,"u"]]],[22,[28,[17,[15,"a"],"historyEvents"]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[52,"b",[13,[41,"$0"],[3,"$0",["require","internal.getFlags"]],["$0"]]],[52,"c",["require","internal.getProductSettingsParameter"]],[52,"d",["require","internal.setRemoteConfigParameter"]],[52,"e",["require","templateStorage"]],[52,"f",[15,"__module_ccdEmPageViewActivity"]],[52,"g","speculative"],[52,"h","ae_block_history"],[52,"i","page_view"],[52,"j","isRegistered"],[52,"k","em_event"],[52,"l",[17,[15,"a"],"instanceDestinationId"]],[22,["c",[15,"l"],[15,"h"]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[2,[15,"f"],"registerPageViewActivityCallback",[7,[15,"l"]]],[22,[2,[15,"e"],"getItem",[7,[15,"j"]]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[52,"m",["require","internal.addDataLayerEventListener"]],[52,"n",["require","internal.enableAutoEventOnHistoryChange"]],[52,"o",["require","internal.getDestinationIds"]],[52,"p",["require","internal.sendGtagEvent"]],[52,"q",[8,"interval",1000,"useV2EventName",true]],[52,"r",["n",[15,"q"]]],[22,[28,[15,"r"]],[46,[2,[15,"a"],"gtmOnFailure",[7]],[36]]],[2,[15,"e"],"setItem",[7,[15,"j"],true]],["m","gtm.historyChange-v2",[51,"",[7,"t","u"],["u"],[52,"v",[16,[15,"t"],"gtm.oldUrl"]],[22,[20,[16,[15,"t"],"gtm.newUrl"],[15,"v"]],[46,[36]]],[52,"w",[16,[15,"t"],"gtm.historyChangeSource"]],[22,[1,[1,[21,[15,"w"],"pushState"],[21,[15,"w"],"popstate"]],[21,[15,"w"],"replaceState"]],[46,[36]]],[52,"x",[8]],[22,[17,[15,"a"],"includeParams"],[46,[43,[15,"x"],"page_location",[16,[15,"t"],"gtm.newUrl"]],[43,[15,"x"],"page_referrer",[15,"v"]]]],[52,"y",[8,"eventId",[16,[15,"t"],"gtm.uniqueEventId"]]],[22,[16,[15,"b"],"enableDeferAllEnhancedMeasurement"],[46,[43,[15,"y"],"deferrable",true]]],["s",[15,"y"]],["p",["o"],[15,"i"],[15,"x"],[15,"y"]]],[15,"r"]],[2,[15,"a"],"gtmOnSuccess",[7]]] ,[50,"__ccd_em_scroll",[46,"a"],[50,"q",[46,"r"],[52,"s",[8]],[43,[15,"s"],[15,"j"],true],[43,[15,"s"],[15,"f"],true],[43,[15,"r"],"eventMetadata",[15,"s"]]],[52,"b",[13,[41,"$0"],[3,"$0",["require","internal.getFlags"]],["$0"]]],[52,"c",["require","internal.getProductSettingsParameter"]],[52,"d",["require","templateStorage"]],[52,"e",[15,"__module_ccdEmScrollActivity"]],[52,"f","speculative"],[52,"g","ae_block_scroll"],[52,"h","scroll"],[52,"i","isRegistered"],[52,"j","em_event"],[52,"k",[17,[15,"a"],"instanceDestinationId"]],[22,["c",[15,"k"],[15,"g"]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[2,[15,"e"],"registerScrollActivityCallback",[7,[15,"k"],[17,[15,"a"],"includeParams"]]],[22,[2,[15,"d"],"getItem",[7,[15,"i"]]],[46,[2,[15,"a"],"gtmOnSuccess",[7]],[36]]],[52,"l",["require","internal.addDataLayerEventListener"]],[52,"m",["require","internal.enableAutoEventOnScroll"]],[52,"n",["require","internal.getDestinationIds"]],[52,"o",["require","internal.sendGtagEvent"]],[52,"p",["m",[8,"verticalThresholdUnits","PERCENT","verticalThresholds",90]]],[22,[28,[15,"p"]],[46,[2,[15,"a"],"gtmOnFailure",[7]],[36]]],[2,[15,"d"],"setItem",[7,[15,"i"],true]],["l","gtm.scrollDepth",[51,"",[7,"r","s"],["s"],[52,"t",[8,"eventId",[16,[15,"r"],"gtm.uniqueEventId"]]],[22,[16,[15,"b"],"enableDeferAllEnhancedMeasurement"],[46,[43,[15,"t"],"deferrable",true]]],[52,"u",[8,"percent_scrolled",[16,[15,"r"],"gtm.scrollThreshold"]]],["q",[15,"t"]],["o",["n"],[15,"h"],[15,"u"],[15,"t"]]],[15,"p"]],[2,[15,"a"],"gtmOnSuccess",[7]]] ,[50,"__ccd_em_site_search",[46,"a"],[52,"b",["require","getQueryParameters"]],[52,"c",["require","internal.sendGtagEvent"]],[52,"d",["require","getContainerVersion"]],[52,"e",[15,"__module_ccdEmSiteSearchActivity"]],[52,"f",[2,[15,"e"],"getSearchTerm",[7,[17,[15,"a"],"searchQueryParams"],[15,"b"]]]],[52,"g",[30,[17,[15,"a"],"instanceDestinationId"],[17,["d"],"containerId"]]],[52,"h",[8,"deferrable",true,"eventId",[17,[15,"a"],"gtmEventId"],"eventMetadata",[8,"em_event",true]]],[22,[15,"f"],[46,[53,[52,"i",[39,[28,[28,[17,[15,"a"],"includeParams"]]],[2,[15,"e"],"buildEventParams",[7,[15,"f"],[17,[15,"a"],"additionalQueryParams"],[15,"b"]]],[8]]],["c",[15,"g"],"view_search_results",[15,"i"],[15,"h"]]]]],[2,[15,"a"],"gtmOnSuccess",[7]]] @@ -4657,582 +4657,584 @@ -var aa,ba=function(a){var b=0;return function(){return b>>0)+"_",d=0,e=function(f){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new b(c+(f||"")+"_"+d++,f)};return e}); -var ma=function(a){return ka(a,a)},ka=function(a,b){a.raw=b;Object.freeze&&(Object.freeze(a),Object.freeze(b));return a},h=function(a){var b=typeof Symbol!="undefined"&&Symbol.iterator&&a[Symbol.iterator];if(b)return b.call(a);if(typeof a.length=="number")return{next:ba(a)};throw Error(String(a)+" is not an iterable or ArrayLike");},na=function(a){for(var b,c=[];!(b=a.next()).done;)c.push(b.value);return c},oa=function(a){return a instanceof Array?a:na(h(a))},pa=typeof Object.assign=="function"?Object.assign: -function(a,b){for(var c=1;c>>0)+"_",d=0,e=function(f){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new b(c+(f||"")+"_"+d++,f)};return e});var ka=typeof Object.create=="function"?Object.create:function(a){var b=function(){};b.prototype=a;return new b},ma; +if(typeof Object.setPrototypeOf=="function")ma=Object.setPrototypeOf;else{var na;a:{var oa={a:!0},pa={};try{pa.__proto__=oa;na=pa.a;break a}catch(a){}na=!1}ma=na?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null} +var qa=ma,ra=function(a,b){a.prototype=ka(b.prototype);a.prototype.constructor=a;if(qa)qa(a,b);else for(var c in b)if(c!="prototype")if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.oo=b.prototype},l=function(a){var b=typeof Symbol!="undefined"&&Symbol.iterator&&a[Symbol.iterator];if(b)return b.call(a);if(typeof a.length=="number")return{next:ba(a)};throw Error(String(a)+" is not an iterable or ArrayLike");},ta=function(a){for(var b, +c=[];!(b=a.next()).done;)c.push(b.value);return c},ua=function(a){return a instanceof Array?a:ta(l(a))},wa=function(a){return va(a,a)},va=function(a,b){a.raw=b;Object.freeze&&(Object.freeze(a),Object.freeze(b));return a},xa=typeof Object.assign=="function"?Object.assign:function(a,b){for(var c=1;c=0&&isFinite(a)&&a%1===0||typeof a==="string"&&a[0]!=="-"&&a===""+parseInt(a)};var Va=function(a){a=a===void 0?[]:a;La.call(this);this.values=[];for(var b in a)a.hasOwnProperty(b)&&(Ua(b)?this.values[Number(b)]=a[Number(b)]:La.prototype.set.call(this,b,a[b]))};wa(Va,La);aa=Va.prototype;aa.toString=function(a){if(a&&a.indexOf(this)>=0)return"";for(var b=[],c=0;c>2,n=(f&3)<<4|g>>4,p=(g&15)<<2|k>>6,q=k&63;e||(q=64,d||(p=64));b.push(Za[m],Za[n],Za[p],Za[q])}return b.join("")} -function cb(a){function b(m){for(;d>4);g!==64&&(c+=String.fromCharCode(f<<4&240|g>>2),k!==64&&(c+=String.fromCharCode(g<<6&192|k)))}};var db={};function fb(a,b){db[a]=db[a]||[];db[a][b]=!0}function gb(a){var b=db[a];if(!b||b.length===0)return"";for(var c=[],d=0,e=0;e0&&(c.push(String.fromCharCode(d)),d=0),b[e]&&(d|=1<0&&c.push(String.fromCharCode(d));return bb(c.join("")).replace(/\.+$/,"")}function hb(){for(var a=[],b=db.fdr||[],c=0;c0?a:void 0};var ib=[],jb={};function kb(a){return ib[a]===void 0?!1:ib[a]};function lb(){}function mb(a){return typeof a==="function"}function l(a){return typeof a==="string"}function nb(a){return typeof a==="number"&&!isNaN(a)}function ob(a){return Array.isArray(a)?a:[a]}function pb(a,b){if(a&&Array.isArray(a))for(var c=0;cb)a=0,b=2147483647;return Math.floor(Math.random()*(b-a+1)+a)} -function rb(a,b){for(var c=new sb,d=0;d=b.length&&a.substring(0,b.length)===b}function Fb(a,b){return a.length>=b.length&&a.substring(a.length-b.length,a.length)===b} -function Gb(a,b){var c=C;b=b||[];for(var d=c,e=0;e=0)return}return d}function Hb(a,b){for(var c={},d=c,e=a.split("."),f=0;f>2,n=(f&3)<<4|g>>4,p=(g&15)<<2|k>>6,q=k&63;e||(q=64,d||(p=64));b.push(Oa[m],Oa[n],Oa[p],Oa[q])}return b.join("")} +function Ta(a){function b(m){for(;d>4);g!==64&&(c+=String.fromCharCode(f<<4&240|g>>2),k!==64&&(c+=String.fromCharCode(g<<6&192|k)))}};var Ua={};function Va(a,b){Ua[a]=Ua[a]||[];Ua[a][b]=!0}function Wa(a){var b=Ua[a];if(!b||b.length===0)return"";for(var c=[],d=0,e=0;e0&&(c.push(String.fromCharCode(d)),d=0),b[e]&&(d|=1<0&&c.push(String.fromCharCode(d));return Ra(c.join("")).replace(/\.+$/,"")}function Xa(){for(var a=[],b=Ua.fdr||[],c=0;c0?a:void 0};var Ya=[],Za={};function $a(a){return Ya[a]===void 0?!1:Ya[a]};function ab(){}function bb(a){return typeof a==="function"}function z(a){return typeof a==="string"}function cb(a){return typeof a==="number"&&!isNaN(a)}function db(a){return Array.isArray(a)?a:[a]}function eb(a,b){if(a&&Array.isArray(a))for(var c=0;cb)a=0,b=2147483647;return Math.floor(Math.random()*(b-a+1)+a)} +function gb(a,b){for(var c=new hb,d=0;d=b.length&&a.substring(0,b.length)===b}function wb(a,b){return a.length>=b.length&&a.substring(a.length-b.length,a.length)===b} +function xb(a,b){var c=B;b=b||[];for(var d=c,e=0;e=0)return}return d}function yb(a,b){for(var c={},d=c,e=a.split("."),f=0;f"+a+""),f=Pb();d=new ic(f?f.createHTML(e):e);if(c.nodeType===1&&/^(script|style)$/i.test(c.tagName))throw Error("");var g;if(d instanceof ic)g=d.j;else throw Error("");c.innerHTML=g;b=b.lastChild;for(var k=[];b&&b.firstChild;)k.push(b.removeChild(b.firstChild));return k} -function Hc(a,b,c){c=c||100;for(var d={},e=0;e-1}function Uc(a,b){var c=String(this.evaluate(a)),d=String(this.evaluate(b));return c.substring(0,d.length)===d} -function Vc(a,b){a=this.evaluate(a);b=this.evaluate(b);switch(a){case "pageLocation":var c=C.location.href;b instanceof Xa&&b.get("stripProtocol")&&(c=c.replace(/^https?:\/\//,""));return c}};var Wc=function(a,b){La.call(this);this.dk=a;this.Ch=b};wa(Wc,La);Wc.prototype.toString=function(){return this.dk};Wc.prototype.getName=function(){return this.dk};Wc.prototype.invoke=function(a){return this.Ch.apply(new Xc(this,a),Array.prototype.slice.call(arguments,1))};Wc.prototype.lb=function(a){try{return this.invoke.apply(this,Array.prototype.slice.call(arguments,0))}catch(b){}};var Xc=function(a,b){this.Ch=a;this.D=b}; -Xc.prototype.evaluate=function(a){var b=this.D;return Array.isArray(a)?Ja(b,a):a};Xc.prototype.getName=function(){return this.Ch.getName()};Xc.prototype.xd=function(){return this.D.xd()};var Yc=function(){this.map=new Map};Yc.prototype.set=function(a,b){this.map.set(a,b)};Yc.prototype.get=function(a){return this.map.get(a)};var Zc=function(){this.keys=[];this.values=[]};Zc.prototype.set=function(a,b){this.keys.push(a);this.values.push(b)};Zc.prototype.get=function(a){var b=this.keys.indexOf(a);if(b>-1)return this.values[b]};function $c(){try{return Map?new Yc:new Zc}catch(a){return new Zc}};var ad=function(a){if(a instanceof ad)return a;if(Ta(a))throw Error("Type of given value has an equivalent Pixie type.");this.value=a};ad.prototype.getValue=function(){return this.value};ad.prototype.toString=function(){return String(this.value)};var cd=function(a){La.call(this);this.promise=a;this.set("then",bd(this));this.set("catch",bd(this,!0));this.set("finally",bd(this,!1,!0))};wa(cd,Xa);var bd=function(a,b,c){b=b===void 0?!1:b;c=c===void 0?!1:c;return new Wc("",function(d,e){b&&(e=d,d=void 0);c&&(e=d);d instanceof Wc||(d=void 0);e instanceof Wc||(e=void 0);var f=Ha(this.D),g=function(m){return function(n){return c?(m.invoke(f),a.promise):m.invoke(f,n)}},k=a.promise.then(d&&g(d),e&&g(e));return new cd(k)})};function G(a,b,c){var d=$c(),e=function(g,k){for(var m=g.La(),n=0;n=0;f--)if(this.has(f)&&this.get(f)===b)return f;return-1},map:function(a,b){for(var c=this.length(),d=[],e=0;ed)throw Error("TypeError: ReduceRight on List with no elements.");}for(var k=f;k>=0;k--)this.has(k)&&(e=b.invoke(a,e,this.get(k),k,this));return e},reverse:function(){for(var a=Wa(this),b=a.length-1,c=0;b>=0;b--,c++)a.hasOwnProperty(b)?this.set(c,a[b]):this.remove(c);return this},shift:function(){return this.shift()},slice:function(a,b,c){var d=this.length();b===void 0&&(b=0);b=b<0?Math.max(d+b,0):Math.min(b,d);c=c===void 0? -d:c<0?Math.max(d+c,0):Math.min(c,d);c=Math.max(b,c);for(var e=[],f=b;f=0){var t=Wa(c);t.unshift(this.D);return fd[b].apply(a,t)}}if(a instanceof Wc||a instanceof Xa){if(a.has(b)){var v=a.get(b);if(v instanceof Wc){var u=Wa(c);u.unshift(this.D);return v.invoke.apply(v,u)}var w="TypeError: "+b+" is not a function";if(ed())throw new gd(w);throw Error(w);}if(b==="toString")return a instanceof Wc?a.getName():a.toString();if(b==="hasOwnProperty")return a.has.apply(a, -Wa(c))}if(a instanceof ad&&b==="toString")return a.toString();var x="TypeError: Object has no '"+b+"' property.";if(ed())throw new gd(x);throw Error(x);}function nd(a,b){a=this.evaluate(a);if(typeof a!=="string")throw Error("Invalid key name given for assignment.");var c=this.D;if(!c.has(a))throw Error("Attempting to assign to undefined value "+b);var d=this.evaluate(b);c.set(a,d);return d}function od(){var a=Ha(this.D),b=Ia(a,Array.prototype.slice.apply(arguments));if(b instanceof za)return b} -function pd(){return id}function qd(a){for(var b=this.evaluate(a),c=0;cthis.evaluate(b)}function Nd(a,b){return this.evaluate(a)>=this.evaluate(b)} -function Od(a,b){a=this.evaluate(a);b=this.evaluate(b);a instanceof ad&&(a=a.getValue());b instanceof ad&&(b=b.getValue());return a===b}function Pd(a,b){return!Od.call(this,a,b)}function Qd(a,b,c){var d=[];this.evaluate(a)?d=this.evaluate(b):c&&(d=this.evaluate(c));var e=Ia(this.D,d);if(e instanceof za)return e}var Kd=!1; -function Rd(a,b){return this.evaluate(a)>Number(this.evaluate(b))} -function qe(a,b){return Number(this.evaluate(a))>>>Number(this.evaluate(b))}function re(a,b){return Number(this.evaluate(a))&Number(this.evaluate(b))}function se(a,b){return Number(this.evaluate(a))^Number(this.evaluate(b))}function te(a,b){return Number(this.evaluate(a))|Number(this.evaluate(b))}function ue(){} -function ve(a,b,c,d,e){var f=!0;try{var g=this.evaluate(c);if(g instanceof za)return g}catch(r){if(!(r instanceof gd&&a))throw f=r instanceof gd,r;var k=Ha(this.D),m=new ad(r);k.add(b,m);var n=this.evaluate(d),p=Ia(k,n);if(p instanceof za)return p}finally{if(f&&e!==void 0){var q=this.evaluate(e);if(q instanceof za)return q}}};var xe=function(){this.j=new Ka;we(this)};xe.prototype.execute=function(a){return this.j.hi(a)};var we=function(a){var b=function(c,d){var e=new Wc(String(c),d);e.Na();a.j.j.set(String(c),e)};b("map",Ud);b("and",Qc);b("contains",Tc);b("equals",Rc);b("or",Sc);b("startsWith",Uc);b("variable",Vc)};var ze=function(){this.C=!1;this.j=new Ka;ye(this);this.C=!0};ze.prototype.execute=function(a){return Ae(this.j.hi(a))};var Be=function(a,b,c){return Ae(a.j.Zk(b,c))};ze.prototype.Na=function(){this.j.Na()}; -var ye=function(a){var b=function(c,d){var e=String(c),f=new Wc(e,d);f.Na();a.j.j.set(e,f)};b(0,kd);b(1,ld);b(2,md);b(3,nd);b(56,re);b(57,oe);b(58,ne);b(59,te);b(60,pe);b(61,qe);b(62,se);b(53,od);b(4,pd);b(5,qd);b(52,rd);b(6,sd);b(49,td);b(7,Td);b(8,Ud);b(9,qd);b(50,ud);b(10,vd);b(12,wd);b(13,xd);b(51,Id);b(47,Ad);b(54,Bd);b(55,Cd);b(63,Hd);b(64,Dd);b(65,Fd);b(66,Gd);b(15,Jd);b(16,Ld);b(17,Ld);b(18,Md);b(19,Nd);b(20,Od);b(21,Pd);b(22,Qd);b(23,Rd);b(24,Sd);b(25,Vd);b(26,Wd);b(27,Xd);b(28,Yd);b(29, -Zd);b(45,$d);b(30,ae);b(32,be);b(33,be);b(34,ce);b(35,ce);b(46,de);b(36,ee);b(43,ge);b(37,he);b(38,ie);b(39,je);b(67,ve);b(40,ke);b(44,ue);b(41,le);b(42,me)};ze.prototype.xd=function(){return this.j.xd()};function Ae(a){if(a instanceof za||a instanceof Wc||a instanceof Va||a instanceof Xa||a instanceof ad||a===null||a===void 0||typeof a==="string"||typeof a==="number"||typeof a==="boolean")return a};var Ce=function(a){this.message=a};function De(a){var b="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[a];return b===void 0?new Ce("Value "+a+" can not be encoded in web-safe base64 dictionary."):b};function Ee(a){switch(a){case 1:return"1";case 2:case 4:return"0";default:return"-"}};var Fe=/^[1-9a-zA-Z_-][1-9a-c][1-9a-v]\d$/;function Ge(a,b){for(var c="",d=!0;a>7;){var e=a&31;a>>=5;d?d=!1:e|=32;c=""+De(e)+c}a<<=2;d||(a|=32);return c=""+De(a|b)+c};var He=function(){function a(b){return{toString:function(){return b}}}return{Ck:a("consent"),ui:a("convert_case_to"),vi:a("convert_false_to"),wi:a("convert_null_to"),xi:a("convert_true_to"),yi:a("convert_undefined_to"),xn:a("debug_mode_metadata"),la:a("function"),ih:a("instance_name"),il:a("live_only"),jl:a("malware_disabled"),METADATA:a("metadata"),nl:a("original_activity_id"),Hn:a("original_vendor_template_id"),Gn:a("once_on_load"),ml:a("once_per_event"),Aj:a("once_per_load"),Jn:a("priority_override"), -Kn:a("respected_consent_types"),Ij:a("setup_tags"),xe:a("tag_id"),Nj:a("teardown_tags")}}();var ef;var ff=[],gf=[],hf=[],jf=[],kf=[],lf={},mf,nf;function of(a){nf=nf||a} -function pf(a){}var qf,rf=[],sf=[];function tf(a,b){var c={};c[He.la]="__"+a;for(var d in b)b.hasOwnProperty(d)&&(c["vtp_"+d]=b[d]);return c} -function uf(a,b,c){try{return mf(vf(a,b,c))}catch(d){JSON.stringify(a)}return 2}function wf(a){var b=a[He.la];if(!b)throw Error("Error: No function name given for function call.");return!!lf[b]} -var vf=function(a,b,c){c=c||[];var d={},e;for(e in a)a.hasOwnProperty(e)&&(d[e]=xf(a[e],b,c));return d},xf=function(a,b,c){if(Array.isArray(a)){var d;switch(a[0]){case "function_id":return a[1];case "list":d=[];for(var e=1;e0;b--)nb(a[b].id)&&a.splice(b++,1);for(var c=a.length-1;c>0;c--)a[c].line=a[c-1].line;a.splice(0,1);return a};function Ef(a){function b(r){for(var t=0;t"+a+""),f=Hb();d=new ac(f?f.createHTML(e):e);if(c.nodeType===1&&/^(script|style)$/i.test(c.tagName))throw Error("");var g;if(d instanceof ac)g=d.j;else throw Error("");c.innerHTML=g;b=b.lastChild;for(var k=[];b&&b.firstChild;)k.push(b.removeChild(b.firstChild));return k} +function Ac(a,b,c){c=c||100;for(var d={},e=0;e0&&(a=c[0].type)}catch(d){return"e"}if(!a)return"u";switch(a){case "navigate":return"n";case "back_forward":return"h";case "reload":return"r";case "prerender":return"p";default:return"x"}}function Jc(){return B.performance||void 0}function Kc(){var a=B.webPixelsManager;return a?a.createShopifyExtend!==void 0:!1} +var uc=function(a,b,c,d){var e=new Image(1,1);pc(e,d,{});e.onload=function(){e.onload=null;b&&b()};e.onerror=function(){e.onerror=null;c&&c()};e.src=a;return e};function Lc(a,b){return this.evaluate(a)&&this.evaluate(b)}function Mc(a,b){return this.evaluate(a)===this.evaluate(b)}function Nc(a,b){return this.evaluate(a)||this.evaluate(b)}function Oc(a,b){a=this.evaluate(a);b=this.evaluate(b);return String(a).indexOf(String(b))>-1}function Pc(a,b){var c=String(this.evaluate(a)),d=String(this.evaluate(b));return c.substring(0,d.length)===d} +function Qc(a,b){a=this.evaluate(a);b=this.evaluate(b);switch(a){case "pageLocation":var c=B.location.href;b instanceof La&&b.get("stripProtocol")&&(c=c.replace(/^https?:\/\//,""));return c}};/* + jQuery (c) 2005, 2012 jQuery Foundation, Inc. jquery.org/license. +*/ +var Rc=/\[object (Boolean|Number|String|Function|Array|Date|RegExp)\]/,Sc=function(a){if(a==null)return String(a);var b=Rc.exec(Object.prototype.toString.call(Object(a)));return b?b[1].toLowerCase():"object"},Tc=function(a,b){return Object.prototype.hasOwnProperty.call(Object(a),b)},Uc=function(a){if(!a||Sc(a)!="object"||a.nodeType||a==a.window)return!1;try{if(a.constructor&&!Tc(a,"constructor")&&!Tc(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}for(var b in a);return b===void 0|| +Tc(a,b)},Vc=function(a,b){var c=b||(Sc(a)=="array"?[]:{}),d;for(d in a)if(Tc(a,d)){var e=a[d];Sc(e)=="array"?(Sc(c[d])!="array"&&(c[d]=[]),c[d]=Vc(e,c[d])):Uc(e)?(Uc(c[d])||(c[d]={}),c[d]=Vc(e,c[d])):c[d]=e}return c};function Wc(a){if(a==void 0||Array.isArray(a)||Uc(a))return!0;switch(typeof a){case "boolean":case "number":case "string":case "function":return!0}return!1}function Xc(a){return typeof a==="number"&&a>=0&&isFinite(a)&&a%1===0||typeof a==="string"&&a[0]!=="-"&&a===""+parseInt(a)};var Yc=function(a){a=a===void 0?[]:a;this.R=new Ca;this.values=[];this.la=!1;for(var b in a)a.hasOwnProperty(b)&&(Xc(b)?this.values[Number(b)]=a[Number(b)]:this.R.set(b,a[b]))};h=Yc.prototype;h.toString=function(a){if(a&&a.indexOf(this)>=0)return"";for(var b=[],c=0;c-1)return this.values[b]};function dd(){try{return Map?new bd:new cd}catch(a){return new cd}};var ed=function(a){if(a instanceof ed)return a;if(Wc(a))throw Error("Type of given value has an equivalent Pixie type.");this.value=a};ed.prototype.getValue=function(){return this.value};ed.prototype.toString=function(){return String(this.value)};var gd=function(a){this.promise=a;this.la=!1;this.R=new Ca;this.R.set("then",fd(this));this.R.set("catch",fd(this,!0));this.R.set("finally",fd(this,!1,!0))};h=gd.prototype;h.get=function(a){return this.R.get(a)};h.set=function(a,b){this.la||this.R.set(a,b)};h.has=function(a){return this.R.has(a)};h.remove=function(a){this.la||this.R.remove(a)};h.ka=function(){return this.R.ka()};h.Vb=function(){return this.R.Vb()};h.Cb=function(){return this.R.Cb()}; +var fd=function(a,b,c){b=b===void 0?!1:b;c=c===void 0?!1:c;return new $c("",function(d,e){b&&(e=d,d=void 0);c&&(e=d);d instanceof $c||(d=void 0);e instanceof $c||(e=void 0);var f=Ha(this.D),g=function(m){return function(n){return c?(m.invoke(f),a.promise):m.invoke(f,n)}},k=a.promise.then(d&&g(d),e&&g(e));return new gd(k)})};gd.prototype.Ia=function(){this.la=!0};gd.prototype.sc=function(){return this.la};function G(a,b,c){var d=dd(),e=function(g,k){for(var m=g.ka(),n=0;n=0;f--)if(this.has(f)&&this.get(f)===b)return f;return-1},map:function(a,b){for(var c=this.length(),d=[],e=0;ed)throw Error("TypeError: ReduceRight on List with no elements.");}for(var k=f;k>=0;k--)this.has(k)&&(e=b.invoke(a,e,this.get(k),k,this));return e},reverse:function(){for(var a=Zc(this),b=a.length-1,c=0;b>=0;b--,c++)a.hasOwnProperty(b)?this.set(c,a[b]):this.remove(c);return this},shift:function(){return this.shift()},slice:function(a,b,c){var d=this.length();b===void 0&&(b=0);b=b<0?Math.max(d+b,0):Math.min(b,d);c=c===void 0? +d:c<0?Math.max(d+c,0):Math.min(c,d);c=Math.max(b,c);for(var e=[],f=b;f=0){var u=Zc(c);return jd[b].call.apply(jd[b],[a,this.D].concat(ua(u)))}}if(a instanceof $c||a instanceof La||a instanceof gd){if(a.has(b)){var v=a.get(b);if(v instanceof $c){var t=Zc(c);return v.invoke.apply(v,[this.D].concat(ua(t)))}var w="TypeError: "+b+" is not a function";if(id())throw new kd(w);throw Error(w);}if(b==="toString")return a instanceof $c?a.getName():a.toString();if(b=== +"hasOwnProperty")return a.has(c.get(0))}if(a instanceof ed&&b==="toString")return a.toString();var x="TypeError: Object has no '"+b+"' property.";if(id())throw new kd(x);throw Error(x);}function rd(a,b){a=this.evaluate(a);if(typeof a!=="string")throw Error("Invalid key name given for assignment.");var c=this.D;if(!c.has(a))throw Error("Attempting to assign to undefined value "+b);var d=this.evaluate(b);c.set(a,d);return d} +function sd(){var a=ya.apply(0,arguments),b=Ha(this.D),c=Ia(b,a);if(c instanceof Ba)return c}function td(){return md}function ud(a){for(var b=this.evaluate(a),c=0;cthis.evaluate(b)} +function Rd(a,b){return this.evaluate(a)>=this.evaluate(b)}function Sd(a,b){a=this.evaluate(a);b=this.evaluate(b);a instanceof ed&&(a=a.getValue());b instanceof ed&&(b=b.getValue());return a===b}function Td(a,b){return!Sd.call(this,a,b)}function Ud(a,b,c){var d=[];this.evaluate(a)?d=this.evaluate(b):c&&(d=this.evaluate(c));var e=Ia(this.D,d);if(e instanceof Ba)return e}var Od=!1; +function Vd(a,b){return this.evaluate(a)>Number(this.evaluate(b))} +function ue(a,b){return Number(this.evaluate(a))>>>Number(this.evaluate(b))}function ve(a,b){return Number(this.evaluate(a))&Number(this.evaluate(b))}function we(a,b){return Number(this.evaluate(a))^Number(this.evaluate(b))}function xe(a,b){return Number(this.evaluate(a))|Number(this.evaluate(b))}function ye(){} +function ze(a,b,c,d,e){var f=!0;try{var g=this.evaluate(c);if(g instanceof Ba)return g}catch(r){if(!(r instanceof kd&&a))throw f=r instanceof kd,r;var k=Ha(this.D),m=new ed(r);k.add(b,m);var n=this.evaluate(d),p=Ia(k,n);if(p instanceof Ba)return p}finally{if(f&&e!==void 0){var q=this.evaluate(e);if(q instanceof Ba)return q}}};var Be=function(){this.j=new Ka;Ae(this)};Be.prototype.execute=function(a){return this.j.ni(a)};var Ae=function(a){var b=function(c,d){var e=new $c(String(c),d);e.Ia();a.j.j.set(String(c),e)};b("map",Yd);b("and",Lc);b("contains",Oc);b("equals",Mc);b("or",Nc);b("startsWith",Pc);b("variable",Qc)};var De=function(){this.C=!1;this.j=new Ka;Ce(this);this.C=!0};De.prototype.execute=function(a){return Ee(this.j.ni(a))};var Fe=function(a,b,c){return Ee(a.j.rl(b,c))};De.prototype.Ia=function(){this.j.Ia()}; +var Ce=function(a){var b=function(c,d){var e=String(c),f=new $c(e,d);f.Ia();a.j.j.set(e,f)};b(0,od);b(1,pd);b(2,qd);b(3,rd);b(56,ve);b(57,se);b(58,re);b(59,xe);b(60,te);b(61,ue);b(62,we);b(53,sd);b(4,td);b(5,ud);b(52,vd);b(6,wd);b(49,xd);b(7,Xd);b(8,Yd);b(9,ud);b(50,yd);b(10,zd);b(12,Ad);b(13,Bd);b(51,Md);b(47,Ed);b(54,Fd);b(55,Gd);b(63,Ld);b(64,Hd);b(65,Jd);b(66,Kd);b(15,Nd);b(16,Pd);b(17,Pd);b(18,Qd);b(19,Rd);b(20,Sd);b(21,Td);b(22,Ud);b(23,Vd);b(24,Wd);b(25,Zd);b(26,$d);b(27,ae);b(28,be);b(29, +ce);b(45,de);b(30,ee);b(32,fe);b(33,fe);b(34,he);b(35,he);b(46,ie);b(36,je);b(43,ke);b(37,le);b(38,me);b(39,ne);b(67,ze);b(40,oe);b(44,ye);b(41,pe);b(42,qe)};De.prototype.Fd=function(){return this.j.Fd()};function Ee(a){if(a instanceof Ba||a instanceof $c||a instanceof Yc||a instanceof La||a instanceof gd||a instanceof ed||a===null||a===void 0||typeof a==="string"||typeof a==="number"||typeof a==="boolean")return a};var Ge=function(a){this.message=a};function He(a){var b="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[a];return b===void 0?new Ge("Value "+a+" can not be encoded in web-safe base64 dictionary."):b};function Ie(a){switch(a){case 1:return"1";case 2:case 4:return"0";default:return"-"}};var Je=/^[1-9a-zA-Z_-][1-9a-c][1-9a-v]\d$/;function Ke(a,b){for(var c="",d=!0;a>7;){var e=a&31;a>>=5;d?d=!1:e|=32;c=""+He(e)+c}a<<=2;d||(a|=32);return c=""+He(a|b)+c};var Le=function(){function a(b){return{toString:function(){return b}}}return{Ok:a("consent"),Ai:a("convert_case_to"),Bi:a("convert_false_to"),Ci:a("convert_null_to"),Di:a("convert_true_to"),Ei:a("convert_undefined_to"),Dn:a("debug_mode_metadata"),oa:a("function"),rh:a("instance_name"),vl:a("live_only"),wl:a("malware_disabled"),METADATA:a("metadata"),zl:a("original_activity_id"),Nn:a("original_vendor_template_id"),Mn:a("once_on_load"),yl:a("once_per_event"),Nj:a("once_per_load"),Pn:a("priority_override"), +Qn:a("respected_consent_types"),Vj:a("setup_tags"),Fe:a("tag_id"),bk:a("teardown_tags")}}();var gf;var hf=[],jf=[],kf=[],lf=[],mf=[],nf={},of,pf;function qf(a){pf=pf||a} +function rf(a){}var sf,tf=[],uf=[];function vf(a,b){var c={};c[Le.oa]="__"+a;for(var d in b)b.hasOwnProperty(d)&&(c["vtp_"+d]=b[d]);return c} +function wf(a,b,c){try{return of(xf(a,b,c))}catch(d){JSON.stringify(a)}return 2}function yf(a){var b=a[Le.oa];if(!b)throw Error("Error: No function name given for function call.");return!!nf[b]} +var xf=function(a,b,c){c=c||[];var d={},e;for(e in a)a.hasOwnProperty(e)&&(d[e]=zf(a[e],b,c));return d},zf=function(a,b,c){if(Array.isArray(a)){var d;switch(a[0]){case "function_id":return a[1];case "list":d=[];for(var e=1;e0;b--)cb(a[b].id)&&a.splice(b++,1);for(var c=a.length-1;c>0;c--)a[c].line=a[c-1].line;a.splice(0,1);return a};function Gf(a){function b(r){for(var u=0;u=20||a.K+this.H>=16384?!1:this.baseUrl=== -a.baseUrl&&this.C===a.H&&this.Z(a):!0};Zf.prototype.Z=function(a){var b=this;if(!this.K)return this.j===a.C;var c=Object.keys(this.ia);return c.length===Object.keys(a.ia).length&&c.every(function(d){return a.ia.hasOwnProperty(d)&&String(b.ia[d])===String(a.ia[d])})};var $f={},ag=($f.uaa=!0,$f.uab=!0,$f.uafvl=!0,$f.uamb=!0,$f.uam=!0,$f.uap=!0,$f.uapv=!0,$f.uaw=!0,$f); -var dg=function(a,b){var c=a.events;if(c.length===1)return bg(c[0],b);var d=[];a.j&&d.push(a.j);for(var e={},f=0;fw&&(u=y,w=B)});x===c.length&&(g[t]=u)});cg(g,d);b&&d.push("_s="+b);for(var k=d.join("&"),m=[],n={},p=0;p2048&&(f=c.pop(),e=c.join("&"));return{params:e,body:f}},cg=function(a,b){z(a,function(c,d){d!=null&&b.push(encodeURIComponent(c)+"="+encodeURIComponent(d))})};var eg=function(a){var b=[];z(a,function(c,d){d!=null&&b.push(encodeURIComponent(c)+"="+encodeURIComponent(String(d)))});return b.join("&")},fg=function(a,b,c,d,e){this.baseUrl=b;this.endpoint=c;this.ia=a.ia;this.Mc=a.Mc;this.Ah=a.Ah;this.H=d;this.C=eg(a.ia);this.j=eg(a.Ah);this.K=this.j.length;if(e&&this.K>16384)throw Error("EVENT_TOO_LARGE");}; -var ig=function(a,b){for(var c=0;cd.length||!g&&d.length!==e.length?0:g?Eb(d,k)&&(d===k||d.charAt(k.length)==="."):d===k)return!0}return!1},hg=/^[a-z$_][\w$]*$/i,gg=/^(?:[a-z_$][a-z_$0-9]*\.)*[a-z_$][a-z_$0-9]*(?:\.\*)?$/i; -var jg=["matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector"];function kg(a,b){var c=String(a),d=String(b),e=c.length-d.length;return e>=0&&c.indexOf(d,e)===e}var lg=new sb;function mg(a,b,c){var d=c?"i":void 0;try{var e=String(b)+String(d),f=lg.get(e);f||(f=new RegExp(b,d),lg.set(e,f));return f.test(a)}catch(g){return!1}}function ng(a,b){return String(a).indexOf(String(b))>=0}function og(a,b){return String(a)===String(b)} -function pg(a,b){return Number(a)>=Number(b)}function qg(a,b){return Number(a)<=Number(b)}function rg(a,b){return Number(a)>Number(b)}function sg(a,b){return Number(a)0;case 3:return!d(c[0]); -case 4:return mg(d(c[0]),d(c[1]),!1);case 5:return og(d(c[0]),d(c[1]));case 6:return tg(d(c[0]),d(c[1]));case 7:return kg(d(c[0]),d(c[1]));case 8:return ng(d(c[0]),d(c[1]));case 9:return sg(d(c[0]),d(c[1]));case 10:return qg(d(c[0]),d(c[1]));case 11:return rg(d(c[0]),d(c[1]));case 12:return pg(d(c[0]),d(c[1]));default:throw Error('Invalid boolean expression format. Expected "type" property tobe a positive integer which is less than 13.');}};function Tg(a){K(this.getName(),["message:?string"],arguments);};function Ug(a,b){K(this.getName(),["min:!number","max:!number"],arguments);return qb(a,b)};function Vg(){return(new Date).getTime()};function Wg(a){if(a===null)return"null";if(a instanceof Va)return"array";if(a instanceof Wc)return"function";if(a instanceof ad){var b;a=(b=a)==null?void 0:b.getValue();var c;if(((c=a)==null?void 0:c.constructor)===void 0||a.constructor.name===void 0){var d=String(a);return d.substring(8,d.length-1)}return String(a.constructor.name)}return typeof a};function Xg(a){function b(c){return function(d){try{return c(d)}catch(e){(Sf||Tf.tk)&&a.call(this,e.message)}}}return{parse:b(function(c){return dd(JSON.parse(c))}),stringify:b(function(c){return JSON.stringify(G(c))})}};function Yg(a){return ub(G(a,this.D))};function Zg(a){return Number(G(a,this.D))};function $g(a){return a===null?"null":a===void 0?"undefined":a.toString()};function ah(a,b,c){var d=null,e=!1;return e?d:null};var Kg="floor ceil round max min abs pow sqrt".split(" ");function bh(){var a={};return{Wl:function(b){return a.hasOwnProperty(b)?a[b]:void 0},pk:function(b,c){a[b]=c},reset:function(){a={}}}}function ch(a,b){return function(){var c=Array.prototype.slice.call(xa.apply(0,arguments),0);c.unshift(b);return Wc.prototype.invoke.apply(a,c)}} -function dh(a,b){K(this.getName(),["apiName:!string","mock:?*"],arguments);} -function eh(a,b){K(this.getName(),["apiName:!string","mock:!PixieMap"],arguments);};var fh={};var gh=function(a){var b=new Xa;if(a instanceof Va)for(var c=a.La(),d=0;d0?n.join(""):""}else k="";return k} -function Jh(a){return Lh(a.item_id,a.id,a.item_name)}function Lh(){for(var a=h(xa.apply(0,arguments)),b=a.next();!b.done;b=a.next()){var c=b.value;if(c!==null&&c!==void 0)return c}}function Mh(a){if(a&&a.length){for(var b=[],c=0;c>6,128|d&63):d<55296||d>=57344?b.push(224|d>>12,128|d>>6&63,128|d&63):(d=65536+((d&1023)<<10|a.charCodeAt(++c)&1023),b.push(240|d>>18,128|d>>12&63,128|d>>6&63,128|d&63))}return new Uint8Array(b)}} -function Vh(a){if(a===""||a==="e0")return Promise.resolve(a);var b;if((b=C.crypto)==null?0:b.subtle){if(Th.test(a))return Promise.resolve(a);try{var c=Uh(a);return C.crypto.subtle.digest("SHA-256",c).then(function(d){var e=Array.from(new Uint8Array(d)).map(function(f){return String.fromCharCode(f)}).join("");return C.btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}).catch(function(){return"e2"})}catch(d){return Promise.resolve("e2")}}else return Promise.resolve("e1")};function Wh(a,b){if(a==="")return b;var c=Number(a);return isNaN(c)?b:c};var Xh=[];function Yh(a){switch(a){case 0:return 0;case 42:return 1;case 43:return 2;case 44:return 9;case 50:return 3;case 65:return 4;case 74:return 7;case 88:return 5;case 103:return 6;case 104:return 11;case 105:return 8}}function P(a){Xh[a]=!0;var b=Yh(a);b!==void 0&&(ib[b]=!0)} -P(32); -P(28);P(29);P(30);P(31);P(45);P(78);P(15); -P(112);P(14); -P(118);P(111); -P(66);P(89); -P(6);P(46);P(4); -P(82);P(108); -P(73);P(70); -P(87); -P(123); -P(99);P(119);P(88);P(5);P(74);P(17);P(18);P(103); -jb[1]=Wh('1',6E4);jb[3]=Wh('10',1);jb[2]=Wh('',50);P(24);P(12);P(69);P(109);var Zh=!1; -P(8);P(91);P(58);P(23);P(105);P(94);P(48);P(21);P(50); -P(62); -P(75);P(61);P(104); -P(107);P(71);P(86); -P(72);P(84);P(53);P(51); -P(95);function Q(a){return!!Xh[a]}function U(a){fb("GTM",a)}; -var gi=function(a){var b=Q(98);b=b===void 0?!1:b;var c={},d=["tv.1"],e=0;var u=d.join("~"), -w={userData:c};return b?{sk:u,jg:w,uk:e,Ll:"tv.1~${"+(u+"|encrypt}"),encryptionKeyString:fi()}:{sk:u,jg:w,uk:e}},di=function(a){return hi.indexOf(a)!==-1},fi=function(){return'{\x22keys\x22:[{\x22id\x22:\x221c712b2f-642e-44d8-9571-fc990b170b42\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BJlhwhV7CDCAWT5kw6b1Y/ba1szyTxbjr+9ktC9wBotMXU1LDufVuO6SZCRknHJY3WbMnakevchuUlctt5akMd0\x3d\x22}},{\x22id\x22:\x222d73bb4b-6a28-428c-a54c-6a946db5ce9e\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BP/V4D+KNwrsoVwMHjYZ8I3PxSchMlpmoF5oYGaqLVmx0SoDG6ViqRAitIhAegM6YkTMzCJ0CwlfLMfVbEZCs6A\x3d\x22}},{\x22id\x22:\x2246f1fa67-227c-471e-8b7a-b3e1cb31f8ef\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BIVLhwDhYMNOLYov0dQFBSbP+23ls4qTtBWmHNFBOFj8cAp10b/E04SZmnJnTfn8ZYrZT8gWOW4eKEFO62hlnr8\x3d\x22}},{\x22id\x22:\x2277625938-c286-4546-8688-193fbbb80284\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BAn95KVRlRKcB396y2PtyaUkSqxVy4QlGwyBdzO5obbZ6TinInt7DQkz9FC+aAgVIDX82eG9RzB5gu1oNGKxBgQ\x3d\x22}},{\x22id\x22:\x22b2bcab08-8f8d-4568-b1fa-35aa150b26d6\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BBXRf+20pfPgVk8j/nbUPZDYWIj2hyOF7s+v+akT56/1ooIF9OsGwhBFFs4y0/sxfIInrEFei4LV5c16GG6hXyg\x3d\x22}}]}'},ji=function(){var a={ab:"tv.1~em.test@example.com~fn.Fake~ln.Name~co.US~sa.123 Fake St~ct.Non-Applicable~pn.+1234567890~pc.12345~rg.ca",af:9,Kh:!1};if(C.Promise){var b=void 0;return b}},li= -function(a,b){if(C.Promise)try{var c=new Promise(function(d){ki(a,d)});return c}catch(d){}},mi=function(a){if(C.Promise)try{return new Promise(function(b){ki(a,function(c){b(c)})})}catch(b){}},ni=function(a){for(var b=a.bf,c=a.time,d=["tv.1"],e=0,f=!1,g=0;g0&&C.Promise?wi(a).some(function(b){return b.value&&di(b.name)&&!Th.test(b.value)}): -!1},oi=function(a,b){var c=wi(a);zi(c,b)},pi=function(a){return a==null?"":l(a)?xb(String(a)):"e0"},vi=function(a){return a.replace(Ai,"")},ti=function(a){return ui(a.replace(/\s/g,""))},ui=function(a){return xb(a.replace(Bi,"").toLowerCase())},si=function(a){a=a.replace(/[\s-()/.]/g,"");a.charAt(0)!=="+"&&(a="+"+a);return Ci.test(a)?a:"e0"},ri=function(a){var b=a.toLowerCase().split("@");if(b.length===2){var c=b[0];/^(gmail|googlemail)\./.test(b[1])&&(c=c.replace(/\./g,""));c=c+"@"+b[1];if(Di.test(c))return c}return"e0"}, -zi=function(a,b){var c=!1;if(c=Q(53)?!a.some(function(e){return e.value&&di(e.name)}):a.some(function(e){e.value&&di(e.name)}))b({bf:a});else if(C.Promise){var d;if(Q(52)||Q(80))d=Oc();Promise.all(a.map(function(e){return e.value&&di(e.name)?Vh(e.value).then(function(f){e.value=f}):Promise.resolve()})).then(function(){var e={bf:a};if(d!==void 0){var f=Oc();d&&f&&(e.time=Math.round(f)-Math.round(d))}b(e)}).catch(function(){b({bf:[]})})}else b({bf:[]})},Bi=/[0-9`~!@#$%^&*()_\-+=:;<>,.?|/\\[\]]/g,Di= -/^\S+@\S+\.\S+$/,Ci=/^\+\d{10,15}$/,Ai=/[.~]/g,ei=/^[0-9A-Za-z_-]{43}$/,Ei={},ci=(Ei.email="em",Ei.phone_number="pn",Ei.first_name="fn",Ei.last_name="ln",Ei.street="sa",Ei.city="ct",Ei.region="rg",Ei.country="co",Ei.postal_code="pc",Ei.error_code="ec",Ei),Fi={},qi=(Fi.email="sha256_email_address",Fi.phone_number="sha256_phone_number",Fi.first_name="sha256_first_name",Fi.last_name="sha256_last_name",Fi.street="sha256_street",Fi);var hi=Object.freeze(["email","phone_number","first_name","last_name", -"street"]);var Gi={},Hi=C.google_tag_manager=C.google_tag_manager||{};Gi.kh="4al0";Gi.ue=Number("0")||0;Gi.nb="dataLayer";Gi.wn="ChAI8IPtuAYQn+mjwe6a1tUaEiUA11tjNlH81yw5rYe+NSf/CfNsh5JHR+Yxq3uHfO3EayiwtfDeGgJfZw\x3d\x3d";var Ii={__cl:1,__ecl:1,__ehl:1,__evl:1,__fal:1,__fil:1,__fsl:1,__hl:1,__jel:1,__lcl:1,__sdl:1,__tl:1,__ytl:1},Ji={__paused:1,__tg:1},Ki;for(Ki in Ii)Ii.hasOwnProperty(Ki)&&(Ji[Ki]=1);var Li=vb("true"),Mi=!0,Ni,Oi=!1;Oi=!0; -Ni=Oi;var Pi,Qi=!1;Pi=Qi;var Ri,Si=!1;Ri=Si;Gi.lf="www.googletagmanager.com";var Ti=""+Gi.lf+(Ni?"/gtag/js":"/gtm.js"),Ui=null,Vi=null,Wi={},Xi={};function Yi(){var a=Hi.sequence||1;Hi.sequence=a+1;return a}Gi.Dk="true";var Zi="";Gi.lh=Zi;var $i=new function(){this.j="";this.H=!1;this.C=0;this.P=this.Z=this.Sa=this.K=""};function aj(){var a=$i.K.length;return $i.K[a-1]==="/"?$i.K.substring(0,a-1):$i.K}function bj(){return $i.H&&$i.C!==1}function cj(a){for(var b={},c=h(a.split("|")),d=c.next();!d.done;d=c.next())b[d.value]=!0;return b}var dj=new sb,ej={},fj={},ij={name:Gi.nb,set:function(a,b){Sa(Hb(a,b),ej);gj()},get:function(a){return hj(a,2)},reset:function(){dj=new sb;ej={};gj()}};function hj(a,b){return b!=2?dj.get(a):jj(a)}function jj(a,b){var c=a.split(".");b=b||[];for(var d=ej,e=0;e0){g=[];for(var t=0;t=0&&(m[m.length-1]="");f=m.join("/");break;case "query":f=a.search.replace("?","");e&&(f=tj(f,e,!1));break;case "extension":var n=a.pathname.split(".");f=n.length>1?n[n.length-1]:"";f=f.split("/")[0];break;case "fragment":f=a.hash.replace("#","");break;default:f=a&&a.href}return f}function vj(a){return a?a.replace(":","").toLowerCase():""}function xj(a){var b="";if(a&&a.href){var c=a.href.indexOf("#");b=c<0?a.href:a.href.substring(0,c)}return b}var yj={},zj=0; -function Aj(a){var b=yj[a];if(!b){var c=E.createElement("a");a&&(c.href=a);var d=c.pathname;d[0]!=="/"&&(a||fb("TAGGING",1),d="/"+d);var e=c.hostname.replace(rj,"");b={href:c.href,protocol:c.protocol,host:c.host,hostname:e,pathname:d,search:c.search,hash:c.hash,port:c.port};zj<5&&(yj[a]=b,zj++)}return b} -function Bj(a){function b(n){var p=n.split("=")[0];return d.indexOf(p)<0?n:p+"=0"}function c(n){return n.split("&").map(b).filter(function(p){return p!==void 0}).join("&")}var d="gclid dclid gbraid wbraid gclaw gcldc gclha gclgf gclgb _gl".split(" "),e=Aj(a),f=a.split(/[?#]/)[0],g=e.search,k=e.hash;g[0]==="?"&&(g=g.substring(1));k[0]==="#"&&(k=k.substring(1));g=c(g);k=c(k);g!==""&&(g="?"+g);k!==""&&(k="#"+k);var m=""+f+g+k;m[m.length-1]==="/"&&(m=m.substring(0,m.length-1));return m} -function Cj(a){var b=Aj(C.location.href),c=uj(b,"host",!1);if(c&&c.match(sj)){var d=uj(b,"path");if(d){var e=d.split(a+"=");if(e.length>1)return e[1].split(";")[0].split("?")[0]}}}function Dj(a){for(var b=0;b<3;++b)try{var c=decodeURIComponent(a).replace(/\+/g," ");if(c===a)break;a=c}catch(d){return""}return a};var Ej={"https://www.google.com":"/g","https://www.googleadservices.com":"/as","https://pagead2.googlesyndication.com":"/gs"};function Fj(a,b){if(a){var c=""+a;c.indexOf("http://")!==0&&c.indexOf("https://")!==0&&(c="https://"+c);c[c.length-1]==="/"&&(c=c.substring(0,c.length-1));return Aj(""+c+b).href}}function Gj(a,b){if(bj()||Pi)return Fj(a,b)}function Hj(){return!!Gi.lh&&Gi.lh.split("@@").join("")!=="SGTM_TOKEN"} -function Ij(a){for(var b=h([O.g.ld,O.g.Pb]),c=b.next();!c.done;c=b.next()){var d=V(a,c.value);if(d)return d}}function Jj(a,b){return bj()?""+aj()+(b?Ej[a]||"":""):a};function Kj(a){var b=String(a[He.la]||"").replace(/_/g,"");return Eb(b,"cvt")?"cvt":b}var Lj=C.location.search.indexOf("?gtm_latency=")>=0||C.location.search.indexOf(">m_latency=")>=0;var Mj={sampleRate:"0.005000",zk:"",un:"0.01"},Nj=Math.random(),Oj;if(!(Oj=Lj)){var Pj=Mj.sampleRate;Oj=Nj=1-Number(Mj.un);var Vj=/gtag[.\/]js/,Wj=/gtm[.\/]js/,Xj=!1;function Yj(a){if(Xj)return"1";var b=a.scriptSource;if(b){if(Vj.test(b))return"3";if(Wj.test(b))return"2"}return"0"}function Zj(a,b){var c=ak();c.pending||(c.pending=[]);pb(c.pending,function(d){return d.target.ctid===a.ctid&&d.target.isDestination===a.isDestination})||c.pending.push({target:a,onLoad:b})}function bk(){var a=C.google_tags_first_party;Array.isArray(a)||(a=[]);for(var b={},c=h(a),d=c.next();!d.done;d=c.next())b[d.value]=!0;return Object.freeze(b)} -var ck=function(){this.container={};this.destination={};this.canonical={};this.pending=[];this.siloed=[];this.injectedFirstPartyContainers={};this.injectedFirstPartyContainers=bk()}; -function ak(){var a=sc("google_tag_data",{}),b=a.tidr;b&&typeof b==="object"||(b=new ck,a.tidr=b);var c=b;c.container||(c.container={});c.destination||(c.destination={});c.canonical||(c.canonical={});c.pending||(c.pending=[]);c.siloed||(c.siloed=[]);c.injectedFirstPartyContainers||(c.injectedFirstPartyContainers=bk());return c};var dk={},ek=!1,Nf={ctid:"G-V7DRP5E70N",canonicalContainerId:"97518959",ek:"G-V7DRP5E70N|GT-5NGSF76",fk:"G-V7DRP5E70N"};dk.qe=vb("");function fk(){var a=gk();return ek?a.map(hk):a}function ik(){var a=jk();return ek?a.map(hk):a}function kk(){return lk(Nf.ctid)}function mk(){return lk(Nf.canonicalContainerId||"_"+Nf.ctid)}function gk(){return Nf.ek?Nf.ek.split("|"):[Nf.ctid]}function jk(){return Nf.fk?Nf.fk.split("|"):[]} -function nk(){var a=ok(pk()),b=a&&a.parent;if(b)return ok(b)}function ok(a){var b=ak();return a.isDestination?b.destination[a.ctid]:b.container[a.ctid]}function lk(a){return ek?hk(a):a}function hk(a){return"siloed_"+a}function qk(a){return ek?rk(a):a}function rk(a){a=String(a);return Eb(a,"siloed_")?a.substring(7):a} -function sk(){var a=!1;if(a){var b=ak();if(b.siloed){for(var c=[],d=gk().map(hk),e=jk().map(hk),f={},g=0;g=0){var t;b:{if(q.scriptSource){for(var v=$i.H,u=Aj(q.scriptSource),w=v?u.pathname:""+u.hostname+u.pathname,x=E.scripts,y="",A=0;A=0){t=String(A);break b}y=String(A)}}if(y){t=y;break b}}t=void 0}var D=t;if(D){Xj=!0;r=D;break a}}var I=[].slice.call(document.scripts);r=q.scriptElement?String(I.indexOf(q.scriptElement)):"-1"}q.htmlLoadOrder=r;q.loadScriptType=Yj(q)}var J=p?e.destination:e.container,H=J[n];H?(p&&H.state===0&&U(93),Object.assign(H,q)):J[n]=q},e=ak(),f=h(b),g=f.next();!g.done;g=f.next())d(g.value,!1);for(var k=h(c),m= -k.next();!m.done;m=k.next())d(m.value,!0);e.canonical[mk()]={};tk()}function vk(a){return!!ak().container[a]}function wk(a){var b=ak().destination[a];return!!b&&!!b.state}function pk(){return{ctid:kk(),isDestination:dk.qe}}function xk(a){var b=ak();(b.siloed=b.siloed||[]).push(a)}function yk(){var a=ak().container,b;for(b in a)if(a.hasOwnProperty(b)&&a[b].state===1)return!0;return!1}function zk(){var a={};z(ak().destination,function(b,c){c.state===0&&(a[rk(b)]=c)});return a} -function Ak(a){return!!(a&&a.parent&&a.context&&a.context.source===1&&a.parent.ctid.indexOf("GTM-")!==0)}var Bk="/td?id="+Nf.ctid,Ck=["v","t","pid","dl","tdp"],Dk=["mcc"],Ek={},Fk={};function Gk(a,b,c){Fk[a]=b;(c===void 0||c)&&Hk(a)}function Hk(a,b){if(Ek[a]===void 0||(b===void 0?0:b))Ek[a]=!0}function Ik(a){a=a===void 0?!1:a;var b=Object.keys(Ek).filter(function(c){return Ek[c]===!0&&Fk[c]!==void 0&&(a||!Dk.includes(c))}).map(function(c){var d=Fk[c];typeof d==="function"&&(d=d());return d?"&"+c+"="+d:""}).join("");return""+Jj("https://www.googletagmanager.com")+Bk+(""+b+"&z=0")} -function Jk(){Object.keys(Ek).forEach(function(a){Ck.indexOf(a)<0&&(Ek[a]=!1)})}function Kk(a){a=a===void 0?!1:a;if(Rj&&Nf.ctid){var b=Ik(a);a?Lc(b):Ac(b);Jk()}}function Lk(){Object.keys(Ek).filter(function(a){return Ek[a]&&!Ck.includes(a)}).length>0&&Kk(!0)}var Mk=qb();function Nk(){Mk=qb()}function Ok(){Gk("v","3");Gk("t","t");Gk("pid",function(){return String(Mk)});Cc(C,"pagehide",Lk);C.setInterval(Nk,864E5)}function Pk(){var a=sc("google_tag_data",{});return a.ics=a.ics||new Qk}var Qk=function(){this.entries={};this.waitPeriodTimedOut=this.wasSetLate=this.accessedAny=this.accessedDefault=this.usedImplicit=this.usedUpdate=this.usedDefault=this.usedDeclare=this.active=!1;this.j=[]}; -Qk.prototype.default=function(a,b,c,d,e,f,g){this.usedDefault||this.usedDeclare||!this.accessedDefault&&!this.accessedAny||(this.wasSetLate=!0);this.usedDefault=this.active=!0;fb("TAGGING",19);b==null?fb("TAGGING",18):Rk(this,a,b==="granted",c,d,e,f,g)};Qk.prototype.waitForUpdate=function(a,b,c){for(var d=0;d0&&n.update===void 0),t={region:q,declare_region:n.declare_region,implicit:n.implicit,default:c!==void 0?c:n.default,declare:n.declare,update:n.update,quiet:r};if(e!==""||n.default!==!1)m[b]=t;r&&C.setTimeout(function(){m[b]===t&&t.quiet&&(fb("TAGGING",2),a.waitPeriodTimedOut=!0,a.clearTimeout(b,void 0,k), -a.notifyListeners())},g)}};aa=Qk.prototype;aa.clearTimeout=function(a,b,c){var d=[a],e=c.delegatedConsentTypes,f;for(f in e)e.hasOwnProperty(f)&&e[f]===a&&d.push(f);var g=this.entries[a]||{},k=this.getConsentState(a,c);if(g.quiet){g.quiet=!1;for(var m=h(d),n=m.next();!n.done;n=m.next())Sk(this,n.value)}else if(b!==void 0&&k!==b)for(var p=h(d),q=p.next();!q.done;q=p.next())Sk(this,q.value)}; -aa.update=function(a,b,c){this.usedDefault||this.usedDeclare||this.usedUpdate||!this.accessedAny||(this.wasSetLate=!0);this.usedUpdate=this.active=!0;if(b!=null){var d=this.getConsentState(a,c),e=this.entries;(e[a]=e[a]||{}).update=b==="granted";this.clearTimeout(a,d,c)}}; -aa.declare=function(a,b,c,d,e){this.usedDeclare=this.active=!0;var f=this.entries,g=f[a]||{},k=g.declare_region,m=c&&l(c)?c.toUpperCase():void 0;d=d.toUpperCase();e=e.toUpperCase();if(d===""||m===e||(m===d?k!==e:!m&&!k)){var n={region:g.region,declare_region:m,declare:b==="granted",implicit:g.implicit,default:g.default,update:g.update,quiet:g.quiet};if(d!==""||g.declare!==!1)f[a]=n}}; -aa.implicit=function(a,b){this.usedImplicit=!0;var c=this.entries,d=c[a]=c[a]||{};d.implicit!==!1&&(d.implicit=b==="granted")}; -aa.getConsentState=function(a,b){var c=this.entries,d=c[a]||{},e=d.update;if(e!==void 0)return e?1:2;if(b.usedContainerScopedDefaults){var f=b.containerScopedDefaults[a];if(f===3)return 1;if(f===2)return 2}else if(e=d.default,e!==void 0)return e?1:2;if(b==null?0:b.delegatedConsentTypes.hasOwnProperty(a)){var g=b.delegatedConsentTypes[a],k=c[g]||{};e=k.update;if(e!==void 0)return e?1:2;if(b.usedContainerScopedDefaults){var m=b.containerScopedDefaults[g];if(m===3)return 1;if(m===2)return 2}else if(e= -k.default,e!==void 0)return e?1:2}e=d.declare;if(e!==void 0)return e?1:2;e=d.implicit;return e!==void 0?e?3:4:0};aa.addListener=function(a,b){this.j.push({consentTypes:a,Rl:b})};var Sk=function(a,b){for(var c=0;c=e.length?m(n):C.setTimeout(function(){m(c())},500)}}))};var fl=["ad_storage","analytics_storage","ad_user_data","ad_personalization"],gl=!1,hl=!1;function il(){Q(48)&&!hl&&gl&&(fl.some(function(a){return Wk.containerScopedDefaults[a]!==1})||jl("mbc"));hl=!0}function jl(a){Rj&&(Gk(a,"1"),Kk())}function kl(a){fb("HEALTH",a)};var ll;try{ll=JSON.parse(cb("eyIwIjoiVVMiLCIxIjoiVVMtSUwiLCIyIjpmYWxzZSwiMyI6IiIsIjQiOiIiLCI1Ijp0cnVlLCI2IjpmYWxzZSwiNyI6ImFkX3N0b3JhZ2V8YW5hbHl0aWNzX3N0b3JhZ2V8YWRfdXNlcl9kYXRhfGFkX3BlcnNvbmFsaXphdGlvbiJ9"))}catch(a){U(123),kl(2),ll={}}function ml(){return ll["0"]||""}function nl(){return ll["1"]||""}function ol(){var a=!1;a=!!ll["2"];return a}function pl(){return ll["6"]!==!1}function ql(){var a="";a=ll["4"]||"";return a} -function rl(){var a=!1;a=!!ll["5"];return a}function sl(){var a="";a=ll["3"]||"";return a}var tl=[O.g.O,O.g.U,O.g.N,O.g.sa],ul,vl;function wl(a){for(var b=a[O.g.Gb],c=Array.isArray(b)?b:[b],d={Ne:0};d.Ne=0||E.location.search.indexOf(">m_diagnostics=")>=0,fm=void 0; -function gm(a,b){if(b.length&&Rj){var c;(c=$l)[a]!=null||(c[a]=[]);am[a]!=null||(am[a]=[]);var d=b.filter(function(e){return!am[a].includes(e)});$l[a].push.apply($l[a],oa(d));am[a].push.apply(am[a],oa(d));!fm&&d.length>0&&(Hk("tdc",!0),fm=C.setTimeout(function(){Kk();$l={};fm=void 0},Zl))}} -function hm(a,b,c){if(Rj&&a==="config"){var d,e=(d=Ul(b))==null?void 0:d.ids;if(!(e&&e.length>1)){var f,g=sc("google_tag_data",{});g.td||(g.td={});f=g.td;var k=Sa(c.K);Sa(c.j,k);var m=[],n;for(n in f)if(f.hasOwnProperty(n)){var p=im(f[n],k);p.length&&(em&&console.log(p),m.push(n))}m.length&&(gm(b,m),fb("TAGGING",bm[E.readyState]||14));f[b]=k}}}function jm(a,b){var c={},d;for(d in b)b.hasOwnProperty(d)&&(c[d]=!0);for(var e in a)a.hasOwnProperty(e)&&(c[e]=!0);return c} -function im(a,b,c,d){c=c===void 0?{}:c;d=d===void 0?"":d;if(a===b)return[];var e=function(r,t){var v;Oa(t)==="object"?v=t[r]:Oa(t)==="array"&&(v=t[r]);return v===void 0?dm[r]:v},f=jm(a,b),g;for(g in f)if(f.hasOwnProperty(g)){var k=(d?d+".":"")+g,m=e(g,a),n=e(g,b),p=Oa(m)==="object"||Oa(m)==="array",q=Oa(n)==="object"||Oa(n)==="array";if(p&&q)im(m,n,c,k);else if(p||q||m!==n)c[k]=!0}return Object.keys(c)} -function km(){Gk("tdc",function(){fm&&(C.clearTimeout(fm),fm=void 0);var a=[],b;for(b in $l)$l.hasOwnProperty(b)&&a.push(b+"*"+$l[b].join("."));return a.length?a.join("!"):void 0},!1)};var lm=function(a,b,c,d,e,f,g,k,m,n,p){this.eventId=a;this.priorityId=b;this.j=c;this.P=d;this.H=e;this.K=f;this.C=g;this.eventMetadata=k;this.onSuccess=m;this.onFailure=n;this.isGtmEvent=p},mm=function(a,b){var c=[];switch(b){case 3:c.push(a.j);c.push(a.P);c.push(a.H);c.push(a.K);c.push(a.C);break;case 2:c.push(a.j);break;case 1:c.push(a.P);c.push(a.H);c.push(a.K);c.push(a.C);break;case 4:c.push(a.j),c.push(a.P),c.push(a.H),c.push(a.K)}return c},V=function(a,b,c,d){for(var e=h(mm(a,d===void 0?3: -d)),f=e.next();!f.done;f=e.next()){var g=f.value;if(g[b]!==void 0)return g[b]}return c},nm=function(a){for(var b={},c=mm(a,4),d=h(c),e=d.next();!e.done;e=d.next())for(var f=Object.keys(e.value),g=h(f),k=g.next();!k.done;k=g.next())b[k.value]=1;return Object.keys(b)},om=function(a,b,c){function d(n){Qa(n)&&z(n,function(p,q){f=!0;e[p]=q})}var e={},f=!1,g=mm(a,c===void 0?3:c);g.reverse();for(var k=h(g),m=k.next();!m.done;m=k.next())d(m.value[b]);return f?e:void 0},pm=function(a){for(var b=[O.g.Uc,O.g.Qc, -O.g.Rc,O.g.Sc,O.g.Tc,O.g.Vc,O.g.Wc],c=mm(a,3),d=h(c),e=d.next();!e.done;e=d.next()){for(var f=e.value,g={},k=!1,m=h(b),n=m.next();!n.done;n=m.next()){var p=n.value;f[p]!==void 0&&(g[p]=f[p],k=!0)}var q=k?g:void 0;if(q)return q}return{}},qm=function(a,b){this.eventId=a;this.priorityId=b;this.C={};this.P={};this.j={};this.H={};this.Z={};this.K={};this.eventMetadata={};this.isGtmEvent=!1;this.onSuccess=function(){};this.onFailure=function(){}},rm=function(a,b){a.C=b;return a},sm=function(a,b){a.P=b; -return a},tm=function(a,b){a.j=b;return a},um=function(a,b){a.H=b;return a},vm=function(a,b){a.Z=b;return a},wm=function(a,b){a.K=b;return a},xm=function(a,b){a.eventMetadata=b||{};return a},ym=function(a,b){a.onSuccess=b;return a},zm=function(a,b){a.onFailure=b;return a},Am=function(a,b){a.isGtmEvent=b;return a},Bm=function(a){return new lm(a.eventId,a.priorityId,a.C,a.P,a.j,a.H,a.K,a.eventMetadata,a.onSuccess,a.onFailure,a.isGtmEvent)};var Cm={yk:Number("5"),io:Number("")},Dm=[];function Em(a){Dm.push(a)}var Fm="?id="+Nf.ctid,Gm=void 0,Hm={},Im=void 0,Jm=new function(){var a=5;Cm.yk>0&&(a=Cm.yk);this.C=a;this.j=0;this.H=[]},Km=1E3; -function Lm(a,b){var c=Gm;if(c===void 0)if(b)c=Yi();else return"";for(var d=[Jj("https://www.googletagmanager.com"),"/a",Fm],e=h(Dm),f=e.next();!f.done;f=e.next())for(var g=f.value,k=g({eventId:c,Oc:!!a}),m=h(k),n=m.next();!n.done;n=m.next()){var p=h(n.value),q=p.next().value,r=p.next().value;d.push("&"+q+"="+r)}d.push("&z=0");return d.join("")} -function Mm(){Im&&(C.clearTimeout(Im),Im=void 0);if(Gm!==void 0&&Nm){var a;(a=Hm[Gm])||(a=Jm.j=2022&&Mm())}var Pm=qb();function Qm(){Pm=qb()}function Rm(){return[["v","3"],["t","t"],["pid",String(Pm)]]}var Sm={};function Tm(a,b,c){Qj&&a!==void 0&&(Sm[a]=Sm[a]||[],Sm[a].push(c+b),Om(a))}function Um(a){var b=a.eventId,c=a.Oc,d=[],e=Sm[b]||[];e.length&&d.push(["epr",e.join(".")]);c&&delete Sm[b];return d};function Vm(a,b){var c=Ul(lk(a),!0);c&&Wm.register(c,b)}function Xm(a,b,c,d){var e=Ul(c,d.isGtmEvent);e&&(Q(47)&&Q(47)&&Mi&&!ek&&(d.deferrable=!0),Wm.push("event",[b,a],e,d))}function Ym(a,b,c,d){var e=Ul(c,d.isGtmEvent);e&&Wm.push("get",[a,b],e,d)}function Zm(a){var b=Ul(lk(a),!0),c;b?c=$m(Wm,b).j:c={};return c}function an(a,b){var c=Ul(lk(a),!0);if(c){var d=Wm,e=Sa(b,null);Sa($m(d,c).j,e);$m(d,c).j=e}} -var bn=function(){this.P={};this.j={};this.C={};this.Z=null;this.K={};this.H=!1;this.status=1},cn=function(a,b,c,d){this.C=zb();this.j=b;this.args=c;this.messageContext=d;this.type=a},dn=function(){this.destinations={};this.j={};this.commands=[]},$m=function(a,b){var c=b.destinationId;return a.destinations[c]=a.destinations[c]||new bn},en=function(a,b,c,d){if(d.j){var e=$m(a,d.j),f=e.Z;if(f){var g=Sa(c,null),k=Sa(e.P[d.j.id],null),m=Sa(e.K,null),n=Sa(e.j,null),p=Sa(a.j,null),q={};if(Qj)try{q=Sa(ej)}catch(u){U(72)}var r= -d.j.prefix,t=function(u){Tm(d.messageContext.eventId,r,u)},v=Bm(Am(zm(ym(xm(vm(um(wm(tm(sm(rm(new qm(d.messageContext.eventId,d.messageContext.priorityId),g),k),m),n),p),q),d.messageContext.eventMetadata),function(){if(t){var u=t;t=void 0;u("2");if(d.messageContext.onSuccess)d.messageContext.onSuccess()}}),function(){if(t){var u=t;t=void 0;u("3");if(d.messageContext.onFailure)d.messageContext.onFailure()}}),!!d.messageContext.isGtmEvent));try{Tm(d.messageContext.eventId,r,"1"),hm(d.type,d.j.id,v), -f(d.j.id,b,d.C,v)}catch(u){Tm(d.messageContext.eventId,r,"4")}}}};dn.prototype.register=function(a,b,c){var d=$m(this,a);d.status!==3&&(d.Z=b,d.status=3,c&&(Sa(d.j,c),d.j=c),this.flush())};dn.prototype.push=function(a,b,c,d){c!==void 0&&($m(this,c).status===1&&($m(this,c).status=2,this.push("require",[{}],c,{})),$m(this,c).H&&(d.deferrable=!1));this.commands.push(new cn(a,c,b,d));d.deferrable||this.flush()}; -dn.prototype.flush=function(a){for(var b=this,c=[],d=!1,e={};this.commands.length;e={Ec:void 0,Bh:void 0}){var f=this.commands[0],g=f.j;if(f.messageContext.deferrable)!g||$m(this,g).H?(f.messageContext.deferrable=!1,this.commands.push(f)):c.push(f),this.commands.shift();else{switch(f.type){case "require":if($m(this,g).status!==3&&!a){this.commands.push.apply(this.commands,c);return}break;case "set":z(f.args[0],function(r,t){Sa(Hb(r,t),b.j)});break;case "config":var k=$m(this,g);e.Ec={};z(f.args[0], -function(r){return function(t,v){Sa(Hb(t,v),r.Ec)}}(e));var m=!!e.Ec[O.g.ic];delete e.Ec[O.g.ic];var n=g.destinationId===g.id;m||(n?k.K={}:k.P[g.id]={});k.H&&m||en(this,O.g.aa,e.Ec,f);k.H=!0;n?Sa(e.Ec,k.K):(Sa(e.Ec,k.P[g.id]),U(70));d=!0;break;case "event":e.Bh={};z(f.args[0],function(r){return function(t,v){Sa(Hb(t,v),r.Bh)}}(e));en(this,f.args[1],e.Bh,f);break;case "get":var p={},q=(p[O.g.wb]=f.args[0],p[O.g.Jb]=f.args[1],p);en(this,O.g.Wa,q,f)}this.commands.shift();fn(this,f)}}this.commands.push.apply(this.commands, -c);d&&this.flush()};var fn=function(a,b){if(b.type!=="require")if(b.j)for(var c=$m(a,b.j).C[b.type]||[],d=0;d0:!1}function xn(){return wn()?!1:vn("Opera")}function yn(){return vn("Firefox")||vn("FxiOS")}function zn(){return wn()?un("Chromium"):(vn("Chrome")||vn("CriOS"))&&!(wn()?0:vn("Edge"))||vn("Silk")};function An(){return ln?!!sn&&!!sn.platform:!1}function Bn(){return vn("iPhone")&&!vn("iPod")&&!vn("iPad")}function Cn(){Bn()||vn("iPad")||vn("iPod")};var Dn=function(a){Dn[" "](a);return a};Dn[" "]=function(){};xn();wn()||vn("Trident")||vn("MSIE");vn("Edge");!vn("Gecko")||rn().toLowerCase().indexOf("webkit")!=-1&&!vn("Edge")||vn("Trident")||vn("MSIE")||vn("Edge");rn().toLowerCase().indexOf("webkit")!=-1&&!vn("Edge")&&vn("Mobile");An()||vn("Macintosh");An()||vn("Windows");(An()?sn.platform==="Linux":vn("Linux"))||An()||vn("CrOS");An()||vn("Android");Bn();vn("iPad");vn("iPod");Cn();rn().toLowerCase().indexOf("kaios");var En=function(a,b,c,d){for(var e=b,f=c.length;(e=a.indexOf(c,e))>=0&&ec)e=c;d+=b.length+1;return decodeURIComponent(a.slice(d,e!==-1?e:0).replace(/\+/g," "))},Hn=/[?&]($|#)/,In=function(a,b,c){for(var d,e=a.search(Fn),f=0,g,k=[];(g=En(a,f,b,e))>=0;)k.push(a.substring(f, -g)),f=Math.min(a.indexOf("&",g)+1||e,e);k.push(a.slice(f));d=k.join("").replace(Hn,"$1");var m,n=c!=null?"="+encodeURIComponent(String(c)):"";var p=b+n;if(p){var q,r=d.indexOf("#");r<0&&(r=d.length);var t=d.indexOf("?"),v;t<0||t>r?(t=r,v=""):v=d.substring(t+1,r);q=[d.slice(0,t),v,d.slice(r)];var u=q[1];q[1]=p?u?u+"&"+p:p:u;m=q[0]+(q[1]?"?"+q[1]:"")+q[2]}else m=d;return m};var Jn=function(a){try{var b;if(b=!!a&&a.location.href!=null)a:{try{Dn(a.foo);b=!0;break a}catch(c){}b=!1}return b}catch(c){return!1}},Kn=function(a,b){if(a)for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&b(a[c],c,a)},Ln=function(a){if(C.top==C)return 0;if(a===void 0?0:a){var b=C.location.ancestorOrigins;if(b)return b[b.length-1]==C.location.origin?1:2}return Jn(C.top)?1:2},Mn=function(a){a=a===void 0?document:a;return a.createElement("img")},Nn=function(){for(var a=C,b=a;a&&a!=a.parent;)a= -a.parent,Jn(a)&&(b=a);return b};function On(a,b,c,d){d=d===void 0?!1:d;a.google_image_requests||(a.google_image_requests=[]);var e=Mn(a.document);if(c){var f=function(){if(c){var g=a.google_image_requests,k=lc(g,e);k>=0&&Array.prototype.splice.call(g,k,1)}kn(e,"load",f);kn(e,"error",f)};jn(e,"load",f);jn(e,"error",f)}d&&(e.attributionSrc="");e.src=b;a.google_image_requests.push(e)} -var Qn=function(a){var b;b=b===void 0?!1:b;var c="https://pagead2.googlesyndication.com/pagead/gen_204?id=tcfe";Kn(a,function(d,e){if(d||d===0)c+="&"+e+"="+encodeURIComponent(""+d)});Pn(c,b)},Pn=function(a,b){var c=window,d;b=b===void 0?!1:b;d=d===void 0?!1:d;if(c.fetch){var e={keepalive:!0,credentials:"include",redirect:"follow",method:"get",mode:"no-cors"};d&&(e.mode="cors","setAttributionReporting"in XMLHttpRequest.prototype?e.attributionReporting={eventSourceEligible:"true",triggerEligible:"false"}: -e.headers={"Attribution-Reporting-Eligible":"event-source"});c.fetch(a,e)}else On(c,a,b===void 0?!1:b,d===void 0?!1:d)};var Rn=function(){this.P=this.P;this.C=this.C};Rn.prototype.P=!1;Rn.prototype.dispose=function(){this.P||(this.P=!0,this.Sa())};Rn.prototype[Symbol.dispose]=function(){this.dispose()};Rn.prototype.addOnDisposeCallback=function(a,b){this.P?b!==void 0?a.call(b):a():(this.C||(this.C=[]),b&&(a=a.bind(b)),this.C.push(a))};Rn.prototype.Sa=function(){if(this.C)for(;this.C.length;)this.C.shift()()};var Sn=function(a){a.addtlConsent!==void 0&&typeof a.addtlConsent!=="string"&&(a.addtlConsent=void 0);a.gdprApplies!==void 0&&typeof a.gdprApplies!=="boolean"&&(a.gdprApplies=void 0);return a.tcString!==void 0&&typeof a.tcString!=="string"||a.listenerId!==void 0&&typeof a.listenerId!=="number"?2:a.cmpStatus&&a.cmpStatus!=="error"?0:3},Tn=function(a,b){b=b===void 0?{}:b;Rn.call(this);this.H=a;this.j=null;this.Z={};this.Uf=0;var c;this.oe=(c=b.pn)!=null?c:500;var d;this.Dc=(d=b.Rn)!=null?d:!1;this.K= -null};wa(Tn,Rn);Tn.prototype.Sa=function(){this.Z={};this.K&&(kn(this.H,"message",this.K),delete this.K);delete this.Z;delete this.H;delete this.j;Rn.prototype.Sa.call(this)};var Vn=function(a){return typeof a.H.__tcfapi==="function"||Un(a)!=null}; -Tn.prototype.addEventListener=function(a){var b=this,c={internalBlockOnErrors:this.Dc},d=hn(function(){return a(c)}),e=0;this.oe!==-1&&(e=setTimeout(function(){c.tcString="tcunavailable";c.internalErrorState=1;d()},this.oe));var f=function(g,k){clearTimeout(e);g?(c=g,c.internalErrorState=Sn(c),c.internalBlockOnErrors=b.Dc,k&&c.internalErrorState===0||(c.tcString="tcunavailable",k||(c.internalErrorState=3))):(c.tcString="tcunavailable",c.internalErrorState=3);a(c)};try{Wn(this,"addEventListener",f)}catch(g){c.tcString= -"tcunavailable",c.internalErrorState=3,e&&(clearTimeout(e),e=0),d()}};Tn.prototype.removeEventListener=function(a){a&&a.listenerId&&Wn(this,"removeEventListener",null,a.listenerId)}; -var Yn=function(a,b,c){var d;d=d===void 0?"755":d;var e;a:{if(a.publisher&&a.publisher.restrictions){var f=a.publisher.restrictions[b];if(f!==void 0){e=f[d===void 0?"755":d];break a}}e=void 0}var g=e;if(g===0)return!1;var k=c;c===2?(k=0,g===2&&(k=1)):c===3&&(k=1,g===1&&(k=0));var m;if(k===0)if(a.purpose&&a.vendor){var n=Xn(a.vendor.consents,d===void 0?"755":d);m=n&&b==="1"&&a.purposeOneTreatment&&a.publisherCC==="CH"?!0:n&&Xn(a.purpose.consents,b)}else m=!0;else m=k===1?a.purpose&&a.vendor?Xn(a.purpose.legitimateInterests, -b)&&Xn(a.vendor.legitimateInterests,d===void 0?"755":d):!0:!0;return m},Xn=function(a,b){return!(!a||!a[b])},Wn=function(a,b,c,d){c||(c=function(){});if(typeof a.H.__tcfapi==="function"){var e=a.H.__tcfapi;e(b,2,c,d)}else if(Un(a)){Zn(a);var f=++a.Uf;a.Z[f]=c;if(a.j){var g={};a.j.postMessage((g.__tcfapiCall={command:b,version:2,callId:f,parameter:d},g),"*")}}else c({},!1)},Un=function(a){if(a.j)return a.j;var b;a:{for(var c=a.H,d=0;d<50;++d){var e;try{e=!(!c.frames||!c.frames.__tcfapiLocator)}catch(k){e= -!1}if(e){b=c;break a}var f;b:{try{var g=c.parent;if(g&&g!=c){f=g;break b}}catch(k){}f=null}if(!(c=f))break}b=null}a.j=b;return a.j},Zn=function(a){a.K||(a.K=function(b){try{var c;c=(typeof b.data==="string"?JSON.parse(b.data):b.data).__tcfapiReturn;a.Z[c.callId](c.returnValue,c.success)}catch(d){}},jn(a.H,"message",a.K))},$n=function(a){if(a.gdprApplies===!1)return!0;a.internalErrorState===void 0&&(a.internalErrorState=Sn(a));return a.cmpStatus==="error"||a.internalErrorState!==0?a.internalBlockOnErrors? -(Qn({e:String(a.internalErrorState)}),!1):!0:a.cmpStatus!=="loaded"||a.eventStatus!=="tcloaded"&&a.eventStatus!=="useractioncomplete"?!1:!0};var ao={1:0,3:0,4:0,7:3,9:3,10:3};function ko(){var a=Hi.tcf||{};return Hi.tcf=a}var lo=function(){return new Tn(C,{pn:-1})}; -function mo(){var a=ko(),b=lo();Vn(b)&&!no()&&!oo()&&U(124);if(!a.active&&Vn(b)){no()&&(a.active=!0,a.nc={},a.cmpId=0,a.tcfPolicyVersion=0,Pk().active=!0,a.tcString="tcunavailable");El();try{b.addEventListener(function(c){if(c.internalErrorState!==0)po(a),Fl([O.g.O,O.g.sa,O.g.N]),Pk().active=!0;else if(a.gdprApplies=c.gdprApplies,a.cmpId=c.cmpId,a.enableAdvertiserConsentMode=c.enableAdvertiserConsentMode,oo()&&(a.active=!0),!qo(c)||no()||oo()){a.tcfPolicyVersion=c.tcfPolicyVersion;var d;if(c.gdprApplies=== -!1){var e={},f;for(f in ao)ao.hasOwnProperty(f)&&(e[f]=!0);d=e;b.removeEventListener(c)}else if(qo(c)){var g={},k;for(k in ao)if(ao.hasOwnProperty(k))if(k==="1"){var m,n=c,p={Vl:!0};p=p===void 0?{}:p;m=$n(n)?n.gdprApplies===!1?!0:n.tcString==="tcunavailable"?!p.Yj:(p.Yj||n.gdprApplies!==void 0||p.Vl)&&(p.Yj||typeof n.tcString==="string"&&n.tcString.length)?Yn(n,"1",0):!0:!1;g["1"]=m}else g[k]=Yn(c,k,ao[k]);d=g}if(d){a.tcString=c.tcString||"tcempty";a.nc=d;var q={},r=(q[O.g.O]=a.nc["1"]?"granted": -"denied",q);a.gdprApplies!==!0?(Fl([O.g.O,O.g.sa,O.g.N]),Pk().active=!0):(r[O.g.sa]=a.nc["3"]&&a.nc["4"]?"granted":"denied",typeof a.tcfPolicyVersion==="number"&&a.tcfPolicyVersion>=4?r[O.g.N]=a.nc["1"]&&a.nc["7"]?"granted":"denied":Fl([O.g.N]),zl(r,{eventId:0},{gdprApplies:a?a.gdprApplies:void 0,tcString:ro()||""}))}}else Fl([O.g.O,O.g.sa,O.g.N])})}catch(c){po(a),Fl([O.g.O,O.g.sa,O.g.N]),Pk().active=!0}}}function po(a){a.type="e";a.tcString="tcunavailable"} -function qo(a){return a.eventStatus==="tcloaded"||a.eventStatus==="useractioncomplete"||a.eventStatus==="cmpuishown"}function no(){return C.gtag_enable_tcf_support===!0}function oo(){return ko().enableAdvertiserConsentMode===!0}function ro(){var a=ko();if(a.active)return a.tcString}function so(){var a=ko();if(a.active&&a.gdprApplies!==void 0)return a.gdprApplies?"1":"0"}function to(a){if(!ao.hasOwnProperty(String(a)))return!0;var b=ko();return b.active&&b.nc?!!b.nc[String(a)]:!0}var uo=[O.g.O,O.g.U,O.g.N,O.g.sa],vo={},wo=(vo[O.g.O]=1,vo[O.g.U]=2,vo);function xo(a){if(a===void 0)return 0;switch(V(a,O.g.ja)){case void 0:return 1;case !1:return 3;default:return 2}}function yo(a){if(nl()==="US-CO"&&oc.globalPrivacyControl===!0)return!1;var b=xo(a);if(b===3)return!1;switch(Yk(O.g.sa)){case 1:case 3:return!0;case 2:return!1;case 4:return b===2;case 0:return!0;default:return!1}}function zo(){return al()||!Xk(O.g.O)||!Xk(O.g.U)} -function Ao(){var a={},b;for(b in wo)wo.hasOwnProperty(b)&&(a[wo[b]]=Yk(b));return"G1"+Ee(a[1]||0)+Ee(a[2]||0)}var Bo={},Co=(Bo[O.g.O]=0,Bo[O.g.U]=1,Bo[O.g.N]=2,Bo[O.g.sa]=3,Bo);function Do(a){switch(a){case void 0:return 1;case !0:return 3;case !1:return 2;default:return 0}} -function Eo(a){for(var b="1",c=0;c=0&&c<=4095&&(a="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[c>>6&63],b="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[c&63]);var e="0",f;var g=ko();f=g.active?g.tcfPolicyVersion:void 0;typeof f==="number"&&f>=0&&f<=63&&(e="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[f]);var k=0;pl()&&(k|=1);so()==="1"&&(k|=2);no()&&(k|=4);var m;var n=ko();m=n.enableAdvertiserConsentMode!== -void 0?n.enableAdvertiserConsentMode?"1":"0":void 0;m==="1"&&(k|=8);Pk().waitPeriodTimedOut&&(k|=16);return"1"+a+b+e+"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[k]}function Jo(){return nl()==="US-CO"};function Ko(){var a=!1;return a};var Lo={UA:1,AW:2,DC:3,G:4,GF:5,GT:12,GTM:14,HA:6,MC:7}; -function Mo(a){a=a===void 0?{}:a;var b=Nf.ctid.split("-")[0].toUpperCase(),c={};c.ctid=Nf.ctid;c.Wm=Gi.ue;c.bn=Gi.kh;c.Bm=dk.qe?2:1;c.kn=a.nk;c.Be=Nf.canonicalContainerId;c.Be!==a.ra&&(c.ra=a.ra);var d=nk();c.Mm=d?d.canonicalContainerId:void 0;Ni?(c.hg=Lo[b],c.hg||(c.hg=0)):c.hg=Ri?13:10;$i.H?(c.fg=0,c.zl=2):Pi?c.fg=1:Ko()?c.fg=2:c.fg=3;var e={};e[6]=ek;$i.C===2?e[7]=!0:$i.C===1&&(e[2]=!0);c.Cl=e;var f=a.Wf,g;var k=c.hg,m=c.fg;k===void 0?g="":(m||(m=0),g=""+Ge(1,1)+De(k<<2|m));var n=c.zl,p="4"+g+ -(n?""+Ge(2,1)+De(n):""),q,r=c.bn;q=r&&Fe.test(r)?""+Ge(3,2)+r:"";var t,v=c.Wm;t=v?""+Ge(4,1)+De(v):"";var u;var w=c.ctid;if(w&&f){var x=w.split("-"),y=x[0].toUpperCase();if(y!=="GTM"&&y!=="OPT")u="";else{var A=x[1];u=""+Ge(5,3)+De(1+A.length)+(c.Bm||0)+A}}else u="";var B=c.kn,D=c.Be,I=c.ra,J=c.eo,H=p+q+t+u+(B?""+Ge(6,1)+De(B):"")+(D?""+Ge(7,3)+De(D.length)+D:"")+(I?""+Ge(8,3)+De(I.length)+I:"")+(J?""+Ge(9,3)+De(J.length)+J:""),T;var N=c.Cl;N=N===void 0?{}:N;for(var Y=[],da=h(Object.keys(N)),S=da.next();!S.done;S= -da.next()){var R=S.value;Y[Number(R)]=N[R]}if(Y.length){var M=Ge(10,3),ia;if(Y.length===0)ia=De(0);else{for(var ea=[],la=0,Ba=!1,Ma=0;Ma=0;d--)e=a.charCodeAt(d),b=(b<<6&268435455)+e+(e<<14),c=b&266338304,b=c!==0?b^c>>21:b;return b};function Oo(a){return a.origin!=="null"};function Po(a,b,c,d){var e;if(Qo(d)){for(var f=[],g=String(b||Ro()).split(";"),k=0;k=0} -function Wo(a,b,c,d){function e(w,x,y){if(y==null)return delete k[x],w;k[x]=y;return w+"; "+x+"="+y}function f(w,x){if(x==null)return w;k[x]=!0;return w+"; "+x}if(!Qo(c.Eb))return 2;var g;b==null?g=a+"=deleted; expires="+(new Date(0)).toUTCString():(c.encode&&(b=encodeURIComponent(b)),b=Xo(b),g=a+"="+b);var k={};g=e(g,"path",c.path);var m;c.expires instanceof Date?m=c.expires.toUTCString():c.expires!=null&&(m=""+c.expires);g=e(g,"expires",m);g=e(g,"max-age",c.Fm);g=e(g,"samesite",c.dn);c.secure&& -(g=f(g,"secure"));var n=c.domain;if(n&&n.toLowerCase()==="auto"){for(var p=Yo(),q=void 0,r=!1,t=0;t0?d:e}function To(a,b,c){for(var d=[],e=Po(a,void 0,void 0,c),f=0;f1200&&(a=a.substring(0,1200));return a} -var ap=/^(www\.)?google(\.com?)?(\.[a-z]{2})?$/,bp=/(^|\.)doubleclick\.net$/i;function Zo(a,b){return a!==void 0&&(bp.test(window.document.location.hostname)||b==="/"&&ap.test(a))}function cp(a){if(!a)return 1;var b=a;kb(9)&&a==="none"&&(b=window.document.location.hostname);b=b.indexOf(".")===0?b.substring(1):b;return b.split(".").length}function dp(a){if(!a||a==="/")return 1;a[0]!=="/"&&(a="/"+a);a[a.length-1]!=="/"&&(a+="/");return a.split("/").length-1} -function ep(a,b){var c=""+cp(a),d=dp(b);d>1&&(c+="-"+d);return c} -var Ro=function(){return Oo(window)?window.document.cookie:""},Qo=function(a){return a&&kb(10)?(Array.isArray(a)?a:[a]).every(function(b){return $k(b)&&Xk(b)}):!0},Yo=function(){var a=[],b=window.document.location.hostname.split(".");if(b.length===4){var c=b[b.length-1];if(Number(c).toString()===c)return["none"]}for(var d=b.length-2;d>=0;d--)a.push(b.slice(d).join("."));var e=window.document.location.hostname;bp.test(e)||ap.test(e)||a.push("none");return a};function fp(a){var b=Math.round(Math.random()*2147483647);return a?String(b^No(a)&2147483647):String(b)}function gp(a){return[fp(a),Math.round(zb()/1E3)].join(".")}function hp(a,b,c,d,e){var f=cp(b);return So(a,f,dp(c),d,e)}function ip(a,b,c,d){return[b,ep(c,d),a].join(".")};function jp(a,b,c,d){var e,f=Number(a.Db!=null?a.Db:void 0);f!==0&&(e=new Date((b||zb())+1E3*(f||7776E3)));return{path:a.path,domain:a.domain,flags:a.flags,encode:!!c,expires:e,Eb:d}};var kp;function lp(){function a(g){c(g.target||g.srcElement||{})}function b(g){d(g.target||g.srcElement||{})}var c=mp,d=np,e=op();if(!e.init){Cc(E,"mousedown",a);Cc(E,"keyup",a);Cc(E,"submit",b);var f=HTMLFormElement.prototype.submit;HTMLFormElement.prototype.submit=function(){d(this);f.call(this)};e.init=!0}}function pp(a,b,c,d,e){var f={callback:a,domains:b,fragment:c===2,placement:c,forms:d,sameHost:e};op().decorators.push(f)} -function qp(a,b,c){for(var d=op().decorators,e={},f=0;f=0||p&&m[q].indexOf(n)>=0){k=!0;break a}k=!1}if(k){var r=g.placement;r===void 0&&(r=g.fragment?2:1);r===b&&Cb(e,g.callback())}}return e} -function op(){var a=sc("google_tag_data",{}),b=a.gl;b&&b.decorators||(b={decorators:[]},a.gl=b);return b};var rp=/(.*?)\*(.*?)\*(.*)/,sp=/^https?:\/\/([^\/]*?)\.?cdn\.ampproject\.org\/?(.*)/,tp=/^(?:www\.|m\.|amp\.)+/,up=/([^?#]+)(\?[^#]*)?(#.*)?/;function vp(a){var b=up.exec(a);if(b)return{Xh:b[1],query:b[2],fragment:b[3]}}function wp(a){return new RegExp("(.*?)(^|&)"+a+"=([^&]*)&?(.*)")} -function xp(a,b){var c=[oc.userAgent,(new Date).getTimezoneOffset(),oc.userLanguage||oc.language,Math.floor(zb()/60/1E3)-(b===void 0?0:b),a].join("*"),d;if(!(d=kp)){for(var e=Array(256),f=0;f<256;f++){for(var g=f,k=0;k<8;k++)g=g&1?g>>>1^3988292384:g>>>1;e[f]=g}d=e}kp=d;for(var m=4294967295,n=0;n>>8^kp[(m^c.charCodeAt(n))&255];return((m^-1)>>>0).toString(36)} -function yp(a){return function(b){var c=Aj(C.location.href),d=c.search.replace("?",""),e=tj(d,"_gl",!1,!0)||"";b.query=zp(e)||{};var f=uj(c,"fragment"),g;var k=-1;if(Eb(f,"_gl="))k=4;else{var m=f.indexOf("&_gl=");m>0&&(k=m+3+2)}if(k<0)g=void 0;else{var n=f.indexOf("&",k);g=n<0?f.substring(k):f.substring(k,n)}b.fragment=zp(g||"")||{};a&&Ap(c,d,f)}}function Bp(a,b){var c=wp(a).exec(b),d=b;if(c){var e=c[2],f=c[4];d=c[1];f&&(d=d+e+f)}return d} -function Ap(a,b,c){function d(g,k){var m=Bp("_gl",g);m.length&&(m=k+m);return m}if(nc&&nc.replaceState){var e=wp("_gl");if(e.test(b)||e.test(c)){var f=uj(a,"path");b=d(b,"?");c=d(c,"#");nc.replaceState({},"",""+f+b+c)}}}function Cp(a,b){var c=yp(!!b),d=op();d.data||(d.data={query:{},fragment:{}},c(d.data));var e={},f=d.data;f&&(Cb(e,f.query),a&&Cb(e,f.fragment));return e} -var zp=function(a){try{var b=Dp(a,3);if(b!==void 0){for(var c={},d=b?b.split("*"):[],e=0;e+10;){if(c.href&&c.nodeName.match(/^a(?:rea)?$/i)){b=c;break a}c=c.parentNode;d--}b=null}var e=b;if(e){var f=e.protocol;f!=="http:"&&f!=="https:"||Fp(e,e.hostname)}}catch(g){}}function np(a){try{if(a.action){var b=uj(Aj(a.action),"host");Fp(a,b)}}catch(c){}}function Jp(a,b,c,d){lp();var e=c==="fragment"?2:1;d=!!d;pp(a,b,e,d,!1);e===2&&fb("TAGGING",23);d&&fb("TAGGING",24)}function Kp(a,b){lp();pp(a,[wj(C.location,"host",!0)],b,!0,!0)} -function Lp(){var a=E.location.hostname,b=sp.exec(E.referrer);if(!b)return!1;var c=b[2],d=b[1],e="";if(c){var f=c.split("/"),g=f[1];e=g==="s"?decodeURIComponent(f[2]):decodeURIComponent(g)}else if(d){if(d.indexOf("xn--")===0)return!1;e=d.replace(/-/g,".").replace(/\.\./g,"-")}var k=a.replace(tp,""),m=e.replace(tp,"");return k===m||Fb(k,"."+m)}function Mp(a,b){return a===!1?!1:a||b||Lp()};var Np=["1"],Op={},Pp={};function Qp(a,b){b=b===void 0?!0:b;var c=Rp(a.prefix);if(!Op[c])if(Sp(c,a.path,a.domain)){var d=Pp[Rp(a.prefix)];Tp(a,d?d.id:void 0,d?d.Sh:void 0)}else{var e=Cj("auiddc");if(e)fb("TAGGING",17),Op[c]=e;else if(b){var f=Rp(a.prefix),g=gp();Up(f,g,a);Sp(c,a.path,a.domain)}}}function Tp(a,b,c){var d=Rp(a.prefix),e=Op[d];if(e){var f=e.split(".");if(f.length===2){var g=Number(f[1])||0;if(g){var k=e;b&&(k=e+"."+b+"."+(c?c:Math.floor(zb()/1E3)));Up(d,k,a,g*1E3)}}}} -function Up(a,b,c,d){var e=ip(b,"1",c.domain,c.path),f=jp(c,d);f.Eb=Vp();$o(a,e,f)}function Sp(a,b,c){var d=hp(a,b,c,Np,Vp());if(!d)return!1;Wp(a,d);return!0}function Wp(a,b){var c=b.split(".");c.length===5?(Op[a]=c.slice(0,2).join("."),Pp[a]={id:c.slice(2,4).join("."),Sh:Number(c[4])||0}):c.length===3?Pp[a]={id:c.slice(0,2).join("."),Sh:Number(c[2])||0}:Op[a]=b}function Rp(a){return(a||"_gcl")+"_au"}function Xp(a){function b(){Xk(c)&&a()}var c=Vp();dl(function(){b();Xk(c)||el(b,c)},c)} -function Yp(a){var b=Cp(!0),c=Rp(a.prefix);Xp(function(){var d=b[c];if(d){Wp(c,d);var e=Number(Op[c].split(".")[1])*1E3;if(e){fb("TAGGING",16);var f=jp(a,e);f.Eb=Vp();var g=ip(d,"1",a.domain,a.path);$o(c,g,f)}}})}function Zp(a,b,c,d,e){e=e||{};var f=function(){var g={},k=hp(a,e.path,e.domain,Np,Vp());k&&(g[a]=k);return g};Xp(function(){Jp(f,b,c,d)})}function Vp(){return["ad_storage","ad_user_data"]};var $p={},aq=($p.k={Ga:/^[\w-]+$/},$p.b={Ga:/^[\w-]+$/,fi:!0},$p.i={Ga:/^[1-9]\d*$/},$p.u={Ga:/^[1-9]\d*$/},$p);var bq={},eq=(bq[5]={Ak:{2:cq},th:["k","i","b","u"]},bq[4]={Ak:{2:cq,GCL:dq},th:["k","i","b"]},bq);function fq(a){var b=eq[5];if(b){var c=a.split(".")[0];if(c){var d=b.Ak[c];if(d)return d(a,5)}}} -function cq(a,b){var c=a.split(".");if(c.length===3){var d={},e=eq[b];if(e){for(var f=e.th,g=h(c[2].split("$")),k=g.next();!k.done;k=g.next()){var m=k.value,n=m[0];if(f.indexOf(n)!==-1)try{var p=decodeURIComponent(m.substring(1)),q=aq[n];q&&(q.fi?(d[n]=d[n]||[],d[n].push(p)):d[n]=p)}catch(r){}}return d}}} -function gq(a,b){var c=eq[5];if(c){for(var d=[],e=h(c.th),f=e.next();!f.done;f=e.next()){var g=f.value,k=aq[g];if(k){var m=a[g];if(m!==void 0)if(k.fi&&Array.isArray(m))for(var n=h(m),p=n.next();!p.done;p=n.next())d.push(encodeURIComponent(""+g+p.value));else d.push(encodeURIComponent(""+g+m))}}return["2",b||"1",d.join("$")].join(".")}}function dq(a){var b=a.split(".");b.shift();var c=b.shift(),d=b.shift(),e={};return e.k=d,e.i=c,e.b=b,e};var hq=new Map([[5,"ad_storage"],[4,["ad_storage","ad_user_data"]]]);function iq(a){if(eq[5]){for(var b=[],c=Po(a,void 0,void 0,hq.get(5)),d=h(c),e=d.next();!e.done;e=d.next()){var f=fq(e.value);f&&(jq(f),b.push(f))}return b}}function kq(a,b,c,d){c=c||{};var e=ep(c.domain,c.path),f=gq(b,e);if(f){var g=jp(c,d,void 0,hq.get(5));$o(a,f,g)}}function lq(a,b){var c=b.Ga;return typeof c==="function"?c(a):c.test(a)} -function jq(a){for(var b=h(Object.keys(a)),c=b.next(),d={};!c.done;d={De:void 0},c=b.next()){var e=c.value,f=a[e];d.De=aq[e];d.De?d.De.fi?a[e]=Array.isArray(f)?f.filter(function(g){return function(k){return lq(k,g.De)}}(d)):void 0:typeof f==="string"&&lq(f,d.De)||(a[e]=void 0):a[e]=void 0}};function mq(a){for(var b=[],c=E.cookie.split(";"),d=new RegExp("^\\s*"+(a||"_gac")+"_(UA-\\d+-\\d+)=\\s*(.+?)\\s*$"),e=0;e3&&(g.labels=f.slice(3));d[c[e].ki].push(g)}}return d};var oq=["ad_storage","ad_user_data"];function pq(){var a=qq();if(a.error)return a;if(!a.value)return{error:2};var b;try{b=a.value.gclid}catch(c){return{error:11}}return b?{value:b}:{value:void 0}} -function qq(){if(!Xk(oq))return{error:3};try{if(!C.localStorage)return{error:1}}catch(d){return{error:14}}var a={schema:"gcl",version:1},b=void 0;try{b=C.localStorage.getItem("_gcl_ls")}catch(d){return{error:13}}try{if(b){var c=JSON.parse(b);if(c&&typeof c==="object")a=c;else return{error:12}}}catch(d){return{error:8}}if(a.schema!=="gcl")return{error:4};if(a.version!==1)return{error:5};try{rq(a)}catch(d){return{error:8}}return{value:a,error:0}} -function rq(a){if(a&&typeof a==="object")if("expires"in a&&"value"in a){var b;typeof a.expires==="number"?b=a.expires:b=typeof a.expires==="string"?Number(a.expires):NaN;!isNaN(b)&&Date.now()<=b||(a.value=null,a.error=9)}else for(var c=h(Object.keys(a)),d=c.next();!d.done;d=c.next())rq(a[d.value])};var sq=/^\w+$/,tq=/^[\w-]+$/,uq={},vq=(uq.aw="_aw",uq.dc="_dc",uq.gf="_gf",uq.gp="_gp",uq.gs="_gs",uq.ha="_ha",uq.ag="_ag",uq.gb="_gb",uq);function wq(){return["ad_storage","ad_user_data"]}function xq(a){return!kb(10)||Xk(a)}function yq(a,b){function c(){var d=xq(b);d&&a();return d}dl(function(){c()||el(c,b)},b)}function zq(a){return Aq(a).map(function(b){return b.T})}function Bq(a){return Cq(a).filter(function(b){return b.T}).map(function(b){return b.T})} -function Cq(a){var b=Dq(a.prefix),c=Eq("gb",b),d=Eq("ag",b);if(!d||!c)return[];var e=function(k){return function(m){m.type=k;return m}},f=Aq(c).map(e("gb")),g=(kb(7)?Fq(d):[]).map(e("ag"));return f.concat(g).sort(function(k,m){return m.timestamp-k.timestamp})}function Gq(a,b,c,d,e,f){var g=pb(a,function(k){return k.T===c});g?(g.timestamp0&&T.push(e.join("."));return T.join(".")},u=h(["aw","dc","gf","ha","gp"]),w=u.next();!w.done;w=u.next()){var x=w.value;a[x]&&t(x,v(a[x][0]))}if(!n&&a.gb){var y=a.gb[0],A=Eq("gb",f);!b&&Aq(A).some(function(H){return H.T===y&&H.labels&&H.labels.length> -0})||t("gb",v(y))}}if(!p&&kb(7)&&a.gbraid&&xq("ad_storage")&&(p=!0,!n)){var B=a.gbraid,D=Eq("ag",f);if(b||!(kb(7)?Fq(D):[]).some(function(H){return H.T===B&&H.labels&&H.labels.length>0})){var I={},J=(I.k=B,I.i=""+k,I.b=e,I);kq(D,J,c,g)}}Wq(a,f,g,c)};dl(function(){q();xq(m)||el(q,m)},m)} -function Wq(a,b,c,d){if(a.gad_source!==void 0&&xq("ad_storage")){var e=a.gad_source,f=Eq("gs",b);if(f){var g=Math.round((zb()-(Oc()||0))/1E3),k;if(kb(11)){var m,n=String,p=C.location.hostname,q=C.location.pathname,r=p=Dj(p);r.split(".").length>2&&(r=r.replace(/^(www[0-9]*|web|ftp|wap|home|m|w|amp|mobile)\./,""));p=r;q=Dj(q);var t=q.split(";")[0];t=t.replace(/\/(ar|slp|web|index)?\/?$/,"");m=n(No((""+p+t).toLowerCase()));var v={};k=(v.k=e,v.i=""+g,v.u=m,v)}else{var u={};k=(u.k=e,u.i=""+g,u)}kq(f,k, -d,c)}}}function Xq(a,b){var c=Cp(!0);yq(function(){for(var d=Dq(b.prefix),e=0;ep){n=!0;break b}n=!1}if(!n){var t=jp(b,m,!0);t.Eb=wq();$o(g,k,t)}}}}Uq(Rq(c.gclid,c.gclsrc),!1,b)},wq())} -function Zq(a){var b=[];kb(7)&&b.push("ag");if(b.length!==0){var c=Cp(!0),d=Dq(a.prefix);yq(function(){for(var e=0;ep){n=!0;break a}n=!1}if(n)break;k.i=""+Math.round(m/1E3);kq(f,k,a,m)}}}}},["ad_storage"])}}function Eq(a,b){var c=vq[a];if(c!==void 0)return b+c} -function Yq(a){return $q(a.split(".")).length!==0?(Number(a.split(".")[1])||0)*1E3:0}function Iq(a){return a?(Number(a.i)||0)*1E3:0}function Jq(a){var b=$q(a.split("."));return b.length===0?null:{version:b[0],T:b[2],timestamp:(Number(b[1])||0)*1E3,labels:b.slice(3)}}function $q(a){return a.length<3||a[0]!=="GCL"&&a[0]!=="1"||!/^\d+$/.test(a[1])||!tq.test(a[2])?[]:a} -function ar(a,b,c,d,e){if(Array.isArray(b)&&Oo(C)){var f=Dq(e),g=function(){for(var k={},m=0;mc}; -var or=function(a,b){var c=Hi.ads_pageview=Hi.ads_pageview||{};if(c[a])return!1;(b===void 0?0:b)||(c[a]=!0);return!0},wr=function(a,b,c,d,e){var f=Dq(a.prefix);if(or(f,!0)){var g=Sq(),k=[],m=g.gclid,n=g.dclid,p=g.gclsrc||"aw",q=pr(),r=q.Ke,t=q.Uj;!m||p!=="aw.ds"&&p!=="aw"&&p!=="ds"&&p!=="3p.ds"||k.push({T:m,Le:p});n&&k.push({T:n,Le:"ds"});k.length===2&&U(147);k.length===0&&g.wbraid&&k.push({T:g.wbraid,Le:"gb"});k.length===0&&p==="aw.ds"&&k.push({T:"",Le:"aw.ds"});qr(function(){var v=W(rr());if(v){Qp(a); -var u=[],w=v?Op[Rp(a.prefix)]:void 0;w&&u.push("auid="+w);if(W(O.g.N)){e&&u.push("userId="+e);var x=Nl(Il.mh);if(x===void 0)Ml(Il.nh,!0);else{var y=Nl(Il.we);u.push("ga_uid="+y+"."+x)}}var A=E.referrer?uj(Aj(E.referrer),"host"):"",B=v||!d?k:[];B.length===0&&(sr.test(A)||tr.test(A))&&B.push({T:"",Le:""});if(B.length!==0||r!==void 0){A&&u.push("ref="+encodeURIComponent(A));var D=ur();u.push("url="+encodeURIComponent(D));u.push("tft="+zb());var I=Oc();I!==void 0&&u.push("tfd="+Math.round(I));var J=Ln(!0); -u.push("frm="+J);r!==void 0&&u.push("gad_source="+encodeURIComponent(r));t!==void 0&&u.push("gad_source_src="+encodeURIComponent(t.toString()));if(!c){var H={};c=Bm(rm(new qm(0),(H[O.g.ja]=Wm.j[O.g.ja],H)))}u.push("gtm="+Mo({ra:b}));zo()&&u.push("gcs="+Ao());u.push("gcd="+Eo(c));Ho()&&u.push("dma_cps="+Fo());u.push("dma="+Go());yo(c)?u.push("npa=0"):u.push("npa=1");Jo()&&u.push("_ng=1");Vn(lo())&&u.push("tcfd="+Io());var T=so();T&&u.push("gdpr="+T);var N=ro();N&&u.push("gdpr_consent="+N);Q(17)&&u.push("apve="+ -(Q(18)?1:0));Q(91)&&Cp(!1)._up&&u.push("gtm_up=1");$i.j&&u.push("tag_exp="+$i.j);if(B.length>0)for(var Y=0;Y0)return f?["0"]:g}var k=Eq(a,e);return k?zq(k):[]},qr=function(a){var b=rr();Dl(function(){a();W(b)||el(a,b)},b)},rr=function(){return[O.g.O,O.g.N]},sr=/^(?:www\.)?google(?:\.com?)?(?:\.[a-z]{2}t?)?$/, -tr=/^www\.googleadservices\.com$/,xr=/^gad_source[_=](\d+)$/;function Cr(){Hi.dedupe_gclid||(Hi.dedupe_gclid=gp());return Hi.dedupe_gclid};var Dr=/^(www\.)?google(\.com?)?(\.[a-z]{2}t?)?$/,Er=/^www.googleadservices.com$/;function Fr(a){a||(a=Gr());return a.tn?!1:a.im||a.jm||a.mm||a.km||a.Ke||a.Ul||a.lm||a.Yl?!0:!1}function Gr(){var a={},b=Cp(!0);a.tn=!!b._up;var c=Sq();a.im=c.aw!==void 0;a.jm=c.dc!==void 0;a.mm=c.wbraid!==void 0;a.km=c.gbraid!==void 0;a.lm=c.gclsrc==="aw.ds";a.Ke=pr().Ke;var d=E.referrer?uj(Aj(E.referrer),"host"):"";a.Yl=Dr.test(d);a.Ul=Er.test(d);return a};var Hr=RegExp("^UA-\\d+-\\d+%3A[\\w-]+(?:%2C[\\w-]+)*(?:%3BUA-\\d+-\\d+%3A[\\w-]+(?:%2C[\\w-]+)*)*$"),Ir=/^~?[\w-]+(?:\.~?[\w-]+)*$/,Jr=/^\d+\.fls\.doubleclick\.net$/,Kr=/;gac=([^;?]+)/,Lr=/;gacgb=([^;?]+)/; -function Mr(a,b){if(Jr.test(E.location.host)){var c=E.location.href.match(b);return c&&c.length===2&&c[1].match(Hr)?decodeURIComponent(c[1]):""}for(var d=[],e=h(Object.keys(a)),f=e.next();!f.done;f=e.next()){for(var g=f.value,k=[],m=a[g],n=0;n0?d.join(";"):""} -function Nr(a,b,c){for(var d=xq(wq())?nq("_gac_gb",!0):{},e=[],f=!1,g=h(Object.keys(d)),k=g.next();!k.done;k=g.next()){var m=k.value,n=jr("_gac_gb_"+m,a,b,c);f=f||n.length!==0&&n.some(function(p){return p===1});e.push(m+":"+n.join(","))}return{Tl:f?e.join(";"):"",Sl:Mr(d,Lr)}}function Or(a){var b=E.location.href.match(new RegExp(";"+a+"=([^;?]+)"));return b&&b.length===2&&b[1].match(Ir)?b[1]:void 0} -function Pr(a){var b=kb(11),c={},d,e,f;Jr.test(E.location.host)&&(d=Or("gclgs"),e=Or("gclst"),b&&(f=Or("gcllp")));if(d&&e&&(!b||f))c.Eh=d,c.Gh=e,c.Fh=f;else{var g=zb(),k=Fq((a||"_gcl")+"_gs"),m=k.map(function(q){return q.T}),n=k.map(function(q){return g-q.timestamp}),p=[];b&&(p=k.map(function(q){return q.Cd}));m.length>0&&n.length>0&&(!b||p.length>0)&&(c.Eh=m.join("."),c.Gh=n.join("."),b&&p.length>0&&(c.Fh=p.join(".")))}return c} -function Qr(a,b,c,d){d=d===void 0?!1:d;if(Jr.test(E.location.host)){var e=Or(c);if(e)return[{T:e}]}else{if(b==="gclid"){var f=(a||"_gcl")+"_aw";return d?Oq(f):Aq(f)}if(b==="wbraid")return Aq((a||"_gcl")+"_gb");if(b==="braids")return Cq({prefix:a})}return[]}function Rr(a){return Qr(a,"gclid","gclaw").map(function(b){return b.T}).join(".")} -function Sr(a){var b=Qr(a,"gclid","gclaw",!0),c=b.map(function(f){return f.T}).join("."),d=b.map(function(f){return f.Ma||0}).join("."),e=b.map(function(f){for(var g=0,k=h(f.Nc||[]),m=k.next();!m.done;m=k.next()){var n=m.value;n===1&&(g|=1);n===2&&(g|=2)}return g.toString()}).join(".");return{T:c,Vj:d,Wj:e}}function Tr(a){return Qr(a,"wbraid","gclgb").map(function(b){return b.T}).join(".")}function Ur(a){return Qr(a,"braids","gclgb").map(function(b){return b.T}).join(".")} -function Vr(a,b){return Jr.test(E.location.host)?!(Or("gclaw")||Or("gac")):nr(a,b)}function Wr(a,b,c){var d;d=c?kr(a,b):jr((b&&b.prefix||"_gcl")+"_gb",a,b);return d.length===0||d.every(function(e){return e===0})?"":d.join(".")};function Xr(){var a=C.__uspapi;if(mb(a)){var b="";try{a("getUSPData",1,function(c,d){if(d&&c){var e=c.uspString;e&&RegExp("^[\\da-zA-Z-]{1,20}$").test(e)&&(b=e)}})}catch(c){}return b}}; -var as=function(a){if(a.eventName===O.g.aa&&a.metadata.hit_type==="page_view")if(Q(18)){a.metadata.redact_click_ids=V(a.m,O.g.fa)!=null&&V(a.m,O.g.fa)!==!1&&!W([O.g.O,O.g.N]);var b=Yr(a),c=V(a.m,O.g.na)!==!1;c||(a.j[O.g.Qi]="1");var d=Dq(b.prefix),e=a.metadata.is_server_side_destination;if(!a.metadata.consent_updated&&!a.metadata.user_id_updated){var f=V(a.m,O.g.Za),g=V(a.m,O.g.oa)||{};Zr({vd:c,Dd:g,Hd:f,mc:b});if(!e&&!or(d)){a.isAborted=!0;return}}if(e)a.isAborted=!0;else{a.j[O.g.xc]=O.g.Wb;if(a.metadata.consent_updated)a.j[O.g.xc]= -O.g.Fk,a.j[O.g.Ub]="1";else if(a.metadata.user_id_updated)a.j[O.g.xc]=O.g.Kk;else{var k=Sq();a.j[O.g.Ld]=k.gclid;a.j[O.g.Td]=k.dclid;a.j[O.g.Li]=k.gclsrc;a.j[O.g.Ld]||a.j[O.g.Td]||(a.j[O.g.rf]=k.wbraid,a.j[O.g.ug]=k.gbraid);a.j[O.g.Aa]=E.referrer?uj(Aj(E.referrer),"host"):"";a.j[O.g.qa]=ur();Q(22)&&(a.j[O.g.hb]=$r());if(Q(21)&&qc&&qc.src){var m=uj(Aj(qc.src),"host");m&&(a.j[O.g.ij]=m)}var n=pr(),p=n.Uj;a.j[O.g.Ji]=n.Ke;a.j[O.g.Ki]=p;a.j[O.g.Kb]=Ln(!0);var q=Gr();Fr(q)&&(a.j[O.g.gd]="1");a.j[O.g.Ni]= -Cr();Cp(!1)._up==="1"&&(a.j[O.g.cj]="1")}gl=!0;var r=W([O.g.O,O.g.N]);c&&r&&(Qp(b),a.j[O.g.Ib]=Op[Rp(b.prefix)]);a.j[O.g.qb]=void 0;a.j[O.g.Xa]=void 0;var t=Q(74);if(!a.j[O.g.Ld]&&!a.j[O.g.Td]&&Vr(d,t)){var v=t?Bq(b):zq(d+"_gb");v.length>0&&(a.j[O.g.qb]=v.join("."))}else if(!a.j[O.g.rf]&&r){var u=zq(d+"_aw");u.length>0&&(a.j[O.g.Xa]=u.join("."))}a.m.isGtmEvent&&(a.m.j[O.g.ja]=Wm.j[O.g.ja]);yo(a.m)?a.j[O.g.Qb]=!1:a.j[O.g.Qb]=!0;a.metadata.add_tag_timing=!0;var w=Xr();w!==void 0&&(a.j[O.g.pd]=w||"error"); -var x=so();x&&(a.j[O.g.ac]=x);var y=ro();y&&(a.j[O.g.hc]=y);a.metadata.speculative=!1}}else a.isAborted=!0},Yr=function(a){var b={prefix:V(a.m,O.g.cb)||V(a.m,O.g.Ia),domain:V(a.m,O.g.Pa),Db:V(a.m,O.g.Qa),flags:V(a.m,O.g.Ya)};a.m.isGtmEvent&&(b.path=V(a.m,O.g.ub));return b},bs=function(a,b){var c,d,e,f,g,k,m,n;c=a.vd;d=a.Dd;e=a.Hd;f=a.ra;g=a.m;k=a.Ed;m=a.Tn;n=a.wk;Zr({vd:c,Dd:d,Hd:e,mc:b});c&&m!==!0&&(n!=null?n=String(n):n=void 0,wr(b,f,g,k,n))},Zr=function(a){var b,c,d,e;b=a.vd;c=a.Dd;d=a.Hd;e=a.mc; -b&&(Mp(c[O.g.Cc],!!c[O.g.W])&&(Xq(cs,e),Zq(e),Yp(e)),Q(83)?Vq(e):Tq(e),cr(cs,e),dr(e));c[O.g.W]&&(ar(cs,c[O.g.W],c[O.g.Mb],!!c[O.g.xb],e.prefix),br(c[O.g.W],c[O.g.Mb],!!c[O.g.xb],e.prefix),Zp(Rp(e.prefix),c[O.g.W],c[O.g.Mb],!!c[O.g.xb],e),Zp("FPAU",c[O.g.W],c[O.g.Mb],!!c[O.g.xb],e));d&&fr(ds);hr(ds)},es=function(a,b,c,d){var e,f,g;e=a.xk;f=a.callback;g=a.bk;if(typeof f==="function")if(e===O.g.Xa&&g===void 0){var k=d(b.prefix,c);k.length===0?f(void 0):k.length===1?f(k[0]):f(k)}else e===O.g.Ib?(U(65), -Qp(b,!1),f(Op[Rp(b.prefix)])):f(g)},cs=["aw","dc","gb"],ds=["aw","dc","gb","ag"];function fs(a){var b=V(a.m,O.g.Lb),c=V(a.m,O.g.bc);b&&!c?(a.eventName!==O.g.aa&&a.eventName!==O.g.Pc&&U(131),a.isAborted=!0):!b&&c&&(U(132),a.isAborted=!0)}function gs(a){var b=W(O.g.O)?Hi.pscdl:"denied";b!=null&&(a.j[O.g.wf]=b)}function hs(a){var b=Ln(!0);a.j[O.g.Kb]=b}function is(a){Jo()&&(a.j[O.g.Ac]=1)} -function $r(){var a=E.title;if(a===void 0||a==="")return"";var b=function(d){try{return decodeURIComponent(d),!0}catch(e){return!1}};a=encodeURIComponent(a);for(var c=256;c>0&&!b(a.substring(0,c));)c--;return decodeURIComponent(a.substring(0,c))}function js(a){ks(a,"ce",V(a.m,O.g.Qa))}function ks(a,b,c){a.j[O.g.rd]||(a.j[O.g.rd]={});a.j[O.g.rd][b]=c};function qs(a,b,c,d){var e=yc(),f;if(e===1)a:{var g=Ti;g=g.toLowerCase();for(var k="https://"+g,m="http://"+g,n=1,p=E.getElementsByTagName("script"),q=0;q=0&&(g=g.substring(k+8,g.indexOf(")",k)),g.charAt(g.length-1)==="%"&&(g=g.substring(0,g.length-1)),f=String(Math.min(Number(g),Number(f))))}if(f!==void 0&&Number(f)<=0)return!0;(d=d.parentElement)&& -(e=C.getComputedStyle(d,null))}return!1} -var Qs=function(a){var b=Ps(),c=b.height,d=b.width,e=a.getBoundingClientRect(),f=e.bottom-e.top,g=e.right-e.left;return f&&g?(1-Math.min((Math.max(0-e.left,0)+Math.max(e.right-d,0))/g,1))*(1-Math.min((Math.max(0-e.top,0)+Math.max(e.bottom-c,0))/f,1)):0},Ps=function(){var a=E.body,b=E.documentElement||a&&a.parentElement,c,d;if(E.compatMode&&E.compatMode!=="BackCompat")c=b?b.clientHeight:0,d=b?b.clientWidth:0;else{var e=function(f,g){return f&&g?Math.min(f,g):Math.max(f,g)};c=e(b?b.clientHeight:0,a? -a.clientHeight:0);d=e(b?b.clientWidth:0,a?a.clientWidth:0)}return{width:d,height:c}};var Ts=function(a){if(Rs){if(a>=0&&a1?c[d]=1:c[d]<0&&(c[d]=0);if(Rs){var e=!1;F(function(){e||Us(a,b,c)()});return Vs(function(f){e=!0;for(var g={Pe:0};g.Pe0,rootBounds:n,target:k,time:zb()};F(function(){a(p)})}for(var e=[],f=[],g=0;ge[k])for(;f[k]=c[f[k]+1];)d(b[k],m),f[k]++; -else if(m=0&&m<=c[f[k]];)d(b[k],m),f[k]--;e[k]=m}}},Vs=function(a,b,c){for(var d=new C.IntersectionObserver(a,{threshold:c}),e=0;e10&&(e="3")}!a.ig&&g&&(f=[g]);for(var p=0;p:nth-child("+e.toString()+")"}else d="";c=d}b=c}return b},bt=function(a){for(var b=[],c=0;c=0}else k=!1;k||b.push({element:d,X:g})}}}return b}, -at=function(){var a=[],b=E.body;if(!b)return{elements:a,status:"4"};for(var c=b.querySelectorAll("*"),d=0;d=0)&&e.children instanceof HTMLCollection){for(var f=!1,g=0;g=0)){f=!0;break}(!f||Q(27)&&st.indexOf(e.tagName)!==-1)&&a.push(e)}}return{elements:a,status:c.length>1E4?"2":"1"}},tt=!1;var pt=/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i,Xs=/@(gmail|googlemail)\./i,ot=/support|noreply/i,qt="SCRIPT STYLE IMG SVG PATH BR NOSCRIPT TEXTAREA".split(" "),rt=["BR"],jt={oc:"1",te:"2",ne:"3",pe:"4",ng:"5",jh:"6",Vf:"7"},$s={},st=["INPUT","SELECT"];var Jt=function(a,b,c){a.j[O.g.ve]||(a.j[O.g.ve]={});a.j[O.g.ve][b]=c},Lt=function(a,b){var c=Kt(a,O.g.Zd,a.m.C[O.g.Zd]);if(c&&c[b||a.eventName]!==void 0)return c[b||a.eventName]},Mt=function(a){var b=a.metadata.user_data;if(Qa(b))return b},Nt=function(a){if(a.metadata.is_merchant_center||!Ij(a.m))return!1;if(!V(a.m,O.g.ld)){var b=V(a.m,O.g.yc);return b===!0||b==="true"}return!0},Ot=function(a){return Kt(a,O.g.Bc,V(a.m,O.g.Bc))||!!Kt(a,"google_ng",!1)};var Jf;var Pt=Number('')||5,Qt=Number('')||50,Rt=qb();var Wt={sl:Number('')||500,Yk:Number('')||5E3,xj:Number('20')||10,Ek:Number('')||5E3};function Xt(a){return a.performance&&a.performance.now()||Date.now()} -var Yt=function(a,b){var c;return c};var Zt;function fu(){var a=Mf(Jf.j,"",function(){return{}});try{return a("internal_sw_allowed"),!0}catch(b){return!1}} -function gu(a,b,c){c=c===void 0?!1:c;} -var hu=function(a,b,c,d){}; -function iu(a,b,c,d,e){} -function ju(a,b,c,d){}var ku=function(a){for(var b=[],c=0,d=0;d>6|192:((e&64512)==55296&&d+1>18|240,b[c++]=e>>12&63|128):b[c++]=e>>12|224,b[c++]=e>>6&63|128),b[c++]=e&63|128)}return b};yn();Bn()||vn("iPod");vn("iPad");!vn("Android")||zn()||yn()||xn()||vn("Silk");zn();!vn("Safari")||zn()||(wn()?0:vn("Coast"))||xn()||(wn()?0:vn("Edge"))||(wn()?un("Microsoft Edge"):vn("Edg/"))||(wn()?un("Opera"):vn("OPR"))||yn()||vn("Silk")||vn("Android")||Cn();var lu={},mu=null,nu=function(a){for(var b=[],c=0,d=0;d255&&(b[c++]=e&255,e>>=8);b[c++]=e}var f=4;f===void 0&&(f=0);if(!mu){mu={};for(var g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),k=["+/=","+/","-_=","-_.","-_"],m=0;m<5;m++){var n=g.concat(k[m].split(""));lu[m]=n;for(var p=0;p>2],D=r[(x&3)<<4|y>>4],I=r[(y&15)<<2|A>>6],J=r[A&63];t[w++]=""+B+D+I+J}var H=0,T=v;switch(b.length-u){case 2:H=b[u+1],T=r[(H&15)<<2]||v;case 1:var N=b[u];t[w]=""+r[N>>2]+r[(N&3)<<4|H>>4]+T+v}return t.join("")};var ou="platform platformVersion architecture model uaFullVersion bitness fullVersionList wow64".split(" ");function pu(a){var b;return(b=a.google_tag_data)!=null?b:a.google_tag_data={}}function qu(){var a=C.google_tag_data,b;if(a!=null&&a.uach){var c=a.uach,d=Object.assign({},c);c.fullVersionList&&(d.fullVersionList=c.fullVersionList.slice(0));b=d}else b=null;return b}function ru(){var a,b;return(b=(a=C.google_tag_data)==null?void 0:a.uach_promise)!=null?b:null} -function su(a){var b,c;return typeof((b=a.navigator)==null?void 0:(c=b.userAgentData)==null?void 0:c.getHighEntropyValues)==="function"}function tu(){var a=C;if(!su(a))return null;var b=pu(a);if(b.uach_promise)return b.uach_promise;var c=a.navigator.userAgentData.getHighEntropyValues(ou).then(function(d){b.uach!=null||(b.uach=d);return d});return b.uach_promise=c}; -var uu=function(a,b){a&&(b.j[O.g.Mf]=a.architecture,b.j[O.g.Nf]=a.bitness,a.fullVersionList&&(b.j[O.g.Of]=a.fullVersionList.map(function(c){return encodeURIComponent(c.brand||"")+";"+encodeURIComponent(c.version||"")}).join("|")),b.j[O.g.Pf]=a.mobile?"1":"0",b.j[O.g.Qf]=a.model,b.j[O.g.Rf]=a.platform,b.j[O.g.Sf]=a.platformVersion,b.j[O.g.Tf]=a.wow64?"1":"0")},wu=function(a){var b=vu.sn,c=function(g,k){try{a(g,k)}catch(m){}},d=qu();if(d)c(d);else{var e=ru();if(e){b=Math.min(Math.max(isFinite(b)?b: -0,0),1E3);var f=C.setTimeout(function(){c.Se||(c.Se=!0,U(106),c(null,Error("Timeout")))},b);e.then(function(g){c.Se||(c.Se=!0,U(104),C.clearTimeout(f),c(g))}).catch(function(g){c.Se||(c.Se=!0,U(105),C.clearTimeout(f),c(null,g))})}else c(null)}},yu=function(){if(su(C)&&(xu=zb(),!ru())){var a=tu();a&&(a.then(function(){U(95)}),a.catch(function(){U(96)}))}},xu;function zu(a){var b;b=b===void 0?document:b;var c;return!((c=b.featurePolicy)==null||!c.allowedFeatures().includes(a))};function Au(){return zu("join-ad-interest-group")&&mb(oc.joinAdInterestGroup)} -function Bu(a,b){var c=jb[3]===void 0?1:jb[3],d='iframe[data-tagging-id="'+b+'"]',e=[];try{if(c===1){var f=E.querySelector(d);f&&(e=[f])}else e=Array.from(E.querySelectorAll(d))}catch(q){}var g;a:{try{g=E.querySelectorAll('iframe[allow="join-ad-interest-group"][data-tagging-id*="-"]');break a}catch(q){}g=void 0}var k=g,m=((k==null?void 0:k.length)||0)>=(jb[2]===void 0?50:jb[2]),n;if(n=e.length>=1){var p=Number(e[e.length-1].dataset.loadTime);p!==void 0&&zb()-p<(jb[1]===void 0?6E4:jb[1])?(fb("TAGGING", -9),n=!0):n=!1}if(!n){if(c===1)if(e.length>=1)Cu(e[0]);else{if(m){fb("TAGGING",10);return}}else e.length>=c?Cu(e[0]):m&&Cu(k[0]);zc(a,void 0,{allow:"join-ad-interest-group"},{taggingId:b,loadTime:zb()})}}function Cu(a){try{a.parentNode.removeChild(a)}catch(b){}}function Du(){return"https://td.doubleclick.net"};function Eu(a){var b=a.location.href;if(a===a.top)return{url:b,ym:!0};var c=!1,d=a.document;d&&d.referrer&&(b=d.referrer,a.parent===a.top&&(c=!0));var e=a.location.ancestorOrigins;if(e){var f=e[e.length-1];f&&b.indexOf(f)===-1&&(c=!1,b=f)}return{url:b,ym:c}}; -var vv=function(a,b){var c={},d=function(f,g){var k;k=g===!0?"1":g===!1?"0":encodeURIComponent(String(g));c[f]=k};z(a.j,function(f,g){var k=uv[f];k&&g!==void 0&&g!==""&&(!a.metadata.redact_click_ids||f!==O.g.Ld&&f!==O.g.Td&&f!==O.g.rf&&f!==O.g.ug||(g="0"),d(k,g))});d("gtm",Mo({ra:a.metadata.source_canonical_id}));zo()&&d("gcs",Ao());d("gcd",Eo(a.m));Ho()&&d("dma_cps",Fo());d("dma",Go());Vn(lo())&&d("tcfd",Io());$i.j&&d("tag_exp",$i.j);if(a.metadata.add_tag_timing){d("tft",zb());var e=Oc();e!==void 0&& -d("tfd",Math.round(e))}Q(17)&&d("apve",Q(18)?"1":"0");Q(19)&&d("apvf",Mc()?Q(20)?"f":"sb":"nf");b(c)},wv=function(a){vv(a,function(b){if(a.metadata.hit_type==="page_view"){var c=[];z(b,function(e,f){c.push(e+"="+f)});var d=Jj(W([O.g.O,O.g.N])?"https://www.google.com":"https://pagead2.googlesyndication.com",!0)+"/ccm/collect?"+c.join("&");Q(19)&&Q(20)&&Mc()?Lc(d,void 0,{noFallback:!0}):Ic(d);if(mb(a.m.onSuccess))a.m.onSuccess()}})},xv={},uv=(xv[O.g.Ub]="gcu",xv[O.g.qb]="gclgb",xv[O.g.Xa]="gclaw",xv[O.g.Ji]= -"gad_source",xv[O.g.Ki]="gad_source_src",xv[O.g.Ld]="gclid",xv[O.g.Li]="gclsrc",xv[O.g.ug]="gbraid",xv[O.g.rf]="wbraid",xv[O.g.Ib]="auid",xv[O.g.Ni]="rnd",xv[O.g.Qi]="ncl",xv[O.g.xg]="gcldc",xv[O.g.Td]="dclid",xv[O.g.eb]="edid",xv[O.g.xc]="en",xv[O.g.ac]="gdpr",xv[O.g.fb]="gdid",xv[O.g.Ac]="_ng",xv[O.g.cj]="gtm_up",xv[O.g.Kb]="frm",xv[O.g.gd]="lps",xv[O.g.fe]="did",xv[O.g.qa]="dl",xv[O.g.Aa]="dr",xv[O.g.hb]="dt",xv[O.g.ij]="scrsrc",xv[O.g.Jf]="ga_uid",xv[O.g.hc]="gdpr_consent",xv[O.g.ya]="uid",xv[O.g.pd]= -"us_privacy",xv[O.g.Qb]="npa",xv);var yv={J:{mi:"ads_conversion_hit",Id:"container_execute_start",ri:"container_setup_end",kg:"container_setup_start",ni:"container_blocking_end",oi:"container_execute_end",si:"container_yield_end",lg:"container_yield_start",nj:"event_execute_end",mj:"event_evaluation_end",gh:"event_evaluation_start",oj:"event_setup_end",me:"event_setup_start",qj:"ga4_conversion_hit",se:"page_load",In:"pageview",jc:"snippet_load",Jj:"tag_callback_error",Kj:"tag_callback_failure",Lj:"tag_callback_success",Mj:"tag_execute_end", -sd:"tag_execute_start"}};function zv(){function a(c,d){var e=gb(d);e&&b.push([c,e])}var b=[];a("u","GTM");a("ut","TAGGING");a("h","HEALTH");return b};var Av=!1;function iw(a,b){} -function jw(a,b){}function kw(a,b){} -function lw(a,b){}function mw(){var a={};return a} -function aw(a){a=a===void 0?!0:a;var b={};return b} -function nw(){}function ow(a,b){} -function pw(a,b,c){} -function qw(){}function rw(a,b){var c=C,d,e=c.GooglebQhCsO;e||(e={},c.GooglebQhCsO=e);d=e;if(d[a])return!1;d[a]=[];d[a][0]=b;return!0};function sw(a,b,c,d){var e=Gn(a,"fmt");if(b){var f=Gn(a,"random"),g=Gn(a,"label")||"";if(!f)return!1;var k=nu(decodeURIComponent(g.replace(/\+/g," "))+":"+decodeURIComponent(f.replace(/\+/g," ")));if(!rw(k,b))return!1}e&&Number(e)!==4&&(a=In(a,"rfmt",e));var m=In(a,"fmt",4);xc(m,function(){C.google_noFurtherRedirects&&b&&(C.google_noFurtherRedirects=null,b())},c,d,E.getElementsByTagName("script")[0].parentElement||void 0);return!0};function Jw(a,b){if(data.entities){var c=data.entities[a];if(c)return c[b]}};function Kw(a,b,c){c=c===void 0?!1:c;Lw().addRestriction(0,a,b,c)}function Mw(a,b,c){c=c===void 0?!1:c;Lw().addRestriction(1,a,b,c)}function Nw(){var a=mk();return Lw().getRestrictions(1,a)}var Ow=function(){this.container={};this.j={}},Pw=function(a,b){var c=a.container[b];c||(c={_entity:{internal:[],external:[]},_event:{internal:[],external:[]}},a.container[b]=c);return c}; -Ow.prototype.addRestriction=function(a,b,c,d){d=d===void 0?!1:d;if(!d||!this.j[b]){var e=Pw(this,b);a===0?d?e._entity.external.push(c):e._entity.internal.push(c):a===1&&(d?e._event.external.push(c):e._event.internal.push(c))}}; -Ow.prototype.getRestrictions=function(a,b){var c=Pw(this,b);if(a===0){var d,e;return[].concat(oa((c==null?void 0:(d=c._entity)==null?void 0:d.internal)||[]),oa((c==null?void 0:(e=c._entity)==null?void 0:e.external)||[]))}if(a===1){var f,g;return[].concat(oa((c==null?void 0:(f=c._event)==null?void 0:f.internal)||[]),oa((c==null?void 0:(g=c._event)==null?void 0:g.external)||[]))}return[]}; -Ow.prototype.getExternalRestrictions=function(a,b){var c=Pw(this,b),d,e;return a===0?(c==null?void 0:(d=c._entity)==null?void 0:d.external)||[]:(c==null?void 0:(e=c._event)==null?void 0:e.external)||[]};Ow.prototype.removeExternalRestrictions=function(a){var b=Pw(this,a);b._event&&(b._event.external=[]);b._entity&&(b._entity.external=[]);this.j[a]=!0};function Lw(){var a=Hi.r;a||(a=new Ow,Hi.r=a);return a};var Qw=new RegExp(/^(.*\.)?(google|youtube|blogger|withgoogle)(\.com?)?(\.[a-z]{2})?\.?$/),Rw={cl:["ecl"],customPixels:["nonGooglePixels"],ecl:["cl"],ehl:["hl"],gaawc:["googtag"],hl:["ehl"],html:["customScripts","customPixels","nonGooglePixels","nonGoogleScripts","nonGoogleIframes"],customScripts:["html","customPixels","nonGooglePixels","nonGoogleScripts","nonGoogleIframes"],nonGooglePixels:[],nonGoogleScripts:["nonGooglePixels"],nonGoogleIframes:["nonGooglePixels"]},Sw={cl:["ecl"],customPixels:["customScripts", -"html"],ecl:["cl"],ehl:["hl"],gaawc:["googtag"],hl:["ehl"],html:["customScripts"],customScripts:["html"],nonGooglePixels:["customPixels","customScripts","html","nonGoogleScripts","nonGoogleIframes"],nonGoogleScripts:["customScripts","html"],nonGoogleIframes:["customScripts","html","nonGoogleScripts"]},Tw="google customPixels customScripts html nonGooglePixels nonGoogleScripts nonGoogleIframes".split(" "); -function Uw(){var a=hj("gtm.allowlist")||hj("gtm.whitelist");a&&U(9);Ni&&(a=["google","gtagfl","lcl","zone"]);Qw.test(C.location&&C.location.hostname)&&(Ni?U(116):(U(117),Vw&&(a=[],window.console&&window.console.log&&window.console.log("GTM blocked. See go/13687728."))));var b=a&&Db(wb(a),Rw),c=hj("gtm.blocklist")||hj("gtm.blacklist");c||(c=hj("tagTypeBlacklist"))&&U(3);c?U(8):c=[];Qw.test(C.location&&C.location.hostname)&&(c=wb(c),c.push("nonGooglePixels","nonGoogleScripts","sandboxedScripts")); -wb(c).indexOf("google")>=0&&U(2);var d=c&&Db(wb(c),Sw),e={};return function(f){var g=f&&f[He.la];if(!g||typeof g!=="string")return!0;g=g.replace(/^_*/,"");if(e[g]!==void 0)return e[g];var k=Xi[g]||[],m=!0;if(a){var n;if(n=m)a:{if(b.indexOf(g)<0)if(k&&k.length>0)for(var p=0;p=0;if(r)q=r;else{var t=rb(d,k||[]);t&&U(10);q=t}}var v=!m||q;v||!(k.indexOf("sandboxedScripts")>=0)||b&&b.indexOf("sandboxedScripts")!== --1||(v=rb(d,Tw));return e[g]=v}}var Vw=!1;Vw=!0;function Ww(){ek&&Kw(mk(),function(a){var b=tf(a.entityId),c;if(wf(b)){var d=b[He.la];if(!d)throw Error("Error: No function name given for function call.");var e=lf[d];c=!!e&&!!e.runInSiloedMode}else c=!!Jw(b[He.la],4);return c})}function Xw(a,b,c,d,e){if(!Yw()){var f=d.siloed?hk(a):a;if(!vk(f)){var g=Zw(a),k=Eb(a,"GTM-"),m=Hj(),n=c?"/gtag/js":"/gtm.js",p=Gj(b,n+g);if(!p){var q=Gi.lf+n;m&&rc&&k?(q=rc.replace(/^(?:https?:\/\/)?/i,"").split(/[?#]/)[0],p=qs("https://","http://",q+g)):p=bj()?aj()+"/"+g:qs("https://","http://",q+g)}d.siloed&&xk({ctid:f,isDestination:!1});var r=pk();ak().container[f]={state:1,context:d,parent:r};Zj({ctid:f,isDestination:!1},e);xc(p)}}} -function $w(a,b,c,d){if(!Yw()){var e=c.siloed?hk(a):a;if(!wk(e))if(!c.siloed&&yk())ak().destination[e]={state:0,transportUrl:b,context:c,parent:pk()},Zj({ctid:e,isDestination:!0},d),U(91);else{var f="/gtag/destination"+Zw(a,!0),g=Gj(b,f);g||(bj()?(f="/gtd"+Zw(a,!0),g=aj()+f):g=qs("https://","http://",Gi.lf+f));c.siloed&&xk({ctid:e,isDestination:!0});ak().destination[e]={state:1,context:c,parent:pk()};Zj({ctid:e,isDestination:!0},d);xc(g)}}} -function Zw(a,b){b=b===void 0?!1:b;var c="?id="+encodeURIComponent(a)+"&l="+Gi.nb;if(!Eb(a,"GTM-")||b)c+="&cx=c";Q(76)&&(c+=">m="+Mo());Hj()&&(c+="&sign="+Gi.lh);var d=$i.C;d===1?c+="&fps=fc":d===2&&(c+="&fps=fe");return c}function Yw(){if(Ko()){return!0}return!1};var ax=!1,bx=0,cx=[];function dx(a){if(!ax){var b=E.createEventObject,c=E.readyState==="complete",d=E.readyState==="interactive";if(!a||a.type!=="readystatechange"||c||!b&&d){ax=!0;for(var e=0;e=0)&&c.push(e.listener)});return c};function hx(a,b,c){return{entityType:a,indexInOriginContainer:b,nameInOriginContainer:c,originContainerId:kk()}};var jx=function(a,b){this.j=!1;this.K=[];this.eventData={tags:[]};this.P=!1;this.C=this.H=0;ix(this,a,b)},kx=function(a,b,c,d){if(Ji.hasOwnProperty(b)||b==="__zone")return-1;var e={};Qa(d)&&(e=Sa(d,e));e.id=c;e.status="timeout";return a.eventData.tags.push(e)-1},lx=function(a,b,c,d){var e=a.eventData.tags[b];e&&(e.status=c,e.executionTime=d)},mx=function(a){if(!a.j){for(var b=a.K,c=0;c=a.H&&mx(a)})},ox=function(a){a.P=!0;a.C>=a.H&&mx(a)};var px={};function qx(){return C[rx()]} -function rx(){return C.GoogleAnalyticsObject||"ga"}function ux(){var a=kk();} -function vx(a,b){return function(){var c=qx(),d=c&&c.getByName&&c.getByName(a);if(d){var e=d.get("sendHitTask");d.set("sendHitTask",function(f){var g=f.get("hitPayload"),k=f.get("hitCallback"),m=g.indexOf("&tid="+b)<0;m&&(f.set("hitPayload",g.replace(/&tid=UA-[0-9]+-[0-9]+/,"&tid="+b),!0),f.set("hitCallback",void 0,!0));e(f);m&&(f.set("hitPayload",g,!0),f.set("hitCallback",k,!0),f.set("_x_19",void 0,!0),e(f))})}}}var Ax=["es","1"],Bx={},Cx={};function Dx(a,b){if(Qj){var c;c=b.match(/^(gtm|gtag)\./)?encodeURIComponent(b):"*";Bx[a]=[["e",c],["eid",a]];Om(a)}}function Ex(a){var b=a.eventId,c=a.Oc;if(!Bx[b])return[];var d=[];Cx[b]||d.push(Ax);d.push.apply(d,oa(Bx[b]));c&&(Cx[b]=!0);return d};var Fx={},Gx={},Hx={};function Ix(a,b,c,d){Qj&&Q(89)&&((d===void 0?0:d)?(Hx[b]=Hx[b]||0,++Hx[b]):c!==void 0?(Gx[a]=Gx[a]||{},Gx[a][b]=Math.round(c)):(Fx[a]=Fx[a]||{},Fx[a][b]=(Fx[a][b]||0)+1))}function Jx(a){var b=a.eventId,c=a.Oc,d=Fx[b]||{},e=[],f;for(f in d)d.hasOwnProperty(f)&&e.push(""+f+d[f]);c&&delete Fx[b];return e.length?[["md",e.join(".")]]:[]} -function Kx(a){var b=a.eventId,c=a.Oc,d=Gx[b]||{},e=[],f;for(f in d)d.hasOwnProperty(f)&&e.push(""+f+d[f]);c&&delete Gx[b];return e.length?[["mtd",e.join(".")]]:[]}function Lx(){for(var a=[],b=h(Object.keys(Hx)),c=b.next();!c.done;c=b.next()){var d=c.value;a.push(""+d+Hx[d])}return a.length?[["mec",a.join(".")]]:[]};var Mx={},Nx={};function Ox(a,b,c){if(Qj&&b){var d=Kj(b);Mx[a]=Mx[a]||[];Mx[a].push(c+d);var e=(wf(b)?"1":"2")+d;Nx[a]=Nx[a]||[];Nx[a].push(e);Om(a)}}function Px(a){var b=a.eventId,c=a.Oc,d=[],e=Mx[b]||[];e.length&&d.push(["tr",e.join(".")]);var f=Nx[b]||[];f.length&&d.push(["ti",f.join(".")]);c&&(delete Mx[b],delete Nx[b]);return d};function Qx(a,b,c,d){var e=jf[a],f=Rx(a,b,c,d);if(!f)return null;var g=xf(e[He.Ij],c,[]);if(g&&g.length){var k=g[0];f=Qx(k.index,{onSuccess:f,onFailure:k.Tj===1?b.terminate:f,terminate:b.terminate},c,d)}return f} -function Rx(a,b,c,d){function e(){function w(){kl(3);var J=zb()-I;Ox(c.id,f,"7");lx(c.kc,B,"exception",J);Q(77)&&pw(c,f,yv.J.Jj);D||(D=!0,k())}if(f[He.jl])k();else{var x=vf(f,c,[]),y=x[He.Ck];if(y!=null)for(var A=0;A -0};var $x=function(a,b){if(!Zx)return!1;var c=a["gtm.triggers"]&&String(a["gtm.triggers"]),d=Zx.C(a.event,c?String(c).split(","):[]);if(!d.length)return!1;for(var e=0;ee?1:dk?1:g=0){if(e.Zh=Ul(g,b),e.Zh){var k=ik();pb(k,function(r){return function(t){return r.Zh.destinationId===t}}(e))?c.push(g):d.push(g)}}else{var m=By[g]||[];e.Jh={};m.forEach(function(r){return function(t){r.Jh[t]=!0}}(e));for(var n=fk(),p=0;p=0&&c.splice(d,1)})}function Fy(a){z(Cy,function(b,c){var d=c.indexOf(a);d>=0&&c.splice(d,1)})}var Gy="HA GF G UA AW DC MC".split(" "),Hy=!1,Iy=!1,Jy=!1,Ky=!1;function Ly(a,b){a.hasOwnProperty("gtm.uniqueEventId")||Object.defineProperty(a,"gtm.uniqueEventId",{value:Yi()});b.eventId=a["gtm.uniqueEventId"];b.priorityId=a["gtm.priorityId"];return{eventId:b.eventId,priorityId:b.priorityId}}var My=void 0,Ny=void 0; -function Oy(a,b,c){var d=Sa(a,null);d.eventId=void 0;d.inheritParentConfig=void 0;Object.keys(b).some(function(f){return b[f]!==void 0})&&U(136);var e=Sa(b,null);Sa(c,e);ny(ky(fk()[0],e),a.eventId,d)}function Py(a){for(var b=h([O.g.ld,O.g.Pb]),c=b.next();!c.done;c=b.next()){var d=c.value,e=a&&a[d]||Wm.j[d];if(e)return e}} -var Qy=[O.g.ld,O.g.Pb,O.g.yc,O.g.sb,O.g.yb,O.g.ya,O.g.oa,O.g.Ia,O.g.Pa,O.g.ub],Ry={config:function(a,b){var c=Ly(a,b);if(!(a.length<2)&&l(a[1])){var d={};if(a.length>2){if(a[2]!==void 0&&!Qa(a[2])||a.length>3)return;d=a[2]}var e=Ul(a[1],b.isGtmEvent);if(e){var f,g,k;a:{if(!dk.qe){var m=ok(pk());if(Ak(m)){var n=m.parent,p=n.isDestination;k={Nm:ok(n),Cm:p};break a}}k=void 0}var q=k;q&&(f=q.Nm,g=q.Cm);Dx(c.eventId,"gtag.config");var r=e.destinationId,t=e.id!==r;if(t?ik().indexOf(r)===-1:fk().indexOf(r)=== --1){if(!b.inheritParentConfig&&!d[O.g.Lb]){var v=Py(d);if(t)$w(r,v,{source:2,fromContainerExecution:b.fromContainerExecution});else if(f!==void 0&&f.containers.indexOf(r)!==-1){var u=d;My?Oy(b,u,My):Ny||(Ny=Sa(u,null))}else Xw(r,v,!0,{source:2,fromContainerExecution:b.fromContainerExecution})}}else{if(f&&(U(128),g&&U(130),b.inheritParentConfig)){var w;var x=d;Ny?(Oy(b,Ny,x),w=!1):(!x[O.g.ic]&&Li&&My||(My=Sa(x,null)),w=!0);w&&f.containers&&f.containers.join(",");return}var y=d;if(!Jy&&(Jy=!0,Iy))for(var A= -h(Qy),B=A.next();!B.done;B=A.next())if(y.hasOwnProperty(B.value)){jl("erc");break}Rj&&!ek&&(hy===1&&(Ek.mcc=!1),hy=2);gl=!0;if(Li&&!t&&!d[O.g.ic]){var D=Ky;Ky=!0;if(D)return}Hy||U(43);if(!b.noTargetGroup)if(t){Fy(e.id);var I=e.id,J=d[O.g.de]||"default";J=String(J).split(",");for(var H=0;H2){if(!Qa(a[2])&&a[2]!==void 0||a.length>3)return;d=a[2]}var e=d,f={},g=(f.event=c,f);e&&(g.eventModel=Sa(e,null),e[O.g.ed]&&(g.eventCallback=e[O.g.ed]),e[O.g.ae]&&(g.eventTimeout=e[O.g.ae]));var k=Ly(a,b),m=k.eventId,n=k.priorityId;g["gtm.uniqueEventId"]=m;n&&(g["gtm.priorityId"]=n);if(c==="optimize.callback")return g.eventModel=g.eventModel||{},g;var p;var q=d,r=q&&q[O.g.fc]; -r===void 0&&(r=hj(O.g.fc,2),r===void 0&&(r="default"));if(l(r)||Array.isArray(r)){var t;t=b.isGtmEvent?l(r)?[r]:r:r.toString().replace(/\s+/g,"").split(",");var v=Dy(t,b.isGtmEvent),u=v.Dm,w=v.Gm;if(w.length)for(var x=Py(q),y=0;y0?g.eventModel[O.g.fc]=I.join():delete g.eventModel[O.g.fc];Hy||U(43);b.noGtmEvent===void 0&&b.eventMetadata&&b.eventMetadata.syn_or_mod&&(b.noGtmEvent=!0);g.eventModel[O.g.bc]&& -(b.noGtmEvent=!0);return b.noGtmEvent?void 0:g}}},get:function(a,b){U(53);if(a.length===4&&l(a[1])&&l(a[2])&&mb(a[3])){var c=Ul(a[1],b.isGtmEvent),d=String(a[2]),e=a[3];if(c){Hy||U(43);var f=Py();if(!pb(ik(),function(k){return c.destinationId===k}))$w(c.destinationId,f,{source:4,fromContainerExecution:b.fromContainerExecution});else if(Gy.indexOf(qk(c.prefix))!==-1){gl=!0;Ly(a,b);var g={};Sa((g[O.g.wb]=d,g[O.g.Jb]=e,g),null);Ym(d,function(k){F(function(){e(k)})},c.id,b)}}}},js:function(a,b){if(a.length=== -2&&a[1].getTime){Hy=!0;var c=Ly(a,b),d=c.eventId,e=c.priorityId,f={};return f.event="gtm.js",f["gtm.start"]=a[1].getTime(),f["gtm.uniqueEventId"]=d,f["gtm.priorityId"]=e,f}},policy:function(a){if(a.length===3&&l(a[1])&&mb(a[2])){if(Kf(a[1],a[2]),U(74),a[1]==="all"){U(75);var b=!1;try{b=a[2](kk(),"unknown",{})}catch(c){}b||U(76)}}else U(73)},set:function(a,b){var c=void 0;a.length===2&&Qa(a[1])?c=Sa(a[1],null):a.length===3&&l(a[1])&&(c={},Qa(a[2])||Array.isArray(a[2])?c[a[1]]=Sa(a[2],null):c[a[1]]= -a[2]);if(c){var d=Ly(a,b),e=d.eventId,f=d.priorityId;Sa(c,null);var g=Sa(c,null);Wm.push("set",[g],void 0,b);c["gtm.uniqueEventId"]=e;f&&(c["gtm.priorityId"]=f);delete c.event;b.overwriteModelFields=!0;return c}}},Sy={policy:!0};var Uy=function(a){if(Ty(a))return a;this.value=a};Uy.prototype.getUntrustedMessageValue=function(){return this.value};var Ty=function(a){return!a||Oa(a)!=="object"||Qa(a)?!1:"getUntrustedMessageValue"in a};Uy.prototype.getUntrustedMessageValue=Uy.prototype.getUntrustedMessageValue;var Vy=!1,Wy=[];function Xy(){if(!Vy){Vy=!0;for(var a=0;aZy&&(Zy=q)}dz=!1}}}return!a} -function nz(){if(Q(77)){var a=oz();}var b=lz();if(Q(77)){}try{var c=kk(),d=C[Gi.nb].hide;if(d&&d[c]!==void 0&&d.end){d[c]=!1;var e=!0,f;for(f in d)if(d.hasOwnProperty(f)&&d[f]=== -!0){e=!1;break}e&&(d.end(),d.end=null)}}catch(g){}return b}function qy(a){if(Zy -0){f=[];for(var g=0;gn)for(U(4),c.pruned=!0;this.length>n;)this.shift();var p=typeof m!=="boolean"||m;return lz()&&p};var e=b.slice(0).map(function(f){return a(f)});az.push.apply(az,e);if(oz()){if(Q(77)){}F(nz)}}var oz=function(){var a=!0;return a},gz=function(a){return C[Gi.nb].push(a)};function qz(a){if(a==null||a.length===0)return!1;var b=Number(a),c=zb();return bc-9E5}function rz(a){return a&&a.indexOf("pending:")===0?qz(a.substr(8)):!1}; - -function Mz(){};var Nz=function(){};Nz.prototype.toString=function(){return"undefined"};var Oz=new Nz;function Vz(a,b){function c(g){var k=Aj(g),m=uj(k,"protocol"),n=uj(k,"host",!0),p=uj(k,"port"),q=uj(k,"path").toLowerCase().replace(/\/$/,"");if(m===void 0||m==="http"&&p==="80"||m==="https"&&p==="443")m="web",p="default";return[m,n,p,q]}for(var d=c(String(a)),e=c(String(b)),f=0;f= -0;case "_le":return qg(b,c);case "_lt":return sg(b,c);case "_re":return mg(b,c,a.ignore_case);case "_sw":return tg(b,c);case "_um":return Vz(b,c)}return!1};function Yz(){var a;a=a===void 0?"":a;var b,c;return((b=data)==null?0:(c=b.blob)==null?0:c.hasOwnProperty(1))?String(data.blob[1]):a};function Zz(){var a=[["cv",Q(109)?Yz():"1"],["rv",Gi.kh],["tc",jf.filter(function(b){return b}).length]];Gi.ue&&a.push(["x",Gi.ue]);$i.j&&a.push(["tag_exp",$i.j]);return a};var $z={},aA={};function bA(){var a=0;return function(b){switch(b){case 1:a|=1;break;case 2:a|=2;break;case 3:a|=4}return a}}function cA(a,b,c,d){if(Qj){var e=String(c)+b;$z[a]=$z[a]||[];$z[a].push(e);aA[a]=aA[a]||[];aA[a].push(d+b)}}function dA(a){var b=a.eventId,c=a.Oc,d=[],e=$z[b]||[];e.length&&d.push(["hf",e.join(".")]);var f=aA[b]||[];f.length&&d.push(["ht",f.join(".")]);c&&(delete $z[b],delete aA[b]);return d};function eA(){return!1}function fA(){var a={};return function(b,c,d){}};function gA(){var a=hA;return function(b,c,d){var e=d&&d.event;b==="__html"&&Q(81)||iA(c);var f=Eb(b,"__cvt_")?void 0:1,g=new Xa;z(c,function(r,t){var v=dd(t,void 0,f);v===void 0&&t!==void 0&&U(44);g.set(r,v)});a.j.j.C=Cf();var k={Qj:Rf(b),eventId:e==null?void 0:e.id,priorityId:e!==void 0?e.priorityId:void 0,ye:e!==void 0?function(r){e.kc.ye(r)}:void 0,jb:function(){return b},log:function(){},Ql:{index:d==null?void 0:d.index,type:d==null?void 0:d.type,name:d==null?void 0:d.name},Xm:!!Jw(b,3),originalEventData:e== -null?void 0:e.originalEventData};e&&e.cachedModelValues&&(k.cachedModelValues={gtm:e.cachedModelValues.gtm,ecommerce:e.cachedModelValues.ecommerce});if(eA()){var m=fA(),n,p;k.Va={ji:[],ze:{},Bb:function(r,t,v){t===1&&(n=r);t===7&&(p=v);m(r,t,v)},gg:bh()};k.log=function(r){var t=xa.apply(1,arguments);n&&m(n,4,{level:r,source:p,message:t})}}var q=Be(a,k,[b,g]);a.j.j.C=void 0;q instanceof za&&q.type==="return"&&(q=q.data);return G(q,void 0,f)}} -function iA(a){var b=a.gtmOnSuccess,c=a.gtmOnFailure;mb(b)&&(a.gtmOnSuccess=function(){F(b)});mb(c)&&(a.gtmOnFailure=function(){F(c)})};function jA(a){}jA.F="internal.addAdsClickIds";function kA(a,b){var c=this;}kA.R="addConsentListener";var lA=!1;function mA(a){for(var b=0;b=0?!1:!0},CA=["input","select","textarea"],DA=["button","hidden","image","reset", +var ag=function(){this.events=[];this.j="";this.ja={};this.baseUrl="";this.H=0;this.K=this.C=!1;};ag.prototype.add=function(a){return this.P(a)?(this.events.push(a),this.j=a.C,this.ja=a.ja,this.baseUrl=a.baseUrl,this.H+=a.K,this.C=a.H,!0):!1};ag.prototype.P=function(a){return this.events.length?this.events.length>=20||a.K+this.H>=16384?!1:this.baseUrl=== +a.baseUrl&&this.C===a.H&&this.aa(a):!0};ag.prototype.aa=function(a){var b=this;if(!this.K)return this.j===a.C;var c=Object.keys(this.ja);return c.length===Object.keys(a.ja).length&&c.every(function(d){return a.ja.hasOwnProperty(d)&&String(b.ja[d])===String(a.ja[d])})};var bg={},cg=(bg.uaa=!0,bg.uab=!0,bg.uafvl=!0,bg.uamb=!0,bg.uam=!0,bg.uap=!0,bg.uapv=!0,bg.uaw=!0,bg); +var fg=function(a,b){var c=a.events;if(c.length===1)return dg(c[0],b);var d=[];a.j&&d.push(a.j);for(var e={},f=0;fw&&(t=y,w=C)});x===c.length&&(g[u]=t)});eg(g,d);b&&d.push("_s="+b);for(var k=d.join("&"),m=[],n={},p=0;p2048&&(f=c.pop(),e=c.join("&"));return{params:e,body:f}},eg=function(a,b){ib(a,function(c,d){d!=null&&b.push(encodeURIComponent(c)+"="+encodeURIComponent(d))})};var gg=function(a){var b=[];ib(a,function(c,d){d!=null&&b.push(encodeURIComponent(c)+"="+encodeURIComponent(String(d)))});return b.join("&")},hg=function(a,b,c,d,e){this.baseUrl=b;this.endpoint=c;this.ja=a.ja;this.Rc=a.Rc;this.Jh=a.Jh;this.H=d;this.C=gg(a.ja);this.j=gg(a.Jh);this.K=this.j.length;if(e&&this.K>16384)throw Error("EVENT_TOO_LARGE");}; +var kg=function(a,b){for(var c=0;cd.length||!g&&d.length!==e.length?0:g?vb(d,k)&&(d===k||d.charAt(k.length)==="."):d===k)return!0}return!1},jg=/^[a-z$_][\w$]*$/i,ig=/^(?:[a-z_$][a-z_$0-9]*\.)*[a-z_$][a-z_$0-9]*(?:\.\*)?$/i; +var lg=["matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector"];function mg(a,b){var c=String(a),d=String(b),e=c.length-d.length;return e>=0&&c.indexOf(d,e)===e}var ng=new hb;function og(a,b,c){var d=c?"i":void 0;try{var e=String(b)+String(d),f=ng.get(e);f||(f=new RegExp(b,d),ng.set(e,f));return f.test(a)}catch(g){return!1}}function pg(a,b){return String(a).indexOf(String(b))>=0}function qg(a,b){return String(a)===String(b)} +function rg(a,b){return Number(a)>=Number(b)}function sg(a,b){return Number(a)<=Number(b)}function tg(a,b){return Number(a)>Number(b)}function ug(a,b){return Number(a)0;case 3:return!d(c[0]); +case 4:return og(d(c[0]),d(c[1]),!1);case 5:return qg(d(c[0]),d(c[1]));case 6:return vg(d(c[0]),d(c[1]));case 7:return mg(d(c[0]),d(c[1]));case 8:return pg(d(c[0]),d(c[1]));case 9:return ug(d(c[0]),d(c[1]));case 10:return sg(d(c[0]),d(c[1]));case 11:return tg(d(c[0]),d(c[1]));case 12:return rg(d(c[0]),d(c[1]));default:throw Error('Invalid boolean expression format. Expected "type" property tobe a positive integer which is less than 13.');}};function Vg(a){K(this.getName(),["message:?string"],arguments);};function Wg(a,b){K(this.getName(),["min:!number","max:!number"],arguments);return fb(a,b)};function Xg(){return(new Date).getTime()};function Yg(a){if(a===null)return"null";if(a instanceof Yc)return"array";if(a instanceof $c)return"function";if(a instanceof ed){var b;a=(b=a)==null?void 0:b.getValue();var c;if(((c=a)==null?void 0:c.constructor)===void 0||a.constructor.name===void 0){var d=String(a);return d.substring(8,d.length-1)}return String(a.constructor.name)}return typeof a};function Zg(a){function b(c){return function(d){try{return c(d)}catch(e){(Vf||Wf.Fk)&&a.call(this,e.message)}}}return{parse:b(function(c){return hd(JSON.parse(c))}),stringify:b(function(c){return JSON.stringify(G(c))})}};function $g(a){return lb(G(a,this.D))};function ah(a){return Number(G(a,this.D))};function bh(a){return a===null?"null":a===void 0?"undefined":a.toString()};function ch(a,b,c){var d=null,e=!1;return e?d:null};var Mg="floor ceil round max min abs pow sqrt".split(" ");function dh(){var a={};return{gm:function(b){return a.hasOwnProperty(b)?a[b]:void 0},Bk:function(b,c){a[b]=c},reset:function(){a={}}}}function eh(a,b){return function(){var c=Array.prototype.slice.call(ya.apply(0,arguments),0);c.unshift(b);return $c.prototype.invoke.apply(a,c)}} +function fh(a,b){K(this.getName(),["apiName:!string","mock:?*"],arguments);} +function gh(a,b){K(this.getName(),["apiName:!string","mock:!PixieMap"],arguments);};var hh={};var ih=function(a){var b=new La;if(a instanceof Yc)for(var c=a.ka(),d=0;d0?n.join(""):""}else k="";return k} +function Lh(a){return Nh(a.item_id,a.id,a.item_name)}function Nh(){for(var a=l(ya.apply(0,arguments)),b=a.next();!b.done;b=a.next()){var c=b.value;if(c!==null&&c!==void 0)return c}}function Oh(a){if(a&&a.length){for(var b=[],c=0;c>6,128|d&63):d<55296||d>=57344?b.push(224|d>>12,128|d>>6&63,128|d&63):(d=65536+((d&1023)<<10|a.charCodeAt(++c)&1023),b.push(240|d>>18,128|d>>12&63,128|d>>6&63,128|d&63))}return new Uint8Array(b)}} +function Xh(a){if(a===""||a==="e0")return Promise.resolve(a);var b;if((b=B.crypto)==null?0:b.subtle){if(Vh.test(a))return Promise.resolve(a);try{var c=Wh(a);return B.crypto.subtle.digest("SHA-256",c).then(function(d){var e=Array.from(new Uint8Array(d)).map(function(f){return String.fromCharCode(f)}).join("");return B.btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}).catch(function(){return"e2"})}catch(d){return Promise.resolve("e2")}}else return Promise.resolve("e1")};function Yh(a,b){if(a==="")return b;var c=Number(a);return isNaN(c)?b:c};var Zh=[];function $h(a){switch(a){case 0:return 0;case 45:return 1;case 46:return 2;case 47:return 9;case 52:return 3;case 67:return 4;case 92:return 5;case 94:return 6;case 111:return 7;case 112:return 11;case 113:return 8}}function ai(a,b){Zh[a]=b;var c=$h(a);c!==void 0&&(Ya[c]=b)}function Q(a){ai(a,!0)} +Q(34); +Q(30);Q(31);Q(32);Q(33);Q(48);Q(84);Q(16); +Q(120);Q(15); +Q(126);Q(119); +Q(68);Q(95); +Q(6);Q(49); +Q(4);Q(82);Q(88); +Q(115);Q(80);Q(74);Q(93); +Q(131);Q(106);Q(107); + +Q(127);Q(94);Q(5); +ai(19,!1),Q(20); +Q(111);Q(70); +Za[1]=Yh('1',6E4);Za[3]=Yh('10',1);Za[2]=Yh('',50);Q(25); +Q(13); +Q(73); +Q(116);var ci=!1; +Q(8);Q(99);Q(61);Q(130);Q(51); +Q(113);Q(102);Q(23);Q(52); +Q(50);Q(64);Q(112);Q(76);Q(79);Q(90); +Q(55);Q(53);Q(78);Q(110);Q(77);Q(71);function R(a){return!!Zh[a]}function bi(a,b){for(var c=!1,d=!1,e=0;c===d;)if(c=((Math.random()*4294967296|0)&1)===0,d=((Math.random()*4294967296|0)&1)===0,e++,e>30)return;c?Q(b):Q(a)}function V(a){Va("GTM",a)}; +var hi=function(a){var b=R(105);b=b===void 0?!1:b;var c={},d=["tv.1"],e=0;var t= +d.join("~"),w={userData:c};return b?{Ek:t,qg:w,Gk:e,Ul:"tv.1~${"+(t+"|encrypt}"),encryptionKeyString:gi()}:{Ek:t,qg:w,Gk:e}},ei=function(a){return ii.indexOf(a)!==-1},gi=function(){return'{\x22keys\x22:[{\x22id\x22:\x2214e479aa-ae60-4981-903f-b0b0039e11d0\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BDyA7Ou97G/A7M5d8092VG+S8ooDfgLfWgRGuS/eVz6ja/RrutqU/1XmjgzyWbyuKvQ2kGMJ6oBjBA6bmgrSZrs\x3d\x22}},{\x22id\x22:\x22ba3ca4a7-f2f9-4eba-8fca-017d0979b705\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BCd20YrlyjoTVssI9cwsok3qm317TanSYEGuacqoWc8fwejtg+5hL2C0v4cTrPe8u2vwlgS04ftSAgTLBO4ex9k\x3d\x22}},{\x22id\x22:\x22bbd6d0fb-7827-4d52-af05-6252a35eb812\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BHDCAEgw6O3X6ZIx3QlvTeH4xuAkW066hL2Tn0tvK/4AVWWhVtzdzgSPyeLobDHenTt3xs8OuWwz28CdscEl8z8\x3d\x22}},{\x22id\x22:\x22e834d0a4-3529-4354-aced-230caa13315b\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BMnsh9OyVcgDNTpnXjnrYnlPd8Zp/ZLKAWJXkjixjwAX6FaCLRZgD9ww33FeTfSxOO0SUmQzBJ5uysLs2O/8+Sk\x3d\x22}},{\x22id\x22:\x22fca2b65a-39ab-40aa-b085-2eaddb1077dd\x22,\x22hpkePublicKey\x22:{\x22version\x22:0,\x22params\x22:{\x22kem\x22:\x22DHKEM_P256_HKDF_SHA256\x22,\x22kdf\x22:\x22HKDF_SHA256\x22,\x22aead\x22:\x22AES_128_GCM\x22},\x22publicKey\x22:\x22BBq5y/0by+6wxUZXDx54gNVE1lxAoUSPKEnPfJSl64VMAsQyNwCnb6Q7ZpHbjH2/sC7kAFY6gDNkNMQ/jEO2A0M\x3d\x22}}]}'},ki=function(a,b){if(B.Promise){var c=void 0;return c}},mi=function(a,b,c){if(B.Promise)try{var d=new Promise(function(e){li(a,e)});return d}catch(e){}},ni=function(a){if(B.Promise)try{return new Promise(function(b){li(a,function(c){b(c)})})}catch(b){}},oi=function(a){for(var b=a.jf,c=a.time,d=["tv.1"],e=0,f=!1,g=0;g0&&B.Promise?xi(a).some(function(b){return b.value&&ei(b.name)&&!Vh.test(b.value)}):!1},pi=function(a,b){var c=xi(a);Ai(c,b)},qi=function(a){return a==null?"":z(a)?ob(String(a)):"e0"},wi=function(a){return a.replace(Bi,"")},ui=function(a){return vi(a.replace(/\s/g, +""))},vi=function(a){return ob(a.replace(Ci,"").toLowerCase())},ti=function(a){a=a.replace(/[\s-()/.]/g,"");a.charAt(0)!=="+"&&(a="+"+a);return Di.test(a)?a:"e0"},si=function(a){var b=a.toLowerCase().split("@");if(b.length===2){var c=b[0];/^(gmail|googlemail)\./.test(b[1])&&(c=c.replace(/\./g,""));c=c+"@"+b[1];if(Ei.test(c))return c}return"e0"},Ai=function(a,b){var c=!1;if(c=R(55)?!a.some(function(e){return e.value&&ei(e.name)}):a.some(function(e){e.value&&ei(e.name)}))b({jf:a});else if(B.Promise){var d; +if(R(54)||R(86))d=Hc();Promise.all(a.map(function(e){return e.value&&ei(e.name)?Xh(e.value).then(function(f){e.value=f}):Promise.resolve()})).then(function(){var e={jf:a};if(d!==void 0){var f=Hc();d&&f&&(e.time=Math.round(f)-Math.round(d))}b(e)}).catch(function(){b({jf:[]})})}else b({jf:[]})},Ci=/[0-9`~!@#$%^&*()_\-+=:;<>,.?|/\\[\]]/g,Ei=/^\S+@\S+\.\S+$/,Di=/^\+\d{10,15}$/,Bi=/[.~]/g,fi=/^[0-9A-Za-z_-]{43}$/,Fi={},di=(Fi.email="em",Fi.phone_number="pn",Fi.first_name="fn",Fi.last_name="ln",Fi.street= +"sa",Fi.city="ct",Fi.region="rg",Fi.country="co",Fi.postal_code="pc",Fi.error_code="ec",Fi),Gi={},ri=(Gi.email="sha256_email_address",Gi.phone_number="sha256_phone_number",Gi.first_name="sha256_first_name",Gi.last_name="sha256_last_name",Gi.street="sha256_street",Gi);var ii=Object.freeze(["email","phone_number","first_name","last_name","street"]);var Hi={An:'101925629~102067554~102067808~102077855'};var Ii={},Ji=B.google_tag_manager=B.google_tag_manager||{};Ii.th="4bc0";Ii.Ce=Number("0")||0;Ii.ob="dataLayer";Ii.Cn="ChEIgP/buQYQjYiNhoeHv8OLARIlAKRFPpEghTiVHxCc40xB4XBUdh9t85cPeSmF91py/rxMulcFfxoCEyA\x3d";var Ki={__cl:1,__ecl:1,__ehl:1,__evl:1,__fal:1,__fil:1,__fsl:1,__hl:1,__jel:1,__lcl:1,__sdl:1,__tl:1,__ytl:1},Li={__paused:1,__tg:1},Mi;for(Mi in Ki)Ki.hasOwnProperty(Mi)&&(Li[Mi]=1);var Ni=mb("true"),Oi=!1,Pi,Qi=!1;Qi=!0; +Pi=Qi;var Ri,Si=!1;Ri=Si;var Ti,Ui=!1;Ti=Ui;Ii.vf="www.googletagmanager.com";var Vi=""+Ii.vf+(Pi?"/gtag/js":"/gtm.js"),Wi=null,Xi=null,Yi={},Zi={};function $i(){var a=Ji.sequence||1;Ji.sequence=a+1;return a}Ii.Pk="true";var aj="";Ii.uh=aj;var bj=function(){this.j=new Set},dj=function(){return Array.from(cj.aa.j).join("~")},cj=new function(){this.aa=new bj;this.C=!1;this.j=0;this.K=this.P=this.Ua=this.H=""};function ej(){var a=cj.H.length;return cj.H[a-1]==="/"?cj.H.substring(0,a-1):cj.H}function fj(){return cj.C?R(71)?cj.j===0:cj.j!==1:!1}function gj(a){for(var b={},c=l(a.split("|")),d=c.next();!d.done;d=c.next())b[d.value]=!0;return b}var hj=new hb,ij={},jj={},mj={name:Ii.ob,set:function(a,b){Vc(yb(a,b),ij);kj()},get:function(a){return lj(a,2)},reset:function(){hj=new hb;ij={};kj()}};function lj(a,b){return b!=2?hj.get(a):nj(a)}function nj(a,b){var c=a.split(".");b=b||[];for(var d=ij,e=0;e0){e=[];for(var q=0;q=0&&(m[m.length-1]="");f=m.join("/");break;case "query":f=a.search.replace("?","");e&&(f=xj(f,e,!1));break;case "extension":var n=a.pathname.split(".");f=n.length>1?n[n.length-1]:"";f=f.split("/")[0];break;case "fragment":f=a.hash.replace("#","");break;default:f=a&&a.href}return f}function zj(a){return a?a.replace(":","").toLowerCase():""}function Bj(a){var b="";if(a&&a.href){var c=a.href.indexOf("#");b=c<0?a.href:a.href.substring(0,c)}return b}var Cj={},Dj=0; +function Ej(a){var b=Cj[a];if(!b){var c=E.createElement("a");a&&(c.href=a);var d=c.pathname;d[0]!=="/"&&(a||Va("TAGGING",1),d="/"+d);var e=c.hostname.replace(vj,"");b={href:c.href,protocol:c.protocol,host:c.host,hostname:e,pathname:d,search:c.search,hash:c.hash,port:c.port};Dj<5&&(Cj[a]=b,Dj++)}return b}function Fj(a){var b=Ej(B.location.href),c=yj(b,"host",!1);if(c&&c.match(wj)){var d=yj(b,"path");if(d){var e=d.split(a+"=");if(e.length>1)return e[1].split(";")[0].split("?")[0]}}} +function Gj(a){for(var b=0;b<3;++b)try{var c=decodeURIComponent(a).replace(/\+/g," ");if(c===a)break;a=c}catch(d){return""}return a};var Hj={"https://www.google.com":"/g","https://www.googleadservices.com":"/as","https://pagead2.googlesyndication.com":"/gs"};function Ij(a,b){if(a){var c=""+a;c.indexOf("http://")!==0&&c.indexOf("https://")!==0&&(c="https://"+c);c[c.length-1]==="/"&&(c=c.substring(0,c.length-1));return Ej(""+c+b).href}}function Jj(a,b){if(fj()||Ri)return Ij(a,b)}function Kj(){return!!Ii.uh&&Ii.uh.split("@@").join("")!=="SGTM_TOKEN"} +function Lj(a){for(var b=l([O.g.rd,O.g.Sb]),c=b.next();!c.done;c=b.next()){var d=W(a,c.value);if(d)return d}}function Mj(a,b){return fj()?""+ej()+(b?Hj[a]||"":""):a};function Nj(a){var b=String(a[Le.oa]||"").replace(/_/g,"");return vb(b,"cvt")?"cvt":b}var Oj=B.location.search.indexOf("?gtm_latency=")>=0||B.location.search.indexOf(">m_latency=")>=0;var Pj={sampleRate:"0.005000",Lk:"",zn:"0.01"},Qj=Math.random(),Rj;if(!(Rj=Oj)){var Sj=Pj.sampleRate;Rj=Qj=1-Number(Pj.zn);var Vj=/gtag[.\/]js/,Wj=/gtm[.\/]js/,Yj=!1;function Zj(a){if(Yj)return"1";var b,c=(b=a.scriptElement)==null?void 0:b.src;if(c){if(Vj.test(c))return"3";if(Wj.test(c))return"2"}return"0"}function ak(a,b){var c=bk();c.pending||(c.pending=[]);eb(c.pending,function(d){return d.target.ctid===a.ctid&&d.target.isDestination===a.isDestination})||c.pending.push({target:a,onLoad:b})}function ck(){var a=B.google_tags_first_party;Array.isArray(a)||(a=[]);for(var b={},c=l(a),d=c.next();!d.done;d=c.next())b[d.value]=!0;return Object.freeze(b)} +var dk=function(){this.container={};this.destination={};this.canonical={};this.pending=[];this.siloed=[];this.injectedFirstPartyContainers={};this.injectedFirstPartyContainers=ck()}; +function bk(){var a=kc("google_tag_data",{}),b=a.tidr;b&&typeof b==="object"||(b=new dk,a.tidr=b);var c=b;c.container||(c.container={});c.destination||(c.destination={});c.canonical||(c.canonical={});c.pending||(c.pending=[]);c.siloed||(c.siloed=[]);c.injectedFirstPartyContainers||(c.injectedFirstPartyContainers=ck());return c};var ek={},fk=!1,Pf={ctid:"G-V7DRP5E70N",canonicalContainerId:"97518959",rk:"G-V7DRP5E70N|GT-5NGSF76",sk:"G-V7DRP5E70N"};ek.ze=mb("");function gk(){return ek.ze&&hk().some(function(a){return a===Pf.ctid})}function ik(){var a=jk();return fk?a.map(kk):a}function lk(){var a=hk();return fk?a.map(kk):a}function mk(){return nk(Pf.ctid)}function ok(){return nk(Pf.canonicalContainerId||"_"+Pf.ctid)} +function jk(){return Pf.rk?Pf.rk.split("|"):[Pf.ctid]}function hk(){return Pf.sk?Pf.sk.split("|"):[]}function pk(){var a=qk(rk()),b=a&&a.parent;if(b)return qk(b)}function qk(a){var b=bk();return a.isDestination?b.destination[a.ctid]:b.container[a.ctid]}function nk(a){return fk?kk(a):a}function kk(a){return"siloed_"+a}function sk(a){return fk?tk(a):a}function tk(a){a=String(a);return vb(a,"siloed_")?a.substring(7):a} +function uk(){var a=!1;if(a){var b=bk();if(b.siloed){for(var c=[],d=jk().map(kk),e=hk().map(kk),f={},g=0;g=0){var u;b:{var v,t=(v=q.scriptElement)==null?void 0:v.src;if(t){for(var w=cj.C,x=Ej(t),y=w?x.pathname:""+x.hostname+x.pathname,A=E.scripts,C="",D=0;D=0){u=String(D);break b}C=String(D)}}if(C){u=C;break b}}u=void 0}var J=u;if(J){Yj=!0;r=J;break a}}var H=[].slice.call(document.scripts);r=q.scriptElement?String(H.indexOf(q.scriptElement)):"-1"}q.htmlLoadOrder=r;q.loadScriptType=Zj(q)}var U=p?e.destination:e.container,M=U[n];M?(p&&M.state===0&&V(93),Object.assign(M,q)):U[n]=q},e=bk(),f=l(b),g=f.next();!g.done;g= +f.next())d(g.value,!1);for(var k=l(c),m=k.next();!m.done;m=k.next())d(m.value,!0);e.canonical[ok()]={};vk()}function xk(a){return!!bk().container[a]}function yk(a){var b=bk().destination[a];return!!b&&!!b.state}function rk(){return{ctid:mk(),isDestination:ek.ze}}function zk(a){var b=bk();(b.siloed=b.siloed||[]).push(a)}function Ak(){var a=bk().container,b;for(b in a)if(a.hasOwnProperty(b)&&a[b].state===1)return!0;return!1} +function Bk(){var a={};ib(bk().destination,function(b,c){c.state===0&&(a[tk(b)]=c)});return a}function Ck(a){return!!(a&&a.parent&&a.context&&a.context.source===1&&a.parent.ctid.indexOf("GTM-")!==0)}var Dk="/td?id="+Pf.ctid,Ek=["v","t","pid","dl","tdp"],Fk=["mcc"],Gk={},Hk={};function Ik(a,b,c){Hk[a]=b;(c===void 0||c)&&Jk(a)}function Jk(a,b){if(Gk[a]===void 0||(b===void 0?0:b))Gk[a]=!0}function Kk(a){a=a===void 0?!1:a;var b=Object.keys(Gk).filter(function(c){return Gk[c]===!0&&Hk[c]!==void 0&&(a||!Fk.includes(c))}).map(function(c){var d=Hk[c];typeof d==="function"&&(d=d());return d?"&"+c+"="+d:""}).join("");return""+Mj("https://www.googletagmanager.com")+Dk+(""+b+"&z=0")} +function Lk(){Object.keys(Gk).forEach(function(a){Ek.indexOf(a)<0&&(Gk[a]=!1)})}function Mk(a){a=a===void 0?!1:a;if(Uj&&Pf.ctid){var b=Kk(a);a?Ec(b):uc(b);Lk()}}function Nk(){Object.keys(Gk).filter(function(a){return Gk[a]&&!Ek.includes(a)}).length>0&&Mk(!0)}var Ok=fb();function Pk(){Ok=fb()}function Qk(){Ik("v","3");Ik("t","t");Ik("pid",function(){return String(Ok)});vc(B,"pagehide",Nk);B.setInterval(Pk,864E5)}function Rk(){var a=kc("google_tag_data",{});return a.ics=a.ics||new Sk}var Sk=function(){this.entries={};this.waitPeriodTimedOut=this.wasSetLate=this.accessedAny=this.accessedDefault=this.usedImplicit=this.usedUpdate=this.usedDefault=this.usedDeclare=this.active=!1;this.j=[]}; +Sk.prototype.default=function(a,b,c,d,e,f,g){this.usedDefault||this.usedDeclare||!this.accessedDefault&&!this.accessedAny||(this.wasSetLate=!0);this.usedDefault=this.active=!0;Va("TAGGING",19);b==null?Va("TAGGING",18):Tk(this,a,b==="granted",c,d,e,f,g)};Sk.prototype.waitForUpdate=function(a,b,c){for(var d=0;d0&&n.update===void 0),u={region:q,declare_region:n.declare_region,implicit:n.implicit,default:c!==void 0?c:n.default,declare:n.declare,update:n.update,quiet:r};if(e!==""||n.default!==!1)m[b]=u;r&&B.setTimeout(function(){m[b]===u&&u.quiet&&(Va("TAGGING",2),a.waitPeriodTimedOut=!0,a.clearTimeout(b,void 0,k), +a.notifyListeners())},g)}};h=Sk.prototype;h.clearTimeout=function(a,b,c){var d=[a],e=c.delegatedConsentTypes,f;for(f in e)e.hasOwnProperty(f)&&e[f]===a&&d.push(f);var g=this.entries[a]||{},k=this.getConsentState(a,c);if(g.quiet){g.quiet=!1;for(var m=l(d),n=m.next();!n.done;n=m.next())Uk(this,n.value)}else if(b!==void 0&&k!==b)for(var p=l(d),q=p.next();!q.done;q=p.next())Uk(this,q.value)}; +h.update=function(a,b,c){this.usedDefault||this.usedDeclare||this.usedUpdate||!this.accessedAny||(this.wasSetLate=!0);this.usedUpdate=this.active=!0;if(b!=null){var d=this.getConsentState(a,c),e=this.entries;(e[a]=e[a]||{}).update=b==="granted";this.clearTimeout(a,d,c)}}; +h.declare=function(a,b,c,d,e){this.usedDeclare=this.active=!0;var f=this.entries,g=f[a]||{},k=g.declare_region,m=c&&z(c)?c.toUpperCase():void 0;d=d.toUpperCase();e=e.toUpperCase();if(d===""||m===e||(m===d?k!==e:!m&&!k)){var n={region:g.region,declare_region:m,declare:b==="granted",implicit:g.implicit,default:g.default,update:g.update,quiet:g.quiet};if(d!==""||g.declare!==!1)f[a]=n}};h.implicit=function(a,b){this.usedImplicit=!0;var c=this.entries,d=c[a]=c[a]||{};d.implicit!==!1&&(d.implicit=b==="granted")}; +h.getConsentState=function(a,b){var c=this.entries,d=c[a]||{},e=d.update;if(e!==void 0)return e?1:2;if(b.usedContainerScopedDefaults){var f=b.containerScopedDefaults[a];if(f===3)return 1;if(f===2)return 2}else if(e=d.default,e!==void 0)return e?1:2;if(b==null?0:b.delegatedConsentTypes.hasOwnProperty(a)){var g=b.delegatedConsentTypes[a],k=c[g]||{};e=k.update;if(e!==void 0)return e?1:2;if(b.usedContainerScopedDefaults){var m=b.containerScopedDefaults[g];if(m===3)return 1;if(m===2)return 2}else if(e= +k.default,e!==void 0)return e?1:2}e=d.declare;if(e!==void 0)return e?1:2;e=d.implicit;return e!==void 0?e?3:4:0};h.addListener=function(a,b){this.j.push({consentTypes:a,Ed:b})};var Uk=function(a,b){for(var c=0;c=e.length?m(n):B.setTimeout(function(){m(c())},500)}}))};var hl=["ad_storage","analytics_storage","ad_user_data","ad_personalization"],il=!1,jl=!1;function kl(){!jl&&il&&(hl.some(function(a){return Yk.containerScopedDefaults[a]!==1})||ll("mbc"));jl=!0}function ll(a){Uj&&(Ik(a,"1"),Mk())}function ml(a){Va("HEALTH",a)};var nl;try{nl=JSON.parse(Ta("eyIwIjoiVVMiLCIxIjoiVVMtQVoiLCIyIjpmYWxzZSwiMyI6IiIsIjQiOiIiLCI1Ijp0cnVlLCI2IjpmYWxzZSwiNyI6ImFkX3N0b3JhZ2V8YW5hbHl0aWNzX3N0b3JhZ2V8YWRfdXNlcl9kYXRhfGFkX3BlcnNvbmFsaXphdGlvbiJ9"))}catch(a){V(123),ml(2),nl={}}function ol(){return nl["0"]||""}function pl(){return nl["1"]||""}function ql(){var a=!1;a=!!nl["2"];return a}function rl(){return nl["6"]!==!1}function sl(){var a="";a=nl["4"]||"";return a} +function tl(){var a=!1;a=!!nl["5"];return a}function ul(){var a="";a=nl["3"]||"";return a}var vl=[O.g.O,O.g.U,O.g.N,O.g.za],wl,xl;function yl(a){for(var b=a[O.g.Jb],c=Array.isArray(b)?b:[b],d={Ue:0};d.Ue=0||E.location.search.indexOf(">m_diagnostics=")>=0,hm=void 0; +function im(a,b){if(b.length&&Uj){var c;(c=bm)[a]!=null||(c[a]=[]);cm[a]!=null||(cm[a]=[]);var d=b.filter(function(e){return!cm[a].includes(e)});bm[a].push.apply(bm[a],ua(d));cm[a].push.apply(cm[a],ua(d));!hm&&d.length>0&&(Jk("tdc",!0),hm=B.setTimeout(function(){Mk();bm={};hm=void 0},am))}} +function jm(a,b,c){if(Uj&&a==="config"){var d,e=(d=Wl(b))==null?void 0:d.ids;if(!(e&&e.length>1)){var f,g=kc("google_tag_data",{});g.td||(g.td={});f=g.td;var k=Vc(c.K);Vc(c.j,k);var m=[],n;for(n in f)if(f.hasOwnProperty(n)){var p=km(f[n],k);p.length&&(gm&&console.log(p),m.push(n))}m.length&&(im(b,m),Va("TAGGING",dm[E.readyState]||14));f[b]=k}}}function lm(a,b){var c={},d;for(d in b)b.hasOwnProperty(d)&&(c[d]=!0);for(var e in a)a.hasOwnProperty(e)&&(c[e]=!0);return c} +function km(a,b,c,d){c=c===void 0?{}:c;d=d===void 0?"":d;if(a===b)return[];var e=function(r,u){var v;Sc(u)==="object"?v=u[r]:Sc(u)==="array"&&(v=u[r]);return v===void 0?fm[r]:v},f=lm(a,b),g;for(g in f)if(f.hasOwnProperty(g)){var k=(d?d+".":"")+g,m=e(g,a),n=e(g,b),p=Sc(m)==="object"||Sc(m)==="array",q=Sc(n)==="object"||Sc(n)==="array";if(p&&q)km(m,n,c,k);else if(p||q||m!==n)c[k]=!0}return Object.keys(c)} +function mm(){Ik("tdc",function(){hm&&(B.clearTimeout(hm),hm=void 0);var a=[],b;for(b in bm)bm.hasOwnProperty(b)&&a.push(b+"*"+bm[b].join("."));return a.length?a.join("!"):void 0},!1)};var nm=function(a,b,c,d,e,f,g,k,m,n,p){this.eventId=a;this.priorityId=b;this.j=c;this.P=d;this.H=e;this.K=f;this.C=g;this.eventMetadata=k;this.onSuccess=m;this.onFailure=n;this.isGtmEvent=p},om=function(a,b){var c=[];switch(b){case 3:c.push(a.j);c.push(a.P);c.push(a.H);c.push(a.K);c.push(a.C);break;case 2:c.push(a.j);break;case 1:c.push(a.P);c.push(a.H);c.push(a.K);c.push(a.C);break;case 4:c.push(a.j),c.push(a.P),c.push(a.H),c.push(a.K)}return c},W=function(a,b,c,d){for(var e=l(om(a,d===void 0?3: +d)),f=e.next();!f.done;f=e.next()){var g=f.value;if(g[b]!==void 0)return g[b]}return c},pm=function(a){for(var b={},c=om(a,4),d=l(c),e=d.next();!e.done;e=d.next())for(var f=Object.keys(e.value),g=l(f),k=g.next();!k.done;k=g.next())b[k.value]=1;return Object.keys(b)},qm=function(a,b,c){function d(n){Uc(n)&&ib(n,function(p,q){f=!0;e[p]=q})}var e={},f=!1,g=om(a,c===void 0?3:c);g.reverse();for(var k=l(g),m=k.next();!m.done;m=k.next())d(m.value[b]);return f?e:void 0},rm=function(a){for(var b=[O.g.Zc,O.g.Vc, +O.g.Wc,O.g.Xc,O.g.Yc,O.g.bd,O.g.dd],c=om(a,3),d=l(c),e=d.next();!e.done;e=d.next()){for(var f=e.value,g={},k=!1,m=l(b),n=m.next();!n.done;n=m.next()){var p=n.value;f[p]!==void 0&&(g[p]=f[p],k=!0)}var q=k?g:void 0;if(q)return q}return{}},sm=function(a,b){this.eventId=a;this.priorityId=b;this.C={};this.P={};this.j={};this.H={};this.aa={};this.K={};this.eventMetadata={};this.isGtmEvent=!1;this.onSuccess=function(){};this.onFailure=function(){}},tm=function(a,b){a.C=b;return a},um=function(a,b){a.P=b; +return a},vm=function(a,b){a.j=b;return a},wm=function(a,b){a.H=b;return a},xm=function(a,b){a.aa=b;return a},ym=function(a,b){a.K=b;return a},zm=function(a,b){a.eventMetadata=b||{};return a},Am=function(a,b){a.onSuccess=b;return a},Bm=function(a,b){a.onFailure=b;return a},Cm=function(a,b){a.isGtmEvent=b;return a},Dm=function(a){return new nm(a.eventId,a.priorityId,a.C,a.P,a.j,a.H,a.K,a.eventMetadata,a.onSuccess,a.onFailure,a.isGtmEvent)};var Em={Kk:Number("5"),po:Number("")},Fm=[];function Gm(a){Fm.push(a)}var Hm="?id="+Pf.ctid,Im=void 0,Jm={},Km=void 0,Lm=new function(){var a=5;Em.Kk>0&&(a=Em.Kk);this.C=a;this.j=0;this.H=[]},Mm=1E3; +function Nm(a,b){var c=Im;if(c===void 0)if(b)c=$i();else return"";for(var d=[Mj("https://www.googletagmanager.com"),"/a",Hm],e=l(Fm),f=e.next();!f.done;f=e.next())for(var g=f.value,k=g({eventId:c,Tc:!!a}),m=l(k),n=m.next();!n.done;n=m.next()){var p=l(n.value),q=p.next().value,r=p.next().value;d.push("&"+q+"="+r)}d.push("&z=0");return d.join("")} +function Om(){Km&&(B.clearTimeout(Km),Km=void 0);if(Im!==void 0&&Pm){var a;(a=Jm[Im])||(a=Lm.j=2022&&Om())}var Rm=fb();function Sm(){Rm=fb()}function Tm(){return[["v","3"],["t","t"],["pid",String(Rm)]]}var Um={};function Vm(a,b,c){Tj&&a!==void 0&&(Um[a]=Um[a]||[],Um[a].push(c+b),Qm(a))}function Wm(a){var b=a.eventId,c=a.Tc,d=[],e=Um[b]||[];e.length&&d.push(["epr",e.join(".")]);c&&delete Um[b];return d};function Xm(a,b){var c=Wl(nk(a),!0);c&&Ym.register(c,b)}function Zm(a,b,c,d){var e=Wl(c,d.isGtmEvent);e&&(R(50)&&Oi&&(d.deferrable=!0),Ym.push("event",[b,a],e,d))}function $m(a,b,c,d){var e=Wl(c,d.isGtmEvent);e&&Ym.push("get",[a,b],e,d)}function an(a){var b=Wl(nk(a),!0),c;b?c=bn(Ym,b).j:c={};return c}function cn(a,b){var c=Wl(nk(a),!0);if(c){var d=Ym,e=Vc(b,null);Vc(bn(d,c).j,e);bn(d,c).j=e}} +var dn=function(){this.P={};this.j={};this.C={};this.aa=null;this.K={};this.H=!1;this.status=1},en=function(a,b,c,d){this.C=qb();this.j=b;this.args=c;this.messageContext=d;this.type=a},fn=function(){this.destinations={};this.j={};this.commands=[]},bn=function(a,b){var c=b.destinationId;return a.destinations[c]=a.destinations[c]||new dn},gn=function(a,b,c,d){if(d.j){var e=bn(a,d.j),f=e.aa;if(f){var g=Vc(c,null),k=Vc(e.P[d.j.id],null),m=Vc(e.K,null),n=Vc(e.j,null),p=Vc(a.j,null),q={};if(Tj)try{q=Vc(ij, +null)}catch(t){V(72)}var r=d.j.prefix,u=function(t){Vm(d.messageContext.eventId,r,t)},v=Dm(Cm(Bm(Am(zm(xm(wm(ym(vm(um(tm(new sm(d.messageContext.eventId,d.messageContext.priorityId),g),k),m),n),p),q),d.messageContext.eventMetadata),function(){if(u){var t=u;u=void 0;t("2");if(d.messageContext.onSuccess)d.messageContext.onSuccess()}}),function(){if(u){var t=u;u=void 0;t("3");if(d.messageContext.onFailure)d.messageContext.onFailure()}}),!!d.messageContext.isGtmEvent));try{Vm(d.messageContext.eventId, +r,"1"),jm(d.type,d.j.id,v),f(d.j.id,b,d.C,v)}catch(t){Vm(d.messageContext.eventId,r,"4")}}}};fn.prototype.register=function(a,b,c){var d=bn(this,a);d.status!==3&&(d.aa=b,d.status=3,c&&(Vc(d.j,c),d.j=c),this.flush())};fn.prototype.push=function(a,b,c,d){c!==void 0&&(bn(this,c).status===1&&(bn(this,c).status=2,this.push("require",[{}],c,{})),bn(this,c).H&&(d.deferrable=!1));this.commands.push(new en(a,c,b,d));d.deferrable||this.flush()}; +fn.prototype.flush=function(a){for(var b=this,c=[],d=!1,e={};this.commands.length;e={Jc:void 0,Kh:void 0}){var f=this.commands[0],g=f.j;if(f.messageContext.deferrable)!g||bn(this,g).H?(f.messageContext.deferrable=!1,this.commands.push(f)):c.push(f),this.commands.shift();else{switch(f.type){case "require":if(bn(this,g).status!==3&&!a){this.commands.push.apply(this.commands,c);return}break;case "set":ib(f.args[0],function(r,u){Vc(yb(r,u),b.j)});break;case "config":var k=bn(this,g);e.Jc={};ib(f.args[0], +function(r){return function(u,v){Vc(yb(u,v),r.Jc)}}(e));var m=!!e.Jc[O.g.nc];delete e.Jc[O.g.nc];var n=g.destinationId===g.id;m||(n?k.K={}:k.P[g.id]={});k.H&&m||gn(this,O.g.ba,e.Jc,f);k.H=!0;n?Vc(e.Jc,k.K):(Vc(e.Jc,k.P[g.id]),V(70));d=!0;break;case "event":e.Kh={};ib(f.args[0],function(r){return function(u,v){Vc(yb(u,v),r.Kh)}}(e));gn(this,f.args[1],e.Kh,f);break;case "get":var p={},q=(p[O.g.xb]=f.args[0],p[O.g.Mb]=f.args[1],p);gn(this,O.g.Ya,q,f)}this.commands.shift();hn(this,f)}}this.commands.push.apply(this.commands, +c);d&&this.flush()};var hn=function(a,b){if(b.type!=="require")if(b.j)for(var c=bn(a,b.j).C[b.type]||[],d=0;d0:!1}function zn(){return yn()?!1:xn("Opera")}function An(){return xn("Firefox")||xn("FxiOS")}function Bn(){return yn()?wn("Chromium"):(xn("Chrome")||xn("CriOS"))&&!(yn()?0:xn("Edge"))||xn("Silk")};var Cn=function(a){Cn[" "](a);return a};Cn[" "]=function(){};var Dn=function(a,b,c,d){for(var e=b,f=c.length;(e=a.indexOf(c,e))>=0&&ec)e=c;d+=b.length+1;return decodeURIComponent(a.slice(d,e!==-1?e:0).replace(/\+/g," "))},Gn=/[?&]($|#)/,Hn=function(a,b,c){for(var d,e=a.search(En),f=0,g,k=[];(g=Dn(a,f,b,e))>=0;)k.push(a.substring(f, +g)),f=Math.min(a.indexOf("&",g)+1||e,e);k.push(a.slice(f));d=k.join("").replace(Gn,"$1");var m,n=c!=null?"="+encodeURIComponent(String(c)):"";var p=b+n;if(p){var q,r=d.indexOf("#");r<0&&(r=d.length);var u=d.indexOf("?"),v;u<0||u>r?(u=r,v=""):v=d.substring(u+1,r);q=[d.slice(0,u),v,d.slice(r)];var t=q[1];q[1]=p?t?t+"&"+p:p:t;m=q[0]+(q[1]?"?"+q[1]:"")+q[2]}else m=d;return m};function In(){return nn?!!un&&!!un.platform:!1}function Jn(){return xn("iPhone")&&!xn("iPod")&&!xn("iPad")}function Kn(){Jn()||xn("iPad")||xn("iPod")};zn();yn()||xn("Trident")||xn("MSIE");xn("Edge");!xn("Gecko")||tn().toLowerCase().indexOf("webkit")!=-1&&!xn("Edge")||xn("Trident")||xn("MSIE")||xn("Edge");tn().toLowerCase().indexOf("webkit")!=-1&&!xn("Edge")&&xn("Mobile");In()||xn("Macintosh");In()||xn("Windows");(In()?un.platform==="Linux":xn("Linux"))||In()||xn("CrOS");In()||xn("Android");Jn();xn("iPad");xn("iPod");Kn();tn().toLowerCase().indexOf("kaios");var Ln=function(a){try{var b;if(b=!!a&&a.location.href!=null)a:{try{Cn(a.foo);b=!0;break a}catch(c){}b=!1}return b}catch(c){return!1}},Mn=function(a,b){if(a)for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&b(a[c],c,a)},Nn=function(a){if(B.top==B)return 0;if(a===void 0?0:a){var b=B.location.ancestorOrigins;if(b)return b[b.length-1]==B.location.origin?1:2}return Ln(B.top)?1:2},On=function(a){a=a===void 0?document:a;return a.createElement("img")},Pn=function(){for(var a=B,b=a;a&&a!=a.parent;)a= +a.parent,Ln(a)&&(b=a);return b};function Qn(a,b,c,d){d=d===void 0?!1:d;a.google_image_requests||(a.google_image_requests=[]);var e=On(a.document);if(c){var f=function(){if(c){var g=a.google_image_requests,k=dc(g,e);k>=0&&Array.prototype.splice.call(g,k,1)}mn(e,"load",f);mn(e,"error",f)};ln(e,"load",f);ln(e,"error",f)}d&&(e.attributionSrc="");e.src=b;a.google_image_requests.push(e)} +var Sn=function(a){var b;b=b===void 0?!1:b;var c="https://pagead2.googlesyndication.com/pagead/gen_204?id=tcfe";Mn(a,function(d,e){if(d||d===0)c+="&"+e+"="+encodeURIComponent(""+d)});Rn(c,b)},Rn=function(a,b){var c=window,d;b=b===void 0?!1:b;d=d===void 0?!1:d;if(c.fetch){var e={keepalive:!0,credentials:"include",redirect:"follow",method:"get",mode:"no-cors"};d&&(e.mode="cors","setAttributionReporting"in XMLHttpRequest.prototype?e.attributionReporting={eventSourceEligible:"true",triggerEligible:"false"}: +e.headers={"Attribution-Reporting-Eligible":"event-source"});c.fetch(a,e)}else Qn(c,a,b===void 0?!1:b,d===void 0?!1:d)};var Tn=function(){this.P=this.P;this.C=this.C};Tn.prototype.P=!1;Tn.prototype.dispose=function(){this.P||(this.P=!0,this.Ua())};Tn.prototype[Symbol.dispose]=function(){this.dispose()};Tn.prototype.addOnDisposeCallback=function(a,b){this.P?b!==void 0?a.call(b):a():(this.C||(this.C=[]),b&&(a=a.bind(b)),this.C.push(a))};Tn.prototype.Ua=function(){if(this.C)for(;this.C.length;)this.C.shift()()};function Un(a){a.addtlConsent!==void 0&&typeof a.addtlConsent!=="string"&&(a.addtlConsent=void 0);a.gdprApplies!==void 0&&typeof a.gdprApplies!=="boolean"&&(a.gdprApplies=void 0);return a.tcString!==void 0&&typeof a.tcString!=="string"||a.listenerId!==void 0&&typeof a.listenerId!=="number"?2:a.cmpStatus&&a.cmpStatus!=="error"?0:3} +var Vn=function(a,b){b=b===void 0?{}:b;Tn.call(this);this.j=null;this.aa={};this.dg=0;this.K=null;this.H=a;var c;this.xe=(c=b.un)!=null?c:500;var d;this.Ic=(d=b.Xn)!=null?d:!1};ra(Vn,Tn);Vn.prototype.Ua=function(){this.aa={};this.K&&(mn(this.H,"message",this.K),delete this.K);delete this.aa;delete this.H;delete this.j;Tn.prototype.Ua.call(this)};var Xn=function(a){return typeof a.H.__tcfapi==="function"||Wn(a)!=null}; +Vn.prototype.addEventListener=function(a){var b=this,c={internalBlockOnErrors:this.Ic},d=kn(function(){return a(c)}),e=0;this.xe!==-1&&(e=setTimeout(function(){c.tcString="tcunavailable";c.internalErrorState=1;d()},this.xe));var f=function(g,k){clearTimeout(e);g?(c=g,c.internalErrorState=Un(c),c.internalBlockOnErrors=b.Ic,k&&c.internalErrorState===0||(c.tcString="tcunavailable",k||(c.internalErrorState=3))):(c.tcString="tcunavailable",c.internalErrorState=3);a(c)};try{Yn(this,"addEventListener",f)}catch(g){c.tcString= +"tcunavailable",c.internalErrorState=3,e&&(clearTimeout(e),e=0),d()}};Vn.prototype.removeEventListener=function(a){a&&a.listenerId&&Yn(this,"removeEventListener",null,a.listenerId)}; +var $n=function(a,b,c){var d;d=d===void 0?"755":d;var e;a:{if(a.publisher&&a.publisher.restrictions){var f=a.publisher.restrictions[b];if(f!==void 0){e=f[d===void 0?"755":d];break a}}e=void 0}var g=e;if(g===0)return!1;var k=c;c===2?(k=0,g===2&&(k=1)):c===3&&(k=1,g===1&&(k=0));var m;if(k===0)if(a.purpose&&a.vendor){var n=Zn(a.vendor.consents,d===void 0?"755":d);m=n&&b==="1"&&a.purposeOneTreatment&&a.publisherCC==="CH"?!0:n&&Zn(a.purpose.consents,b)}else m=!0;else m=k===1?a.purpose&&a.vendor?Zn(a.purpose.legitimateInterests, +b)&&Zn(a.vendor.legitimateInterests,d===void 0?"755":d):!0:!0;return m},Zn=function(a,b){return!(!a||!a[b])},Yn=function(a,b,c,d){c||(c=function(){});var e=a.H;if(typeof e.__tcfapi==="function"){var f=e.__tcfapi;f(b,2,c,d)}else if(Wn(a)){io(a);var g=++a.dg;a.aa[g]=c;if(a.j){var k={};a.j.postMessage((k.__tcfapiCall={command:b,version:2,callId:g,parameter:d},k),"*")}}else c({},!1)},Wn=function(a){if(a.j)return a.j;var b;a:{for(var c=a.H,d=0;d<50;++d){var e;try{e=!(!c.frames||!c.frames.__tcfapiLocator)}catch(k){e= +!1}if(e){b=c;break a}var f;b:{try{var g=c.parent;if(g&&g!=c){f=g;break b}}catch(k){}f=null}if(!(c=f))break}b=null}a.j=b;return a.j},io=function(a){if(!a.K){var b=function(c){try{var d;d=(typeof c.data==="string"?JSON.parse(c.data):c.data).__tcfapiReturn;a.aa[d.callId](d.returnValue,d.success)}catch(e){}};a.K=b;ln(a.H,"message",b)}},jo=function(a){if(a.gdprApplies===!1)return!0;a.internalErrorState===void 0&&(a.internalErrorState=Un(a));return a.cmpStatus==="error"||a.internalErrorState!==0?a.internalBlockOnErrors? +(Sn({e:String(a.internalErrorState)}),!1):!0:a.cmpStatus!=="loaded"||a.eventStatus!=="tcloaded"&&a.eventStatus!=="useractioncomplete"?!1:!0};var ko={1:0,3:0,4:0,7:3,9:3,10:3};function lo(){var a=Ji.tcf||{};return Ji.tcf=a}var mo=function(){return new Vn(B,{un:-1})}; +function no(){var a=lo(),b=mo();Xn(b)&&!oo()&&!po()&&V(124);if(!a.active&&Xn(b)){oo()&&(a.active=!0,a.uc={},a.cmpId=0,a.tcfPolicyVersion=0,Rk().active=!0,a.tcString="tcunavailable");Gl();try{b.addEventListener(function(c){if(c.internalErrorState!==0)qo(a),Hl([O.g.O,O.g.za,O.g.N]),Rk().active=!0;else if(a.gdprApplies=c.gdprApplies,a.cmpId=c.cmpId,a.enableAdvertiserConsentMode=c.enableAdvertiserConsentMode,po()&&(a.active=!0),!ro(c)||oo()||po()){a.tcfPolicyVersion=c.tcfPolicyVersion;var d;if(c.gdprApplies=== +!1){var e={},f;for(f in ko)ko.hasOwnProperty(f)&&(e[f]=!0);d=e;b.removeEventListener(c)}else if(ro(c)){var g={},k;for(k in ko)if(ko.hasOwnProperty(k))if(k==="1"){var m,n=c,p={fm:!0};p=p===void 0?{}:p;m=jo(n)?n.gdprApplies===!1?!0:n.tcString==="tcunavailable"?!p.nk:(p.nk||n.gdprApplies!==void 0||p.fm)&&(p.nk||typeof n.tcString==="string"&&n.tcString.length)?$n(n,"1",0):!0:!1;g["1"]=m}else g[k]=$n(c,k,ko[k]);d=g}if(d){a.tcString=c.tcString||"tcempty";a.uc=d;var q={},r=(q[O.g.O]=a.uc["1"]?"granted": +"denied",q);a.gdprApplies!==!0?(Hl([O.g.O,O.g.za,O.g.N]),Rk().active=!0):(r[O.g.za]=a.uc["3"]&&a.uc["4"]?"granted":"denied",typeof a.tcfPolicyVersion==="number"&&a.tcfPolicyVersion>=4?r[O.g.N]=a.uc["1"]&&a.uc["7"]?"granted":"denied":Hl([O.g.N]),Bl(r,{eventId:0},{gdprApplies:a?a.gdprApplies:void 0,tcString:so()||""}))}}else Hl([O.g.O,O.g.za,O.g.N])})}catch(c){qo(a),Hl([O.g.O,O.g.za,O.g.N]),Rk().active=!0}}}function qo(a){a.type="e";a.tcString="tcunavailable"} +function ro(a){return a.eventStatus==="tcloaded"||a.eventStatus==="useractioncomplete"||a.eventStatus==="cmpuishown"}function oo(){return B.gtag_enable_tcf_support===!0}function po(){return lo().enableAdvertiserConsentMode===!0}function so(){var a=lo();if(a.active)return a.tcString}function to(){var a=lo();if(a.active&&a.gdprApplies!==void 0)return a.gdprApplies?"1":"0"}function uo(a){if(!ko.hasOwnProperty(String(a)))return!0;var b=lo();return b.active&&b.uc?!!b.uc[String(a)]:!0}var vo=[O.g.O,O.g.U,O.g.N,O.g.za],wo={},xo=(wo[O.g.O]=1,wo[O.g.U]=2,wo);function yo(a){if(a===void 0)return 0;switch(W(a,O.g.ma)){case void 0:return 1;case !1:return 3;default:return 2}}function zo(a){if(pl()==="US-CO"&&gc.globalPrivacyControl===!0)return!1;var b=yo(a);if(b===3)return!1;switch($k(O.g.za)){case 1:case 3:return!0;case 2:return!1;case 4:return b===2;case 0:return!0;default:return!1}}function Ao(){return cl()||!Zk(O.g.O)||!Zk(O.g.U)} +function Bo(){var a={},b;for(b in xo)xo.hasOwnProperty(b)&&(a[xo[b]]=$k(b));return"G1"+Ie(a[1]||0)+Ie(a[2]||0)}var Co={},Do=(Co[O.g.O]=0,Co[O.g.U]=1,Co[O.g.N]=2,Co[O.g.za]=3,Co);function Eo(a){switch(a){case void 0:return 1;case !0:return 3;case !1:return 2;default:return 0}} +function Fo(a){for(var b="1",c=0;c=0&&c<=4095&&(a="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[c>>6&63],b="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[c&63]);var e="0",f;var g=lo();f=g.active?g.tcfPolicyVersion:void 0;typeof f==="number"&&f>=0&&f<=63&&(e="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[f]);var k=0;rl()&&(k|=1);to()==="1"&&(k|=2);oo()&&(k|=4);var m;var n=lo();m=n.enableAdvertiserConsentMode!== +void 0?n.enableAdvertiserConsentMode?"1":"0":void 0;m==="1"&&(k|=8);Rk().waitPeriodTimedOut&&(k|=16);return"1"+a+b+e+"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"[k]}function Ko(){return pl()==="US-CO"};function Lo(){var a=!1;return a};var Mo={UA:1,AW:2,DC:3,G:4,GF:5,GT:12,GTM:14,HA:6,MC:7}; +function No(a){a=a===void 0?{}:a;var b=Pf.ctid.split("-")[0].toUpperCase(),c={ctid:Pf.ctid,gn:Ii.Ce,jn:Ii.th,Im:ek.ze?2:1,pn:a.Ak,Je:Pf.canonicalContainerId};c.Je!==a.ya&&(c.ya=a.ya);var d=pk();c.Tm=d?d.canonicalContainerId:void 0;Pi?(c.og=Mo[b],c.og||(c.og=0)):c.og=Ti?13:10;cj.C?(c.mg=0,c.Kl=2):Ri?c.mg=1:Lo()?c.mg=2:c.mg=3;var e={};e[6]=fk;cj.j===2?e[7]=!0:cj.j===1&&(e[2]=!0);if(jc){var f=yj(Ej(jc),"host");f&&(e[8]=f.match(/^(www\.)?googletagmanager\.com$/)===null)}c.Nl=e;var g=a.fg,k;var m=c.og, +n=c.mg;m===void 0?k="":(n||(n=0),k=""+Ke(1,1)+He(m<<2|n));var p=c.Kl,q="4"+k+(p?""+Ke(2,1)+He(p):""),r,u=c.jn;r=u&&Je.test(u)?""+Ke(3,2)+u:"";var v,t=c.gn;v=t?""+Ke(4,1)+He(t):"";var w;var x=c.ctid;if(x&&g){var y=x.split("-"),A=y[0].toUpperCase();if(A!=="GTM"&&A!=="OPT")w="";else{var C=y[1];w=""+Ke(5,3)+He(1+C.length)+(c.Im||0)+C}}else w="";var D=c.pn,I=c.Je,J=c.ya,H=c.mo,U=q+r+v+w+(D?""+Ke(6,1)+He(D):"")+(I?""+Ke(7,3)+He(I.length)+I:"")+(J?""+Ke(8,3)+He(J.length)+J:"")+(H?""+Ke(9,3)+He(H.length)+ +H:""),M;var aa=c.Nl;aa=aa===void 0?{}:aa;for(var da=[],T=l(Object.keys(aa)),S=T.next();!S.done;S=T.next()){var N=S.value;da[Number(N)]=aa[N]}if(da.length){var la=Ke(10,3),ia;if(da.length===0)ia=He(0);else{for(var ea=[],sa=0,Ma=!1,za=0;za=0;d--)e=a.charCodeAt(d),b=(b<<6&268435455)+e+(e<<14),c=b&266338304,b=c!==0?b^c>>21:b;return b};function Po(a){return a.origin!=="null"};function Qo(a,b,c,d){var e;if(Ro(d)){for(var f=[],g=String(b||So()).split(";"),k=0;k=0} +function Xo(a,b,c,d){function e(w,x,y){if(y==null)return delete k[x],w;k[x]=y;return w+"; "+x+"="+y}function f(w,x){if(x==null)return w;k[x]=!0;return w+"; "+x}if(!Ro(c.Hb))return 2;var g;b==null?g=a+"=deleted; expires="+(new Date(0)).toUTCString():(c.encode&&(b=encodeURIComponent(b)),b=Yo(b),g=a+"="+b);var k={};g=e(g,"path",c.path);var m;c.expires instanceof Date?m=c.expires.toUTCString():c.expires!=null&&(m=""+c.expires);g=e(g,"expires",m);g=e(g,"max-age",c.Mm);g=e(g,"samesite",c.kn);c.secure&& +(g=f(g,"secure"));var n=c.domain;if(n&&n.toLowerCase()==="auto"){for(var p=Zo(),q=void 0,r=!1,u=0;u0?d:e}function Uo(a,b,c){for(var d=[],e=Qo(a,void 0,void 0,c),f=0;f1200&&(a=a.substring(0,1200));return a} +var bp=/^(www\.)?google(\.com?)?(\.[a-z]{2})?$/,cp=/(^|\.)doubleclick\.net$/i;function $o(a,b){return a!==void 0&&(cp.test(window.document.location.hostname)||b==="/"&&bp.test(a))}function dp(a){if(!a)return 1;var b=a;$a(9)&&a==="none"&&(b=window.document.location.hostname);b=b.indexOf(".")===0?b.substring(1):b;return b.split(".").length}function ep(a){if(!a||a==="/")return 1;a[0]!=="/"&&(a="/"+a);a[a.length-1]!=="/"&&(a+="/");return a.split("/").length-1} +function fp(a,b){var c=""+dp(a),d=ep(b);d>1&&(c+="-"+d);return c} +var So=function(){return Po(window)?window.document.cookie:""},Ro=function(a){return a&&$a(10)?(Array.isArray(a)?a:[a]).every(function(b){return bl(b)&&Zk(b)}):!0},Zo=function(){var a=[],b=window.document.location.hostname.split(".");if(b.length===4){var c=b[b.length-1];if(Number(c).toString()===c)return["none"]}for(var d=b.length-2;d>=0;d--)a.push(b.slice(d).join("."));var e=window.document.location.hostname;cp.test(e)||bp.test(e)||a.push("none");return a};function gp(a){var b=Math.round(Math.random()*2147483647);return a?String(b^Oo(a)&2147483647):String(b)}function hp(a){return[gp(a),Math.round(qb()/1E3)].join(".")}function ip(a,b,c,d,e){var f=dp(b);return To(a,f,ep(c),d,e)}function jp(a,b,c,d){return[b,fp(c,d),a].join(".")};function kp(a,b,c,d){var e,f=Number(a.Fb!=null?a.Fb:void 0);f!==0&&(e=new Date((b||qb())+1E3*(f||7776E3)));return{path:a.path,domain:a.domain,flags:a.flags,encode:!!c,expires:e,Hb:d}};var lp;function mp(){function a(g){c(g.target||g.srcElement||{})}function b(g){d(g.target||g.srcElement||{})}var c=np,d=op,e=pp();if(!e.init){vc(E,"mousedown",a);vc(E,"keyup",a);vc(E,"submit",b);var f=HTMLFormElement.prototype.submit;HTMLFormElement.prototype.submit=function(){d(this);f.call(this)};e.init=!0}}function qp(a,b,c,d,e){var f={callback:a,domains:b,fragment:c===2,placement:c,forms:d,sameHost:e};pp().decorators.push(f)} +function rp(a,b,c){for(var d=pp().decorators,e={},f=0;f=0||p&&m[q].indexOf(n)>=0){k=!0;break a}k=!1}if(k){var r=g.placement;r===void 0&&(r=g.fragment?2:1);r===b&&tb(e,g.callback())}}return e} +function pp(){var a=kc("google_tag_data",{}),b=a.gl;b&&b.decorators||(b={decorators:[]},a.gl=b);return b};var sp=/(.*?)\*(.*?)\*(.*)/,tp=/^https?:\/\/([^\/]*?)\.?cdn\.ampproject\.org\/?(.*)/,up=/^(?:www\.|m\.|amp\.)+/,vp=/([^?#]+)(\?[^#]*)?(#.*)?/;function wp(a){var b=vp.exec(a);if(b)return{ei:b[1],query:b[2],fragment:b[3]}}function xp(a){return new RegExp("(.*?)(^|&)"+a+"=([^&]*)&?(.*)")} +function yp(a,b){var c=[gc.userAgent,(new Date).getTimezoneOffset(),gc.userLanguage||gc.language,Math.floor(qb()/60/1E3)-(b===void 0?0:b),a].join("*"),d;if(!(d=lp)){for(var e=Array(256),f=0;f<256;f++){for(var g=f,k=0;k<8;k++)g=g&1?g>>>1^3988292384:g>>>1;e[f]=g}d=e}lp=d;for(var m=4294967295,n=0;n>>8^lp[(m^c.charCodeAt(n))&255];return((m^-1)>>>0).toString(36)} +function zp(a){return function(b){var c=Ej(B.location.href),d=c.search.replace("?",""),e=xj(d,"_gl",!1,!0)||"";b.query=Ap(e)||{};var f=yj(c,"fragment"),g;var k=-1;if(vb(f,"_gl="))k=4;else{var m=f.indexOf("&_gl=");m>0&&(k=m+3+2)}if(k<0)g=void 0;else{var n=f.indexOf("&",k);g=n<0?f.substring(k):f.substring(k,n)}b.fragment=Ap(g||"")||{};a&&Bp(c,d,f)}}function Cp(a,b){var c=xp(a).exec(b),d=b;if(c){var e=c[2],f=c[4];d=c[1];f&&(d=d+e+f)}return d} +function Bp(a,b,c){function d(g,k){var m=Cp("_gl",g);m.length&&(m=k+m);return m}if(fc&&fc.replaceState){var e=xp("_gl");if(e.test(b)||e.test(c)){var f=yj(a,"path");b=d(b,"?");c=d(c,"#");fc.replaceState({},"",""+f+b+c)}}}function Dp(a,b){var c=zp(!!b),d=pp();d.data||(d.data={query:{},fragment:{}},c(d.data));var e={},f=d.data;f&&(tb(e,f.query),a&&tb(e,f.fragment));return e} +var Ap=function(a){try{var b=Ep(a,3);if(b!==void 0){for(var c={},d=b?b.split("*"):[],e=0;e+10;){if(c.href&&c.nodeName.match(/^a(?:rea)?$/i)){b=c;break a}c=c.parentNode;d--}b=null}var e=b;if(e){var f=e.protocol;f!=="http:"&&f!=="https:"||Gp(e,e.hostname)}}catch(g){}}function op(a){try{if(a.action){var b=yj(Ej(a.action),"host");Gp(a,b)}}catch(c){}}function Kp(a,b,c,d){mp();var e=c==="fragment"?2:1;d=!!d;qp(a,b,e,d,!1);e===2&&Va("TAGGING",23);d&&Va("TAGGING",24)}function Lp(a,b){mp();qp(a,[Aj(B.location,"host",!0)],b,!0,!0)} +function Mp(){var a=E.location.hostname,b=tp.exec(E.referrer);if(!b)return!1;var c=b[2],d=b[1],e="";if(c){var f=c.split("/"),g=f[1];e=g==="s"?decodeURIComponent(f[2]):decodeURIComponent(g)}else if(d){if(d.indexOf("xn--")===0)return!1;e=d.replace(/-/g,".").replace(/\.\./g,"-")}var k=a.replace(up,""),m=e.replace(up,"");return k===m||wb(k,"."+m)}function Np(a,b){return a===!1?!1:a||b||Mp()};var Op=["1"],Pp={},Qp={};function Rp(a,b){b=b===void 0?!0:b;var c=Sp(a.prefix);if(!Pp[c])if(Tp(c,a.path,a.domain)){var d=Qp[Sp(a.prefix)];Up(a,d?d.id:void 0,d?d.Yh:void 0)}else{var e=Fj("auiddc");if(e)Va("TAGGING",17),Pp[c]=e;else if(b){var f=Sp(a.prefix),g=hp();Vp(f,g,a);Tp(c,a.path,a.domain)}}}function Up(a,b,c){var d=Sp(a.prefix),e=Pp[d];if(e){var f=e.split(".");if(f.length===2){var g=Number(f[1])||0;if(g){var k=e;b&&(k=e+"."+b+"."+(c?c:Math.floor(qb()/1E3)));Vp(d,k,a,g*1E3)}}}} +function Vp(a,b,c,d){var e=jp(b,"1",c.domain,c.path),f=kp(c,d);f.Hb=Wp();ap(a,e,f)}function Tp(a,b,c){var d=ip(a,b,c,Op,Wp());if(!d)return!1;Xp(a,d);return!0}function Xp(a,b){var c=b.split(".");c.length===5?(Pp[a]=c.slice(0,2).join("."),Qp[a]={id:c.slice(2,4).join("."),Yh:Number(c[4])||0}):c.length===3?Qp[a]={id:c.slice(0,2).join("."),Yh:Number(c[2])||0}:Pp[a]=b}function Sp(a){return(a||"_gcl")+"_au"}function Yp(a){function b(){Zk(c)&&a()}var c=Wp();fl(function(){b();Zk(c)||gl(b,c)},c)} +function Zp(a){var b=Dp(!0),c=Sp(a.prefix);Yp(function(){var d=b[c];if(d){Xp(c,d);var e=Number(Pp[c].split(".")[1])*1E3;if(e){Va("TAGGING",16);var f=kp(a,e);f.Hb=Wp();var g=jp(d,"1",a.domain,a.path);ap(c,g,f)}}})}function $p(a,b,c,d,e){e=e||{};var f=function(){var g={},k=ip(a,e.path,e.domain,Op,Wp());k&&(g[a]=k);return g};Yp(function(){Kp(f,b,c,d)})}function Wp(){return["ad_storage","ad_user_data"]};var aq={},bq=(aq.k={La:/^[\w-]+$/},aq.b={La:/^[\w-]+$/,li:!0},aq.i={La:/^[1-9]\d*$/},aq.u={La:/^[1-9]\d*$/},aq);var cq={},fq=(cq[5]={Mk:{2:dq},Ch:["k","i","b","u"]},cq[4]={Mk:{2:dq,GCL:eq},Ch:["k","i","b"]},cq);function gq(a){var b=fq[5];if(b){var c=a.split(".")[0];if(c){var d=b.Mk[c];if(d)return d(a,5)}}} +function dq(a,b){var c=a.split(".");if(c.length===3){var d={},e=fq[b];if(e){for(var f=e.Ch,g=l(c[2].split("$")),k=g.next();!k.done;k=g.next()){var m=k.value,n=m[0];if(f.indexOf(n)!==-1)try{var p=decodeURIComponent(m.substring(1)),q=bq[n];q&&(q.li?(d[n]=d[n]||[],d[n].push(p)):d[n]=p)}catch(r){}}return d}}} +function hq(a,b){var c=fq[5];if(c){for(var d=[],e=l(c.Ch),f=e.next();!f.done;f=e.next()){var g=f.value,k=bq[g];if(k){var m=a[g];if(m!==void 0)if(k.li&&Array.isArray(m))for(var n=l(m),p=n.next();!p.done;p=n.next())d.push(encodeURIComponent(""+g+p.value));else d.push(encodeURIComponent(""+g+m))}}return["2",b||"1",d.join("$")].join(".")}}function eq(a){var b=a.split(".");b.shift();var c=b.shift(),d=b.shift(),e={};return e.k=d,e.i=c,e.b=b,e};var iq=new Map([[5,"ad_storage"],[4,["ad_storage","ad_user_data"]]]);function jq(a){if(fq[5]){for(var b=[],c=Qo(a,void 0,void 0,iq.get(5)),d=l(c),e=d.next();!e.done;e=d.next()){var f=gq(e.value);f&&(kq(f),b.push(f))}return b}}function lq(a,b,c,d){c=c||{};var e=fp(c.domain,c.path),f=hq(b,e);if(f){var g=kp(c,d,void 0,iq.get(5));ap(a,f,g)}}function mq(a,b){var c=b.La;return typeof c==="function"?c(a):c.test(a)} +function kq(a){for(var b=l(Object.keys(a)),c=b.next(),d={};!c.done;d={Le:void 0},c=b.next()){var e=c.value,f=a[e];d.Le=bq[e];d.Le?d.Le.li?a[e]=Array.isArray(f)?f.filter(function(g){return function(k){return mq(k,g.Le)}}(d)):void 0:typeof f==="string"&&mq(f,d.Le)||(a[e]=void 0):a[e]=void 0}};function nq(a){for(var b=[],c=E.cookie.split(";"),d=new RegExp("^\\s*"+(a||"_gac")+"_(UA-\\d+-\\d+)=\\s*(.+?)\\s*$"),e=0;e3&&(g.labels=f.slice(3));d[c[e].si].push(g)}}return d};var pq=["ad_storage","ad_user_data"];function qq(){var a=rq();if(a.error)return a;if(!a.value)return{error:2};var b;try{b=a.value.gclid}catch(c){return{error:11}}return b?{value:b}:{value:void 0}} +function rq(){if(!Zk(pq))return{error:3};try{if(!B.localStorage)return{error:1}}catch(d){return{error:14}}var a={schema:"gcl",version:1},b=void 0;try{b=B.localStorage.getItem("_gcl_ls")}catch(d){return{error:13}}try{if(b){var c=JSON.parse(b);if(c&&typeof c==="object")a=c;else return{error:12}}}catch(d){return{error:8}}if(a.schema!=="gcl")return{error:4};if(a.version!==1)return{error:5};try{sq(a)}catch(d){return{error:8}}return{value:a,error:0}} +function sq(a){if(a&&typeof a==="object")if("expires"in a&&"value"in a){var b;typeof a.expires==="number"?b=a.expires:b=typeof a.expires==="string"?Number(a.expires):NaN;!isNaN(b)&&Date.now()<=b||(a.value=null,a.error=9)}else for(var c=l(Object.keys(a)),d=c.next();!d.done;d=c.next())sq(a[d.value])};var tq=/^\w+$/,uq=/^[\w-]+$/,vq={},wq=(vq.aw="_aw",vq.dc="_dc",vq.gf="_gf",vq.gp="_gp",vq.gs="_gs",vq.ha="_ha",vq.ag="_ag",vq.gb="_gb",vq);function xq(){return["ad_storage","ad_user_data"]}function yq(a){return!$a(10)||Zk(a)}function zq(a,b){function c(){var d=yq(b);d&&a();return d}fl(function(){c()||gl(c,b)},b)}function Aq(a){return Bq(a).map(function(b){return b.W})}function Cq(a){return Dq(a).filter(function(b){return b.W}).map(function(b){return b.W})} +function Dq(a){var b=Eq(a.prefix),c=Fq("gb",b),d=Fq("ag",b);if(!d||!c)return[];var e=function(k){return function(m){m.type=k;return m}},f=Bq(c).map(e("gb")),g=Gq(d).map(e("ag"));return f.concat(g).sort(function(k,m){return m.timestamp-k.timestamp})}function Hq(a,b,c,d,e,f){var g=eb(a,function(k){return k.W===c});g?(g.timestamp0&&U.push(e.join("."));return U.join(".")},t=l(["aw","dc","gf","ha","gp"]),w=t.next();!w.done;w=t.next()){var x=w.value;a[x]&&u(x,v(a[x][0]))}if(!n&&a.gb){var y=a.gb[0],A=Fq("gb",f);!b&&Bq(A).some(function(H){return H.W===y&&H.labels&&H.labels.length> +0})||u("gb",v(y))}}if(!p&&a.gbraid&&yq("ad_storage")&&(p=!0,!n)){var C=a.gbraid,D=Fq("ag",f);if(b||!Gq(D).some(function(H){return H.W===C&&H.labels&&H.labels.length>0})){var I={},J=(I.k=C,I.i=""+k,I.b=e,I);lq(D,J,c,g)}}Xq(a,f,g,c)};fl(function(){q();yq(m)||gl(q,m)},m)} +function Xq(a,b,c,d){if(a.gad_source!==void 0&&yq("ad_storage")){if($a(5)){var e=Ic();if(e==="r"||e==="h")return}var f=a.gad_source,g=Fq("gs",b);if(g){var k=Math.round((qb()-(Hc()||0))/1E3),m;if($a(11)){var n,p=String,q=B.location.hostname,r=B.location.pathname,u=q=Gj(q);u.split(".").length>2&&(u=u.replace(/^(www[0-9]*|web|ftp|wap|home|m|w|amp|mobile)\./,""));q=u;r=Gj(r);var v=r.split(";")[0];v=v.replace(/\/(ar|slp|web|index)?\/?$/,"");n=p(Oo((""+q+v).toLowerCase()));var t={};m=(t.k=f,t.i=""+k,t.u= +n,t)}else{var w={};m=(w.k=f,w.i=""+k,w)}lq(g,m,d,c)}}}function Yq(a,b){var c=Dp(!0);zq(function(){for(var d=Eq(b.prefix),e=0;ep){n=!0;break b}n=!1}if(!n){var u=kp(b,m,!0);u.Hb=xq();ap(g,k,u)}}}}Vq(Sq(c.gclid,c.gclsrc),!1,b)},xq())} +function $q(a){var b=["ag"],c=Dp(!0),d=Eq(a.prefix);zq(function(){for(var e=0;ep){n=!0;break a}n=!1}if(n)break;k.i=""+Math.round(m/1E3);lq(f,k,a,m)}}}}},["ad_storage"])}function Fq(a,b){var c=wq[a];if(c!==void 0)return b+c}function Zq(a){return ar(a.split(".")).length!==0?(Number(a.split(".")[1])||0)*1E3:0} +function Jq(a){return a?(Number(a.i)||0)*1E3:0}function Kq(a){var b=ar(a.split("."));return b.length===0?null:{version:b[0],W:b[2],timestamp:(Number(b[1])||0)*1E3,labels:b.slice(3)}}function ar(a){return a.length<3||a[0]!=="GCL"&&a[0]!=="1"||!/^\d+$/.test(a[1])||!uq.test(a[2])?[]:a} +function br(a,b,c,d,e){if(Array.isArray(b)&&Po(B)){var f=Eq(e),g=function(){for(var k={},m=0;mb}; +var pr=function(a,b){var c=Ji.ads_pageview=Ji.ads_pageview||{};if(c[a])return!1;(b===void 0?0:b)||(c[a]=!0);return!0},qr=function(a){var b=Ej(a);return Db("gclid dclid gbraid wbraid gclaw gcldc gclha gclgf gclgb _gl".split(" "),b,"0")},yr=function(a,b,c,d,e){var f=Eq(a.prefix);if(pr(f,!0)){var g=Tq(),k=[],m=g.gclid,n=g.dclid,p=g.gclsrc||"aw",q=rr(),r=q.Re,u=q.jk;!m||p!=="aw.ds"&&p!=="aw"&&p!=="ds"&&p!=="3p.ds"||k.push({W:m,Se:p});n&&k.push({W:n,Se:"ds"});k.length===2&&V(147);k.length===0&&g.wbraid&& +k.push({W:g.wbraid,Se:"gb"});k.length===0&&p==="aw.ds"&&k.push({W:"",Se:"aw.ds"});sr(function(){var v=X(tr());if(v){Rp(a);var t=[],w=v?Pp[Sp(a.prefix)]:void 0;w&&t.push("auid="+w);if(X(O.g.N)){e&&t.push("userId="+e);var x=Pl(Kl.vh);if(x===void 0)Ol(Kl.wh,!0);else{var y=Pl(Kl.Ee);t.push("ga_uid="+y+"."+x)}}var A=E.referrer?yj(Ej(E.referrer),"host"):"",C=v||!d?k:[];C.length===0&&(ur.test(A)||vr.test(A))&&C.push({W:"",Se:""});if(C.length!==0||r!==void 0){A&&t.push("ref="+encodeURIComponent(A));var D= +wr();t.push("url="+encodeURIComponent(D));t.push("tft="+qb());var I=Hc();I!==void 0&&t.push("tfd="+Math.round(I));var J=Nn(!0);t.push("frm="+J);r!==void 0&&t.push("gad_source="+encodeURIComponent(r));u!==void 0&&t.push("gad_source_src="+encodeURIComponent(u.toString()));if(!c){var H={};c=Dm(tm(new sm(0),(H[O.g.ma]=Ym.j[O.g.ma],H)))}t.push("gtm="+No({ya:b}));Ao()&&t.push("gcs="+Bo());t.push("gcd="+Fo(c));Io()&&t.push("dma_cps="+Go());t.push("dma="+Ho());zo(c)?t.push("npa=0"):t.push("npa=1");Ko()&& +t.push("_ng=1");Xn(mo())&&t.push("tcfd="+Jo());var U=to();U&&t.push("gdpr="+U);var M=so();M&&t.push("gdpr_consent="+M);R(19)&&t.push("apve=0");R(99)&&Dp(!1)._up&&t.push("gtm_up=1");dj()&&t.push("tag_exp="+dj());if(C.length>0)for(var aa=0;aa0)return f?["0"]:g}var k=Fq(a,e);return k?Aq(k):[]},sr=function(a){var b= +tr();Fl(function(){a();X(b)||gl(a,b)},b)},tr=function(){return[O.g.O,O.g.N]},ur=/^(?:www\.)?google(?:\.com?)?(?:\.[a-z]{2}t?)?$/,vr=/^www\.googleadservices\.com$/,zr=/^gad_source[_=](\d+)$/;function Er(){Ji.dedupe_gclid||(Ji.dedupe_gclid=hp());return Ji.dedupe_gclid};var Fr=/^(www\.)?google(\.com?)?(\.[a-z]{2}t?)?$/,Gr=/^www.googleadservices.com$/;function Hr(a){a||(a=Ir());return a.yn?!1:a.tm||a.vm||a.ym||a.wm||a.Re||a.dm||a.xm||a.im?!0:!1}function Ir(){var a={},b=Dp(!0);a.yn=!!b._up;var c=Tq();a.tm=c.aw!==void 0;a.vm=c.dc!==void 0;a.ym=c.wbraid!==void 0;a.wm=c.gbraid!==void 0;a.xm=c.gclsrc==="aw.ds";a.Re=rr().Re;var d=E.referrer?yj(Ej(E.referrer),"host"):"";a.im=Fr.test(d);a.dm=Gr.test(d);return a};var Jr=RegExp("^UA-\\d+-\\d+%3A[\\w-]+(?:%2C[\\w-]+)*(?:%3BUA-\\d+-\\d+%3A[\\w-]+(?:%2C[\\w-]+)*)*$"),Kr=/^~?[\w-]+(?:\.~?[\w-]+)*$/,Lr=/^\d+\.fls\.doubleclick\.net$/,Mr=/;gac=([^;?]+)/,Nr=/;gacgb=([^;?]+)/; +function Or(a,b){if(Lr.test(E.location.host)){var c=E.location.href.match(b);return c&&c.length===2&&c[1].match(Jr)?decodeURIComponent(c[1]):""}for(var d=[],e=l(Object.keys(a)),f=e.next();!f.done;f=e.next()){for(var g=f.value,k=[],m=a[g],n=0;n0?d.join(";"):""} +function Pr(a,b,c){for(var d=yq(xq())?oq("_gac_gb",!0):{},e=[],f=!1,g=l(Object.keys(d)),k=g.next();!k.done;k=g.next()){var m=k.value,n=kr("_gac_gb_"+m,a,b,c);f=f||n.length!==0&&n.some(function(p){return p===1});e.push(m+":"+n.join(","))}return{bm:f?e.join(";"):"",am:Or(d,Nr)}}function Qr(a){var b=E.location.href.match(new RegExp(";"+a+"=([^;?]+)"));return b&&b.length===2&&b[1].match(Kr)?b[1]:void 0} +function Rr(a){var b=$a(11),c={},d,e,f;Lr.test(E.location.host)&&(d=Qr("gclgs"),e=Qr("gclst"),b&&(f=Qr("gcllp")));if(d&&e&&(!b||f))c.Mh=d,c.Oh=e,c.Nh=f;else{var g=qb(),k=Gq((a||"_gcl")+"_gs"),m=k.map(function(q){return q.W}),n=k.map(function(q){return g-q.timestamp}),p=[];b&&(p=k.map(function(q){return q.Jd}));m.length>0&&n.length>0&&(!b||p.length>0)&&(c.Mh=m.join("."),c.Oh=n.join("."),b&&p.length>0&&(c.Nh=p.join(".")))}return c} +function Sr(a,b,c,d){d=d===void 0?!1:d;if(Lr.test(E.location.host)){var e=Qr(c);if(e)return[{W:e}]}else{if(b==="gclid"){var f=(a||"_gcl")+"_aw";return d?Pq(f):Bq(f)}if(b==="wbraid")return Bq((a||"_gcl")+"_gb");if(b==="braids")return Dq({prefix:a})}return[]}function Tr(a){return Sr(a,"gclid","gclaw").map(function(b){return b.W}).join(".")} +function Ur(a){var b=Sr(a,"gclid","gclaw",!0),c=b.map(function(f){return f.W}).join("."),d=b.map(function(f){return f.Pa||0}).join("."),e=b.map(function(f){for(var g=0,k=l(f.Sc||[]),m=k.next();!m.done;m=k.next()){var n=m.value;n===1&&(g|=1);n===2&&(g|=2)}return g.toString()}).join(".");return{W:c,kk:d,lk:e}}function Vr(a){return Sr(a,"braids","gclgb").map(function(b){return b.W}).join(".")}function Wr(a){return Lr.test(E.location.host)?!(Qr("gclaw")||Qr("gac")):or(a)} +function Xr(a,b,c){var d;d=c?lr(a,b):kr((b&&b.prefix||"_gcl")+"_gb",a,b);return d.length===0||d.every(function(e){return e===0})?"":d.join(".")};function Yr(){var a=B.__uspapi;if(bb(a)){var b="";try{a("getUSPData",1,function(c,d){if(d&&c){var e=c.uspString;e&&RegExp("^[\\da-zA-Z-]{1,20}$").test(e)&&(b=e)}})}catch(c){}return b}}; +var bs=function(a){if(a.eventName===O.g.ba&&a.metadata.hit_type==="page_view")if(R(20)){a.metadata.redact_click_ids=W(a.m,O.g.ia)!=null&&W(a.m,O.g.ia)!==!1&&!X([O.g.O,O.g.N]);var b=Zr(a),c=W(a.m,O.g.ra)!==!1;c||(a.j[O.g.bj]="1");var d=Eq(b.prefix),e=a.metadata.is_server_side_destination;if(!a.metadata.consent_updated&&!a.metadata.user_id_updated){var f=W(a.m,O.g.cb),g=W(a.m,O.g.sa)||{};$r({Bd:c,Kd:g,Pd:f,rc:b});if(!e&&!pr(d)){a.isAborted=!0;return}}if(e)a.isAborted=!0;else{a.j[O.g.Cc]=O.g.ac;if(a.metadata.consent_updated)a.j[O.g.Cc]= +O.g.Rk,a.j[O.g.Yb]="1";else if(a.metadata.user_id_updated)a.j[O.g.Cc]=O.g.Wk;else{var k=Tq();a.j[O.g.Td]=k.gclid;a.j[O.g.be]=k.dclid;a.j[O.g.Wi]=k.gclsrc;a.j[O.g.Td]||a.j[O.g.be]||(a.j[O.g.zf]=k.wbraid,a.j[O.g.Ag]=k.gbraid);a.j[O.g.Fa]=E.referrer?yj(Ej(E.referrer),"host"):"";a.j[O.g.wa]=wr();if(R(23)&&jc){var m=yj(Ej(jc),"host");m&&(a.j[O.g.uj]=m)}var n=rr(),p=n.jk;a.j[O.g.Pi]=n.Re;a.j[O.g.Qi]=p;a.j[O.g.Nb]=Nn(!0);var q=Ir();Hr(q)&&(a.j[O.g.md]="1");a.j[O.g.Yi]=Er();Dp(!1)._up==="1"&&(a.j[O.g.oj]= +"1")}il=!0;var r=X([O.g.O,O.g.N]);r&&(R(24)&&(a.j[O.g.ib]=as()),c&&(Rp(b),a.j[O.g.Lb]=Pp[Sp(b.prefix)]));a.j[O.g.rb]=void 0;a.j[O.g.Za]=void 0;if(!a.j[O.g.Td]&&!a.j[O.g.be]&&Wr(d)){var u=Cq(b);u.length>0&&(a.j[O.g.rb]=u.join("."))}else if(!a.j[O.g.zf]&&r){var v=Aq(d+"_aw");v.length>0&&(a.j[O.g.Za]=v.join("."))}R(27)&&(a.j[O.g.pj]=Ic());a.m.isGtmEvent&&(a.m.j[O.g.ma]=Ym.j[O.g.ma]);zo(a.m)?a.j[O.g.Tb]=!1:a.j[O.g.Tb]=!0;a.metadata.add_tag_timing=!0;var t=Yr();t!==void 0&&(a.j[O.g.wd]=t||"error");var w= +to();w&&(a.j[O.g.ic]=w);var x=so();x&&(a.j[O.g.mc]=x);a.metadata.speculative=!1}}else a.isAborted=!0},Zr=function(a){var b={prefix:W(a.m,O.g.eb)||W(a.m,O.g.Na),domain:W(a.m,O.g.Ra),Fb:W(a.m,O.g.Sa),flags:W(a.m,O.g.ab)};a.m.isGtmEvent&&(b.path=W(a.m,O.g.vb));return b},cs=function(a,b){var c,d,e,f,g,k,m,n;c=a.Bd;d=a.Kd;e=a.Pd;f=a.ya;g=a.m;k=a.Md;m=a.Zn;n=a.Ik;$r({Bd:c,Kd:d,Pd:e,rc:b});c&&m!==!0&&(n!=null?n=String(n):n=void 0,yr(b,f,g,k,n))},$r=function(a){var b,c,d,e;b=a.Bd;c=a.Kd;d=a.Pd;e=a.rc;b&& +(Np(c[O.g.Hc],!!c[O.g.X])&&(Yq(ds,e),$q(e),Zp(e)),R(89)||R(117)?Wq(e):Uq(e),dr(ds,e),er(e));c[O.g.X]&&(br(ds,c[O.g.X],c[O.g.Pb],!!c[O.g.yb],e.prefix),cr(c[O.g.X],c[O.g.Pb],!!c[O.g.yb],e.prefix),$p(Sp(e.prefix),c[O.g.X],c[O.g.Pb],!!c[O.g.yb],e),$p("FPAU",c[O.g.X],c[O.g.Pb],!!c[O.g.yb],e));d&&(R(78)?gr(es):gr(fs));ir(fs)},gs=function(a,b,c,d){var e,f,g;e=a.Jk;f=a.callback;g=a.qk;if(typeof f==="function")if(e===O.g.Za&&g===void 0){var k=d(b.prefix,c);k.length===0?f(void 0):k.length===1?f(k[0]):f(k)}else e=== +O.g.Lb?(V(65),Rp(b,!1),f(Pp[Sp(b.prefix)])):f(g)},ds=["aw","dc","gb"],fs=["aw","dc","gb","ag"],es=["aw","dc","gb","ag","gad_source"];function hs(a){var b=W(a.m,O.g.Ob),c=W(a.m,O.g.jc);b&&!c?(a.eventName!==O.g.ba&&a.eventName!==O.g.Uc&&V(131),a.isAborted=!0):!b&&c&&(V(132),a.isAborted=!0)}function is(a){var b=X(O.g.O)?Ji.pscdl:"denied";b!=null&&(a.j[O.g.Df]=b)}function js(a){var b=Nn(!0);a.j[O.g.Nb]=b} +function ks(a){Ko()&&(a.j[O.g.Fc]=1)}function as(){var a=E.title;if(a===void 0||a==="")return"";var b=function(d){try{return decodeURIComponent(d),!0}catch(e){return!1}};a=encodeURIComponent(a);for(var c=256;c>0&&!b(a.substring(0,c));)c--;return decodeURIComponent(a.substring(0,c))}function ls(a){ms(a,"ce",W(a.m,O.g.Sa))}function ms(a,b,c){a.j[O.g.xd]||(a.j[O.g.xd]={});a.j[O.g.xd][b]=c};function ss(a,b,c,d){var e=rc(),f;if(e===1)a:{var g=Vi;g=g.toLowerCase();for(var k="https://"+g,m="http://"+g,n=1,p=E.getElementsByTagName("script"),q=0;q=0;e--){var f=b[e],g=f.url&&f.url.match("[?&#]"+a+"=([^&#]+)");if(g&&g.length===2)return g[1]}};var Ms,Ns=!1;function Os(){Ns=!0;Ms=Ms||{}}function Ps(a){Ns||Os();return Ms[a]}function Qs(){var a=B.screen;return{width:a?a.width:0,height:a?a.height:0}} +function Rs(a){if(E.hidden)return!0;var b=a.getBoundingClientRect();if(b.top===b.bottom||b.left===b.right||!B.getComputedStyle)return!0;var c=B.getComputedStyle(a,null);if(c.visibility==="hidden")return!0;for(var d=a,e=c;d;){if(e.display==="none")return!0;var f=e.opacity,g=e.filter;if(g){var k=g.indexOf("opacity(");k>=0&&(g=g.substring(k+8,g.indexOf(")",k)),g.charAt(g.length-1)==="%"&&(g=g.substring(0,g.length-1)),f=String(Math.min(Number(g),Number(f))))}if(f!==void 0&&Number(f)<=0)return!0;(d=d.parentElement)&& +(e=B.getComputedStyle(d,null))}return!1} +var Ts=function(a){var b=Ss(),c=b.height,d=b.width,e=a.getBoundingClientRect(),f=e.bottom-e.top,g=e.right-e.left;return f&&g?(1-Math.min((Math.max(0-e.left,0)+Math.max(e.right-d,0))/g,1))*(1-Math.min((Math.max(0-e.top,0)+Math.max(e.bottom-c,0))/f,1)):0},Ss=function(){var a=E.body,b=E.documentElement||a&&a.parentElement,c,d;if(E.compatMode&&E.compatMode!=="BackCompat")c=b?b.clientHeight:0,d=b?b.clientWidth:0;else{var e=function(f,g){return f&&g?Math.min(f,g):Math.max(f,g)};c=e(b?b.clientHeight:0,a? +a.clientHeight:0);d=e(b?b.clientWidth:0,a?a.clientWidth:0)}return{width:d,height:c}};var Ws=function(a){if(Us){if(a>=0&&a1?c[d]=1:c[d]<0&&(c[d]=0);if(Us){var e=!1;F(function(){e||Xs(a,b,c)()});return Ys(function(f){e=!0;for(var g={We:0};g.We0,rootBounds:n,target:k,time:qb()};F(function(){a(p)})}for(var e=[],f=[],g=0;ge[k])for(;f[k]=c[f[k]+1];)d(b[k],m),f[k]++; +else if(m=0&&m<=c[f[k]];)d(b[k],m),f[k]--;e[k]=m}}},Ys=function(a,b,c){for(var d=new B.IntersectionObserver(a,{threshold:c}),e=0;e10&&(e="3")}!a.pg&&g&&(f=[g]);for(var p=0;p:nth-child("+e.toString()+")"}else d="";c=d}b=c}return b},et=function(a){for(var b=[],c=0;c=0}else k=!1;k||b.push({element:d,Z:g})}}}return b}, +dt=function(){var a=[],b=E.body;if(!b)return{elements:a,status:"4"};for(var c=b.querySelectorAll("*"),d=0;d=0)&&e.children instanceof HTMLCollection){for(var f=!1,g=0;g=0)){f=!0;break}(!f||R(29)&&vt.indexOf(e.tagName)!==-1)&&a.push(e)}}return{elements:a,status:c.length>1E4?"2":"1"}},wt=!1;var st=/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i,$s=/@(gmail|googlemail)\./i,rt=/support|noreply/i,tt="SCRIPT STYLE IMG SVG PATH BR NOSCRIPT TEXTAREA".split(" "),ut=["BR"],mt={vc:"1",Be:"2",we:"3",ye:"4",ug:"5",sh:"6",eg:"7"},ct={},vt=["INPUT","SELECT"];var Mt=function(a,b,c){a.j[O.g.De]||(a.j[O.g.De]={});a.j[O.g.De][b]=c},Ot=function(a,b){var c=Nt(a,O.g.ie,a.m.C[O.g.ie]);if(c&&c[b||a.eventName]!==void 0)return c[b||a.eventName]},Pt=function(a){var b=a.metadata.user_data;if(Uc(b))return b},Qt=function(a){if(a.metadata.is_merchant_center||!Lj(a.m))return!1;if(!W(a.m,O.g.rd)){var b=W(a.m,O.g.Dc);return b===!0||b==="true"}return!0},Rt=function(a){return Nt(a,O.g.Gc,W(a.m,O.g.Gc))||!!Nt(a,"google_ng",!1)};var Lf;var St=Number('')||5,Tt=Number('')||50,Ut=fb();var Zt={El:Number('')||500,ql:Number('')||5E3,Kj:Number('20')||10,Qk:Number('')||5E3};function $t(a){return a.performance&&a.performance.now()||Date.now()} +var au=function(a,b){var c;return c};var bu;function iu(){var a=Of(Lf.j,"",function(){return{}});try{return a("internal_sw_allowed"),!0}catch(b){return!1}} +function ju(a,b,c){c=c===void 0?!1:c;} +var ku=function(a,b,c,d){}; +function lu(a,b,c,d,e){} +function mu(a,b,c,d){}var nu=function(a){for(var b=[],c=0,d=0;d>6|192:((e&64512)==55296&&d+1>18|240,b[c++]=e>>12&63|128):b[c++]=e>>12|224,b[c++]=e>>6&63|128),b[c++]=e&63|128)}return b};An();Jn()||xn("iPod");xn("iPad");!xn("Android")||Bn()||An()||zn()||xn("Silk");Bn();!xn("Safari")||Bn()||(yn()?0:xn("Coast"))||zn()||(yn()?0:xn("Edge"))||(yn()?wn("Microsoft Edge"):xn("Edg/"))||(yn()?wn("Opera"):xn("OPR"))||An()||xn("Silk")||xn("Android")||Kn();var ou={},pu=null,qu=function(a){for(var b=[],c=0,d=0;d255&&(b[c++]=e&255,e>>=8);b[c++]=e}var f=4;f===void 0&&(f=0);if(!pu){pu={};for(var g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),k=["+/=","+/","-_=","-_.","-_"],m=0;m<5;m++){var n=g.concat(k[m].split(""));ou[m]=n;for(var p=0;p>2],D=r[(x&3)<<4|y>>4],I=r[(y&15)<<2|A>>6],J=r[A&63];u[w++]=""+C+D+I+J}var H=0,U=v;switch(b.length-t){case 2:H=b[t+1],U=r[(H&15)<<2]||v;case 1:var M=b[t];u[w]=""+r[M>>2]+r[(M&3)<<4|H>>4]+U+v}return u.join("")};var ru="platform platformVersion architecture model uaFullVersion bitness fullVersionList wow64".split(" ");function su(a){var b;return(b=a.google_tag_data)!=null?b:a.google_tag_data={}}function tu(){var a=B.google_tag_data,b;if(a!=null&&a.uach){var c=a.uach,d=Object.assign({},c);c.fullVersionList&&(d.fullVersionList=c.fullVersionList.slice(0));b=d}else b=null;return b}function uu(){var a,b;return(b=(a=B.google_tag_data)==null?void 0:a.uach_promise)!=null?b:null} +function vu(a){var b,c;return typeof((b=a.navigator)==null?void 0:(c=b.userAgentData)==null?void 0:c.getHighEntropyValues)==="function"}function wu(){var a=B;if(!vu(a))return null;var b=su(a);if(b.uach_promise)return b.uach_promise;var c=a.navigator.userAgentData.getHighEntropyValues(ru).then(function(d){b.uach!=null||(b.uach=d);return d});return b.uach_promise=c}; +var yu=function(a,b){if(a){var c=xu(a);Object.assign(b.j,c)}},xu=function(a){var b={};b[O.g.Tf]=a.architecture;b[O.g.Uf]=a.bitness;a.fullVersionList&&(b[O.g.Vf]=a.fullVersionList.map(function(c){return encodeURIComponent(c.brand||"")+";"+encodeURIComponent(c.version||"")}).join("|"));b[O.g.Wf]=a.mobile?"1":"0";b[O.g.Xf]=a.model;b[O.g.Yf]=a.platform;b[O.g.Zf]=a.platformVersion;b[O.g.cg]=a.wow64?"1":"0";return b},Au=function(a){var b=zu.xn,c=function(g,k){try{a(g,k)}catch(m){}},d=tu();if(d)c(d);else{var e= +uu();if(e){b=Math.min(Math.max(isFinite(b)?b:0,0),1E3);var f=B.setTimeout(function(){c.Ze||(c.Ze=!0,V(106),c(null,Error("Timeout")))},b);e.then(function(g){c.Ze||(c.Ze=!0,V(104),B.clearTimeout(f),c(g))}).catch(function(g){c.Ze||(c.Ze=!0,V(105),B.clearTimeout(f),c(null,g))})}else c(null)}},Cu=function(){if(vu(B)&&(Bu=qb(),!uu())){var a=wu();a&&(a.then(function(){V(95)}),a.catch(function(){V(96)}))}},Bu;function Du(a){var b;b=b===void 0?document:b;var c;return!((c=b.featurePolicy)==null||!c.allowedFeatures().includes(a))};function Eu(){return Du("join-ad-interest-group")&&bb(gc.joinAdInterestGroup)} +function Fu(a,b){var c=Za[3]===void 0?1:Za[3],d='iframe[data-tagging-id="'+b+'"]',e=[];try{if(c===1){var f=E.querySelector(d);f&&(e=[f])}else e=Array.from(E.querySelectorAll(d))}catch(q){}var g;a:{try{g=E.querySelectorAll('iframe[allow="join-ad-interest-group"][data-tagging-id*="-"]');break a}catch(q){}g=void 0}var k=g,m=((k==null?void 0:k.length)||0)>=(Za[2]===void 0?50:Za[2]),n;if(n=e.length>=1){var p=Number(e[e.length-1].dataset.loadTime);p!==void 0&&qb()-p<(Za[1]===void 0?6E4:Za[1])?(Va("TAGGING", +9),n=!0):n=!1}if(!n){if(c===1)if(e.length>=1)Gu(e[0]);else{if(m){Va("TAGGING",10);return}}else e.length>=c?Gu(e[0]):m&&Gu(k[0]);sc(a,void 0,{allow:"join-ad-interest-group"},{taggingId:b,loadTime:qb()})}}function Gu(a){try{a.parentNode.removeChild(a)}catch(b){}}function Hu(){return"https://td.doubleclick.net"};function Iu(a){var b=a.location.href;if(a===a.top)return{url:b,Gm:!0};var c=!1,d=a.document;d&&d.referrer&&(b=d.referrer,a.parent===a.top&&(c=!0));var e=a.location.ancestorOrigins;if(e){var f=e[e.length-1];f&&b.indexOf(f)===-1&&(c=!1,b=f)}return{url:b,Gm:c}}; +var Av=function(a,b){var c={},d=function(f,g){var k;k=g===!0?"1":g===!1?"0":encodeURIComponent(String(g));c[f]=k};ib(a.j,function(f,g){var k=zv[f];k&&g!==void 0&&g!==""&&(!a.metadata.redact_click_ids||f!==O.g.Td&&f!==O.g.be&&f!==O.g.zf&&f!==O.g.Ag||(g="0"),d(k,g))});d("gtm",No({ya:a.metadata.source_canonical_id}));Ao()&&d("gcs",Bo());d("gcd",Fo(a.m));Io()&&d("dma_cps",Go());d("dma",Ho());Xn(mo())&&d("tcfd",Jo());dj()&&d("tag_exp",dj());if(a.metadata.add_tag_timing){d("tft",qb());var e=Hc();e!==void 0&& +d("tfd",Math.round(e))}R(20)&&d("apve","1");R(21)&&d("apvf",Fc()?R(22)?"f":"sb":"nf");b(c)},Bv=function(a){Av(a,function(b){if(a.metadata.hit_type==="page_view"){var c=[];ib(b,function(e,f){c.push(e+"="+f)});var d=Mj(X([O.g.O,O.g.N])?"https://www.google.com":"https://pagead2.googlesyndication.com",!0)+"/ccm/collect?"+c.join("&");R(21)&&R(22)&&Fc()?Ec(d,void 0,{noFallback:!0}):Bc(d);if(bb(a.m.onSuccess))a.m.onSuccess()}})},Cv={},zv=(Cv[O.g.Yb]="gcu",Cv[O.g.rb]="gclgb",Cv[O.g.Za]="gclaw",Cv[O.g.Pi]= +"gad_source",Cv[O.g.Qi]="gad_source_src",Cv[O.g.Td]="gclid",Cv[O.g.Wi]="gclsrc",Cv[O.g.Ag]="gbraid",Cv[O.g.zf]="wbraid",Cv[O.g.Lb]="auid",Cv[O.g.Yi]="rnd",Cv[O.g.bj]="ncl",Cv[O.g.Gg]="gcldc",Cv[O.g.be]="dclid",Cv[O.g.fb]="edid",Cv[O.g.Cc]="en",Cv[O.g.ic]="gdpr",Cv[O.g.hb]="gdid",Cv[O.g.Fc]="_ng",Cv[O.g.oj]="gtm_up",Cv[O.g.Nb]="frm",Cv[O.g.md]="lps",Cv[O.g.pe]="did",Cv[O.g.pj]="navt",Cv[O.g.wa]="dl",Cv[O.g.Fa]="dr",Cv[O.g.ib]="dt",Cv[O.g.uj]="scrsrc",Cv[O.g.Qf]="ga_uid",Cv[O.g.mc]="gdpr_consent",Cv[O.g.Ca]= +"uid",Cv[O.g.wd]="us_privacy",Cv[O.g.Tb]="npa",Cv);var Dv={J:{vi:"ads_conversion_hit",Qd:"container_execute_start",yi:"container_setup_end",rg:"container_setup_start",wi:"container_blocking_end",xi:"container_execute_end",zi:"container_yield_end",sg:"container_yield_start",Aj:"event_execute_end",zj:"event_evaluation_end",ph:"event_evaluation_start",Bj:"event_setup_end",ve:"event_setup_start",Dj:"ga4_conversion_hit",Ae:"page_load",On:"pageview",oc:"snippet_load",Wj:"tag_callback_error",Xj:"tag_callback_failure",Yj:"tag_callback_success",Zj:"tag_execute_end", +yd:"tag_execute_start"}};function Ev(){function a(c,d){var e=Wa(d);e&&b.push([c,e])}var b=[];a("u","GTM");a("ut","TAGGING");a("h","HEALTH");return b};var Fv=!1;function nw(a,b){} +function ow(a,b){}function pw(a,b){} +function qw(a,b){}function rw(){var a={};return a} +function fw(a){a=a===void 0?!0:a;var b={};return b} +function sw(){}function tw(a,b){} +function uw(a,b,c){} +function vw(){}function ww(a,b){var c=B,d,e=c.GooglebQhCsO;e||(e={},c.GooglebQhCsO=e);d=e;if(d[a])return!1;d[a]=[];d[a][0]=b;return!0};function xw(a,b,c,d){var e=Fn(a,"fmt");if(b){var f=Fn(a,"random"),g=Fn(a,"label")||"";if(!f)return!1;var k=qu(decodeURIComponent(g.replace(/\+/g," "))+":"+decodeURIComponent(f.replace(/\+/g," ")));if(!ww(k,b))return!1}e&&Number(e)!==4&&(a=Hn(a,"rfmt",e));var m=Hn(a,"fmt",4);qc(m,function(){B.google_noFurtherRedirects&&b&&(B.google_noFurtherRedirects=null,b())},c,d,E.getElementsByTagName("script")[0].parentElement||void 0);return!0};function Nw(a,b){if(data.entities){var c=data.entities[a];if(c)return c[b]}};function Ow(a,b,c){c=c===void 0?!1:c;Pw().addRestriction(0,a,b,c)}function Qw(a,b,c){c=c===void 0?!1:c;Pw().addRestriction(1,a,b,c)}function Rw(){var a=ok();return Pw().getRestrictions(1,a)}var Sw=function(){this.container={};this.j={}},Tw=function(a,b){var c=a.container[b];c||(c={_entity:{internal:[],external:[]},_event:{internal:[],external:[]}},a.container[b]=c);return c}; +Sw.prototype.addRestriction=function(a,b,c,d){d=d===void 0?!1:d;if(!d||!this.j[b]){var e=Tw(this,b);a===0?d?e._entity.external.push(c):e._entity.internal.push(c):a===1&&(d?e._event.external.push(c):e._event.internal.push(c))}}; +Sw.prototype.getRestrictions=function(a,b){var c=Tw(this,b);if(a===0){var d,e;return[].concat(ua((c==null?void 0:(d=c._entity)==null?void 0:d.internal)||[]),ua((c==null?void 0:(e=c._entity)==null?void 0:e.external)||[]))}if(a===1){var f,g;return[].concat(ua((c==null?void 0:(f=c._event)==null?void 0:f.internal)||[]),ua((c==null?void 0:(g=c._event)==null?void 0:g.external)||[]))}return[]}; +Sw.prototype.getExternalRestrictions=function(a,b){var c=Tw(this,b),d,e;return a===0?(c==null?void 0:(d=c._entity)==null?void 0:d.external)||[]:(c==null?void 0:(e=c._event)==null?void 0:e.external)||[]};Sw.prototype.removeExternalRestrictions=function(a){var b=Tw(this,a);b._event&&(b._event.external=[]);b._entity&&(b._entity.external=[]);this.j[a]=!0};function Pw(){var a=Ji.r;a||(a=new Sw,Ji.r=a);return a};var Uw=new RegExp(/^(.*\.)?(google|youtube|blogger|withgoogle)(\.com?)?(\.[a-z]{2})?\.?$/),Vw={cl:["ecl"],customPixels:["nonGooglePixels"],ecl:["cl"],ehl:["hl"],gaawc:["googtag"],hl:["ehl"],html:["customScripts","customPixels","nonGooglePixels","nonGoogleScripts","nonGoogleIframes"],customScripts:["html","customPixels","nonGooglePixels","nonGoogleScripts","nonGoogleIframes"],nonGooglePixels:[],nonGoogleScripts:["nonGooglePixels"],nonGoogleIframes:["nonGooglePixels"]},Ww={cl:["ecl"],customPixels:["customScripts", +"html"],ecl:["cl"],ehl:["hl"],gaawc:["googtag"],hl:["ehl"],html:["customScripts"],customScripts:["html"],nonGooglePixels:["customPixels","customScripts","html","nonGoogleScripts","nonGoogleIframes"],nonGoogleScripts:["customScripts","html"],nonGoogleIframes:["customScripts","html","nonGoogleScripts"]},Xw="google customPixels customScripts html nonGooglePixels nonGoogleScripts nonGoogleIframes".split(" "); +function Yw(){var a=lj("gtm.allowlist")||lj("gtm.whitelist");a&&V(9);Pi&&(a=["google","gtagfl","lcl","zone"]);Uw.test(B.location&&B.location.hostname)&&(Pi?V(116):(V(117),Zw&&(a=[],window.console&&window.console.log&&window.console.log("GTM blocked. See go/13687728."))));var b=a&&ub(nb(a),Vw),c=lj("gtm.blocklist")||lj("gtm.blacklist");c||(c=lj("tagTypeBlacklist"))&&V(3);c?V(8):c=[];Uw.test(B.location&&B.location.hostname)&&(c=nb(c),c.push("nonGooglePixels","nonGoogleScripts","sandboxedScripts")); +nb(c).indexOf("google")>=0&&V(2);var d=c&&ub(nb(c),Ww),e={};return function(f){var g=f&&f[Le.oa];if(!g||typeof g!=="string")return!0;g=g.replace(/^_*/,"");if(e[g]!==void 0)return e[g];var k=Zi[g]||[],m=!0;if(a){var n;if(n=m)a:{if(b.indexOf(g)<0)if(k&&k.length>0)for(var p=0;p=0;if(r)q=r;else{var u=gb(d,k||[]);u&&V(10);q=u}}var v=!m||q;v||!(k.indexOf("sandboxedScripts")>=0)||b&&b.indexOf("sandboxedScripts")!== +-1||(v=gb(d,Xw));return e[g]=v}}var Zw=!1;Zw=!0;function $w(){fk&&Ow(ok(),function(a){var b=vf(a.entityId),c;if(yf(b)){var d=b[Le.oa];if(!d)throw Error("Error: No function name given for function call.");var e=nf[d];c=!!e&&!!e.runInSiloedMode}else c=!!Nw(b[Le.oa],4);return c})}function ax(a,b,c,d,e){if(!bx()){var f=d.siloed?kk(a):a;if(!xk(f)){d.siloed&&zk({ctid:f,isDestination:!1});var g=rk();bk().container[f]={state:1,context:d,parent:g};ak({ctid:f,isDestination:!1},e);var k=cx(a);if(R(70)&&fj())qc(ej()+"/"+k);else{var m=vb(a,"GTM-"),n=Kj(),p=c?"/gtag/js":"/gtm.js",q=Jj(b,p+k);if(!q){var r=Ii.vf+p;n&&jc&&m?(r=jc.replace(/^(?:https?:\/\/)?/i,"").split(/[?#]/)[0],q=ss("https://","http://",r+k)):q=fj()?ej()+"/"+k:ss("https://","http://",r+k)}qc(q)}}}} +function dx(a,b,c,d){if(!bx()){var e=c.siloed?kk(a):a;if(!yk(e))if(!c.siloed&&Ak())bk().destination[e]={state:0,transportUrl:b,context:c,parent:rk()},ak({ctid:e,isDestination:!0},d),V(91);else if(c.siloed&&zk({ctid:e,isDestination:!0}),bk().destination[e]={state:1,context:c,parent:rk()},ak({ctid:e,isDestination:!0},d),R(70)&&fj())qc(ej()+("/gtd"+cx(a,!0)));else{var f="/gtag/destination"+cx(a,!0),g=Jj(b,f);g||(fj()?(f="/gtd"+cx(a,!0),g=ej()+f):g=ss("https://","http://",Ii.vf+f));qc(g)}}} +function cx(a,b){b=b===void 0?!1:b;var c="?id="+encodeURIComponent(a)+"&l="+Ii.ob;if(!vb(a,"GTM-")||b)c+="&cx=c";R(82)&&(c+=">m="+No());Kj()&&(c+="&sign="+Ii.uh);var d=cj.j;d===1?c+="&fps=fc":d===2&&(c+="&fps=fe");return c}function bx(){if(Lo()){return!0}return!1};var ex=!1,fx=0,gx=[];function hx(a){if(!ex){var b=E.createEventObject,c=E.readyState==="complete",d=E.readyState==="interactive";if(!a||a.type!=="readystatechange"||c||!b&&d){ex=!0;for(var e=0;e=0)&&c.push(e.listener)});return c}; +function lx(a,b,c){return{entityType:a,indexInOriginContainer:b,nameInOriginContainer:c,originContainerId:mk()}};var nx=function(a,b){this.j=!1;this.K=[];this.eventData={tags:[]};this.P=!1;this.C=this.H=0;mx(this,a,b)},ox=function(a,b,c,d){if(Li.hasOwnProperty(b)||b==="__zone")return-1;var e={};Uc(d)&&(e=Vc(d,e));e.id=c;e.status="timeout";return a.eventData.tags.push(e)-1},px=function(a,b,c,d){var e=a.eventData.tags[b];e&&(e.status=c,e.executionTime=d)},qx=function(a){if(!a.j){for(var b=a.K,c=0;c=a.H&&qx(a)})},sx=function(a){a.P=!0;a.C>=a.H&&qx(a)};var tx={};function ux(){return B[vx()]} +function vx(){return B.GoogleAnalyticsObject||"ga"}function yx(){var a=mk();} +function zx(a,b){return function(){var c=ux(),d=c&&c.getByName&&c.getByName(a);if(d){var e=d.get("sendHitTask");d.set("sendHitTask",function(f){var g=f.get("hitPayload"),k=f.get("hitCallback"),m=g.indexOf("&tid="+b)<0;m&&(f.set("hitPayload",g.replace(/&tid=UA-[0-9]+-[0-9]+/,"&tid="+b),!0),f.set("hitCallback",void 0,!0));e(f);m&&(f.set("hitPayload",g,!0),f.set("hitCallback",k,!0),f.set("_x_19",void 0,!0),e(f))})}}}var Ex=["es","1"],Fx={},Gx={};function Hx(a,b){if(Tj){var c;c=b.match(/^(gtm|gtag)\./)?encodeURIComponent(b):"*";Fx[a]=[["e",c],["eid",a]];Qm(a)}}function Ix(a){var b=a.eventId,c=a.Tc;if(!Fx[b])return[];var d=[];Gx[b]||d.push(Ex);d.push.apply(d,ua(Fx[b]));c&&(Gx[b]=!0);return d};var Jx={},Kx={},Lx={};function Mx(a,b,c,d){Tj&&R(95)&&((d===void 0?0:d)?(Lx[b]=Lx[b]||0,++Lx[b]):c!==void 0?(Kx[a]=Kx[a]||{},Kx[a][b]=Math.round(c)):(Jx[a]=Jx[a]||{},Jx[a][b]=(Jx[a][b]||0)+1))}function Nx(a){var b=a.eventId,c=a.Tc,d=Jx[b]||{},e=[],f;for(f in d)d.hasOwnProperty(f)&&e.push(""+f+d[f]);c&&delete Jx[b];return e.length?[["md",e.join(".")]]:[]} +function Ox(a){var b=a.eventId,c=a.Tc,d=Kx[b]||{},e=[],f;for(f in d)d.hasOwnProperty(f)&&e.push(""+f+d[f]);c&&delete Kx[b];return e.length?[["mtd",e.join(".")]]:[]}function Px(){for(var a=[],b=l(Object.keys(Lx)),c=b.next();!c.done;c=b.next()){var d=c.value;a.push(""+d+Lx[d])}return a.length?[["mec",a.join(".")]]:[]};var Qx={},Rx={};function Sx(a,b,c){if(Tj&&b){var d=Nj(b);Qx[a]=Qx[a]||[];Qx[a].push(c+d);var e=(yf(b)?"1":"2")+d;Rx[a]=Rx[a]||[];Rx[a].push(e);Qm(a)}}function Tx(a){var b=a.eventId,c=a.Tc,d=[],e=Qx[b]||[];e.length&&d.push(["tr",e.join(".")]);var f=Rx[b]||[];f.length&&d.push(["ti",f.join(".")]);c&&(delete Qx[b],delete Rx[b]);return d};function Ux(a,b,c,d){var e=lf[a],f=Vx(a,b,c,d);if(!f)return null;var g=zf(e[Le.Vj],c,[]);if(g&&g.length){var k=g[0];f=Ux(k.index,{onSuccess:f,onFailure:k.ik===1?b.terminate:f,terminate:b.terminate},c,d)}return f} +function Vx(a,b,c,d){function e(){function w(){ml(3);var J=qb()-I;Sx(c.id,f,"7");px(c.qc,C,"exception",J);R(83)&&uw(c,f,Dv.J.Wj);D||(D=!0,k())}if(f[Le.wl])k();else{var x=xf(f,c,[]),y=x[Le.Ok];if(y!=null)for(var A=0;A +0};var dy=function(a,b){if(!cy)return!1;var c=a["gtm.triggers"]&&String(a["gtm.triggers"]),d=cy.C(a.event,c?String(c).split(","):[]);if(!d.length)return!1;for(var e=0;ee?1:dk?1:g=0){if(e.gi=Wl(g,b),e.gi){var k=lk();eb(k,function(r){return function(u){return r.gi.destinationId===u}}(e))?c.push(g):d.push(g)}}else{var m=vy[g]||[];e.Qh={};m.forEach(function(r){return function(u){r.Qh[u]=!0}}(e));for(var n=ik(),p=0;p=0&&c.splice(d,1)})}function Qy(a){ib(wy,function(b,c){var d=c.indexOf(a);d>=0&&c.splice(d,1)})}var Ry="HA GF G UA AW DC MC".split(" "),Sy=!1,Ty=!1,Uy=!1,Vy=!1;function Wy(a,b){a.hasOwnProperty("gtm.uniqueEventId")||Object.defineProperty(a,"gtm.uniqueEventId",{value:$i()});b.eventId=a["gtm.uniqueEventId"];b.priorityId=a["gtm.priorityId"];return{eventId:b.eventId,priorityId:b.priorityId}}var Xy=void 0,Yy=void 0; +function Zy(a,b,c){var d=Vc(a,null);d.eventId=void 0;d.inheritParentConfig=void 0;Object.keys(b).some(function(f){return b[f]!==void 0})&&V(136);var e=Vc(b,null);Vc(c,e);ry(oy(ik()[0],e),a.eventId,d)}function $y(a){for(var b=l([O.g.rd,O.g.Sb]),c=b.next();!c.done;c=b.next()){var d=c.value,e=a&&a[d]||Ym.j[d];if(e)return e}} +var az=[O.g.rd,O.g.Sb,O.g.Dc,O.g.tb,O.g.zb,O.g.Ca,O.g.sa,O.g.Na,O.g.Ra,O.g.vb],bz={config:function(a,b){var c=Wy(a,b);if(!(a.length<2)&&z(a[1])){var d={};if(a.length>2){if(a[2]!==void 0&&!Uc(a[2])||a.length>3)return;d=a[2]}var e=Wl(a[1],b.isGtmEvent);if(e){var f,g,k;a:{if(!ek.ze){var m=qk(rk());if(Ck(m)){var n=m.parent,p=n.isDestination;k={Um:qk(n),Jm:p};break a}}k=void 0}var q=k;q&&(f=q.Um,g=q.Jm);Hx(c.eventId,"gtag.config");var r=e.destinationId,u=e.id!==r;if(u?lk().indexOf(r)===-1:ik().indexOf(r)=== +-1){if(!b.inheritParentConfig&&!d[O.g.Ob]){var v=$y(d);if(u)dx(r,v,{source:2,fromContainerExecution:b.fromContainerExecution});else if(f!==void 0&&f.containers.indexOf(r)!==-1){var t=d;Xy?Zy(b,t,Xy):Yy||(Yy=Vc(t,null))}else ax(r,v,!0,{source:2,fromContainerExecution:b.fromContainerExecution})}}else{if(f&&(V(128),g&&V(130),b.inheritParentConfig)){var w;var x=d;Yy?(Zy(b,Yy,x),w=!1):(!x[O.g.nc]&&Ni&&Xy||(Xy=Vc(x,null)),w=!0);w&&f.containers&&f.containers.join(",");return}var y=d;if(!Uy&&(Uy=!0,Ty))for(var A= +l(az),C=A.next();!C.done;C=A.next())if(y.hasOwnProperty(C.value)){ll("erc");break}Uj&&!fk&&(ly===1&&(Gk.mcc=!1),ly=2);il=!0;if(Ni&&!u&&!d[O.g.nc]){var D=Vy;Vy=!0;if(D)return}Sy||V(43);if(!b.noTargetGroup)if(u){Qy(e.id);var I=e.id,J=d[O.g.ne]||"default";J=String(J).split(",");for(var H=0;H2){if(!Uc(a[2])&&a[2]!==void 0||a.length>3)return;d=a[2]}var e=d,f={},g=(f.event=c,f);e&&(g.eventModel=Vc(e,null),e[O.g.kd]&&(g.eventCallback=e[O.g.kd]),e[O.g.je]&&(g.eventTimeout=e[O.g.je]));var k=Wy(a,b),m=k.eventId,n=k.priorityId;g["gtm.uniqueEventId"]=m;n&&(g["gtm.priorityId"]=n);if(c==="optimize.callback")return g.eventModel=g.eventModel||{},g;var p;var q=d, +r=q&&q[O.g.kc];r===void 0&&(r=lj(O.g.kc,2),r===void 0&&(r="default"));if(z(r)||Array.isArray(r)){var u;u=b.isGtmEvent?z(r)?[r]:r:r.toString().replace(/\s+/g,"").split(",");var v=xy(u,b.isGtmEvent),t=v.Km,w=v.Nm;if(w.length)for(var x=$y(q),y=0;y0?g.eventModel[O.g.kc]=I.join():delete g.eventModel[O.g.kc];Sy||V(43);b.noGtmEvent===void 0&&b.eventMetadata&&b.eventMetadata.syn_or_mod&&(b.noGtmEvent= +!0);g.eventModel[O.g.jc]&&(b.noGtmEvent=!0);return b.noGtmEvent?void 0:g}}},get:function(a,b){V(53);if(a.length===4&&z(a[1])&&z(a[2])&&bb(a[3])){var c=Wl(a[1],b.isGtmEvent),d=String(a[2]),e=a[3];if(c){Sy||V(43);var f=$y();if(!eb(lk(),function(k){return c.destinationId===k}))dx(c.destinationId,f,{source:4,fromContainerExecution:b.fromContainerExecution});else if(Ry.indexOf(sk(c.prefix))!==-1){il=!0;Wy(a,b);var g={};Vc((g[O.g.xb]=d,g[O.g.Mb]=e,g),null);$m(d,function(k){F(function(){e(k)})},c.id,b)}}}}, +js:function(a,b){if(a.length===2&&a[1].getTime){Sy=!0;var c=Wy(a,b),d=c.eventId,e=c.priorityId,f={};return f.event="gtm.js",f["gtm.start"]=a[1].getTime(),f["gtm.uniqueEventId"]=d,f["gtm.priorityId"]=e,f}},policy:function(a){if(a.length===3&&z(a[1])&&bb(a[2])){if(Mf(a[1],a[2]),V(74),a[1]==="all"){V(75);var b=!1;try{b=a[2](mk(),"unknown",{})}catch(c){}b||V(76)}}else V(73)},set:function(a,b){var c=void 0;a.length===2&&Uc(a[1])?c=Vc(a[1],null):a.length===3&&z(a[1])&&(c={},Uc(a[2])||Array.isArray(a[2])? +c[a[1]]=Vc(a[2],null):c[a[1]]=a[2]);if(c){var d=Wy(a,b),e=d.eventId,f=d.priorityId;Vc(c,null);var g=Vc(c,null);Ym.push("set",[g],void 0,b);c["gtm.uniqueEventId"]=e;f&&(c["gtm.priorityId"]=f);delete c.event;b.overwriteModelFields=!0;return c}}},cz={policy:!0};var ez=function(a){if(dz(a))return a;this.value=a};ez.prototype.getUntrustedMessageValue=function(){return this.value};var dz=function(a){return!a||Sc(a)!=="object"||Uc(a)?!1:"getUntrustedMessageValue"in a};ez.prototype.getUntrustedMessageValue=ez.prototype.getUntrustedMessageValue;var fz=!1,gz=[];function hz(){if(!fz){fz=!0;for(var a=0;ajz&&(jz=q)}oz=!1}}}return!a} +function yz(){if(R(83)){var a=zz();}var b=wz();if(R(83)){}try{var c=mk(),d=B[Ii.ob].hide;if(d&&d[c]!==void 0&&d.end){d[c]=!1;var e=!0,f;for(f in d)if(d.hasOwnProperty(f)&&d[f]=== +!0){e=!1;break}e&&(d.end(),d.end=null)}}catch(g){}return b}function uy(a){if(jz +0){f=[];for(var g=0;gn)for(V(4),c.pruned=!0;this.length>n;)this.shift();var p=typeof m!=="boolean"||m;return wz()&&p};var e=b.slice(0).map(function(f){return a(f)});lz.push.apply(lz,e);if(zz()){if(R(83)){}F(yz)}}var zz=function(){var a=!0;return a},rz=function(a){return B[Ii.ob].push(a)};function Bz(a){if(a==null||a.length===0)return!1;var b=Number(a),c=qb();return bc-9E5}function Cz(a){return a&&a.indexOf("pending:")===0?Bz(a.substr(8)):!1}; + +function Xz(){};var Yz=function(){};Yz.prototype.toString=function(){return"undefined"};var Zz=new Yz;function fA(a,b){function c(g){var k=Ej(g),m=yj(k,"protocol"),n=yj(k,"host",!0),p=yj(k,"port"),q=yj(k,"path").toLowerCase().replace(/\/$/,"");if(m===void 0||m==="http"&&p==="80"||m==="https"&&p==="443")m="web",p="default";return[m,n,p,q]}for(var d=c(String(a)),e=c(String(b)),f=0;f= +0;case "_le":return sg(b,c);case "_lt":return ug(b,c);case "_re":return og(b,c,a.ignore_case);case "_sw":return vg(b,c);case "_um":return fA(b,c)}return!1};function iA(){var a;a=a===void 0?"":a;var b,c;return((b=data)==null?0:(c=b.blob)==null?0:c.hasOwnProperty(1))?String(data.blob[1]):a};function jA(){var a=[["cv",R(116)?iA():"1"],["rv",Ii.th],["tc",lf.filter(function(b){return b}).length]];Ii.Ce&&a.push(["x",Ii.Ce]);dj()&&a.push(["tag_exp",dj()]);return a};var kA={},lA={};function mA(){var a=0;return function(b){switch(b){case 1:a|=1;break;case 2:a|=2;break;case 3:a|=4}return a}}function nA(a,b,c,d){if(Tj){var e=String(c)+b;kA[a]=kA[a]||[];kA[a].push(e);lA[a]=lA[a]||[];lA[a].push(d+b)}}function oA(a){var b=a.eventId,c=a.Tc,d=[],e=kA[b]||[];e.length&&d.push(["hf",e.join(".")]);var f=lA[b]||[];f.length&&d.push(["ht",f.join(".")]);c&&(delete kA[b],delete lA[b]);return d};function pA(){return!1}function qA(){var a={};return function(b,c,d){}};function rA(){var a=sA;return function(b,c,d){var e=d&&d.event;b==="__html"&&R(87)||tA(c);var f=vb(b,"__cvt_")?void 0:1,g=new La;ib(c,function(r,u){var v=hd(u,void 0,f);v===void 0&&u!==void 0&&V(44);g.set(r,v)});a.j.j.C=Ef();var k={fk:Tf(b),eventId:e==null?void 0:e.id,priorityId:e!==void 0?e.priorityId:void 0,Ge:e!==void 0?function(r){e.qc.Ge(r)}:void 0,kb:function(){return b},log:function(){},Zl:{index:d==null?void 0:d.index,type:d==null?void 0:d.type,name:d==null?void 0:d.name},hn:!!Nw(b,3),originalEventData:e== +null?void 0:e.originalEventData};e&&e.cachedModelValues&&(k.cachedModelValues={gtm:e.cachedModelValues.gtm,ecommerce:e.cachedModelValues.ecommerce});if(pA()){var m=qA(),n,p;k.Xa={ri:[],He:{},Db:function(r,u,v){u===1&&(n=r);u===7&&(p=v);m(r,u,v)},ng:dh()};k.log=function(r){var u=ya.apply(1,arguments);n&&m(n,4,{level:r,source:p,message:u})}}var q=Fe(a,k,[b,g]);a.j.j.C=void 0;q instanceof Ba&&q.type==="return"&&(q=q.data);return G(q,void 0,f)}} +function tA(a){var b=a.gtmOnSuccess,c=a.gtmOnFailure;bb(b)&&(a.gtmOnSuccess=function(){F(b)});bb(c)&&(a.gtmOnFailure=function(){F(c)})};function uA(a){}uA.F="internal.addAdsClickIds";function vA(a,b){var c=this;}vA.T="addConsentListener";var wA=!1;function xA(a){for(var b=0;b=0?!1:!0},NA=["input","select","textarea"],OA=["button","hidden","image","reset", "submit"]; -function HA(a){}HA.F="internal.addFormAbandonmentListener";function IA(a,b,c,d){} -IA.F="internal.addFormData";var JA={},KA=[],LA={},MA=0,NA=0; -var PA=function(){Cc(E,"change",function(a){for(var b=0;b0?e:2E3;var g=G(a,this.D,1);if(d){var k=function(n){return Math.max(e,n)};xA("pix.fsl","mwt",k,0);f||xA("pix.fsl","nv.mwt",k,0)}var m=function(n){n.push(g);return n};xA("pix.fsl","runIfUncanceled",m,[]);f||xA("pix.fsl","runIfCanceled",m,[]);tA("pix.fsl", -"init")||($A(),uA("pix.fsl","init",!0));}aB.F="internal.addFormSubmitListener"; -function fB(a){}fB.F="internal.addGaSendListener";function gB(a){if(!a)return{};var b=a.Ql;return hx(b.type,b.index,b.name)}function hB(a){return a?{originatingEntity:gB(a)}:{}};function pB(a){var b=Hi.zones;return b?b.getIsAllowedFn(fk(),a):function(){return!0}} -function qB(){Mw(mk(),function(a){var b=a.originalEventData["gtm.uniqueEventId"],c=Hi.zones;return c?c.isActive(fk(),b):!0});Kw(mk(),function(a){var b,c;b=a.entityId;c=a.securityGroups;return pB(Number(a.originalEventData["gtm.uniqueEventId"]))(b,c)})};var rB=function(a,b){this.tagId=a;this.Be=b}; -function sB(a,b){var c=this,d;return d} -sB.F="internal.loadGoogleTag";function tB(a){return new Wc("",function(b){var c=this.evaluate(b);if(c instanceof Wc)return new Wc("",function(){var d=xa.apply(0,arguments),e=this,f=Sa(qA(this),null);f.eventId=a.eventId;f.priorityId=a.priorityId;f.originalEventData=a.originalEventData;var g=d.map(function(m){return e.evaluate(m)}),k=Ha(this.D);k.j=f;return c.lb.apply(c,[k].concat(oa(g)))})})};function uB(a,b,c){var d=this;}uB.F="internal.addGoogleTagRestriction";var vB={},wB=[]; -function DB(a,b){} -DB.F="internal.addHistoryChangeListener";function EB(a,b,c){}EB.R="addWindowEventListener";function FB(a,b){return!0}FB.R="aliasInWindow";function GB(a,b,c){}GB.F="internal.appendRemoteConfigParameter";function HB(a){var b;return b}HB.R="callInWindow";function IB(a){}IB.R="callLater";function JB(a){}JB.F="callOnDomReady";function KB(a){}KB.F="callOnWindowLoad";function LB(a,b){var c;return c}LB.F="internal.computeGtmParameter";function MB(a,b){var c=this;}MB.F="internal.consentScheduleFirstTry";function NB(a,b){var c=this;}NB.F="internal.consentScheduleRetry";function OB(a){var b;return b}OB.F="internal.copyFromCrossContainerData";function PB(a,b){var c;var d=dd(c,this.D,Eb(qA(this).jb(),"__cvt_")?2:1);d===void 0&&c!==void 0&&U(45);return d}PB.R="copyFromDataLayer"; -function QB(a){var b=void 0;return b}QB.F="internal.copyFromDataLayerCache";function RB(a){var b;return b}RB.R="copyFromWindow";function SB(a){var b=void 0;return dd(b,this.D,1)}SB.F="internal.copyKeyFromWindow";var TB=function(a,b,c){this.eventName=b;this.m=c;this.j={};this.isAborted=!1;this.target=a;this.metadata=Sa(c.eventMetadata||{},{})};TB.prototype.copyToHitData=function(a,b,c){var d=V(this.m,a);d===void 0&&(d=b);if(d!==void 0&&c!==void 0&&l(d)&&Q(70))try{d=c(d)}catch(e){}d!==void 0&&(this.j[a]=d)};var Kt=function(a,b,c){var d=Ms(a.target.destinationId);return d&&d[b]!==void 0?d[b]:c};function UB(a,b){var c;K(this.getName(),["preHit:!PixieMap","dustOptions:?PixieMap"],arguments);var d=G(b)||{},e=G(a,this.D,1).Rb(),f=e.m;d.omitEventContext&&(f=Bm(new qm(e.m.eventId,e.m.priorityId)));var g=new TB(e.target,e.eventName,f);d.omitHitData||Sa(e.j,g.j);d.omitMetadata?g.metadata={}:Sa(e.metadata,g.metadata);g.isAborted=e.isAborted;c=dd(Cs(g),this.D,1);return c}UB.F="internal.copyPreHit";function VB(a,b){var c=null;return dd(c,this.D,2)}VB.R="createArgumentsQueue";function WB(a){return dd(function(c){var d=qx();if(typeof c==="function")d(function(){c(function(f,g,k){var m=qx(),n=m&&m.getByName&& -m.getByName(f);return gn(C.gaplugins.Linker,n).decorate(g,k)})});else if(Array.isArray(c)){var e=String(c[0]).split(".");b[e.length===1?e[0]:e[1]]&&d.apply(null,c)}else if(c==="isLoaded")return!!d.loaded},this.D,1)}WB.F="internal.createGaCommandQueue";function XB(a){return dd(function(){if(!mb(e.push))throw Error("Object at "+a+" in window is not an array.");e.push.apply(e,Array.prototype.slice.call(arguments,0))},this.D,Eb(qA(this).jb(), -"__cvt_")?2:1)}XB.R="createQueue";function YB(a,b){var c=null;return c}YB.F="internal.createRegex";function ZB(){var a={};return a};function $B(a){}$B.F="internal.declareConsentState";function aC(a){var b="";return b}aC.F="internal.decodeUrlHtmlEntities";function bC(a,b,c){var d;return d}bC.F="internal.decorateUrlWithGaCookies";function cC(a){var b;L(this,"detect_user_provided_data","auto");var c=G(a)||{},d=lt({zd:!!c.includeSelector,Bd:!!c.includeVisibility,Fe:c.excludeElementSelectors,Ab:c.fieldFilters,ig:!!c.selectMultipleElements});b=new Xa;var e=new Va;b.set("elements",e);for(var f=d.elements,g=0;g0?e:2E3;var g=G(a,this.D,1);if(d){var k=function(n){return Math.max(e,n)};IA("pix.fsl","mwt",k,0);f||IA("pix.fsl","nv.mwt",k,0)}var m=function(n){n.push(g);return n};IA("pix.fsl","runIfUncanceled",m,[]);f||IA("pix.fsl","runIfCanceled",m,[]);EA("pix.fsl", +"init")||(kB(),FA("pix.fsl","init",!0));}lB.F="internal.addFormSubmitListener"; +function qB(a){}qB.F="internal.addGaSendListener";function rB(a){if(!a)return{};var b=a.Zl;return lx(b.type,b.index,b.name)}function sB(a){return a?{originatingEntity:rB(a)}:{}};function AB(a){var b=Ji.zones;return b?b.getIsAllowedFn(ik(),a):function(){return!0}} +function BB(){Qw(ok(),function(a){var b=a.originalEventData["gtm.uniqueEventId"],c=Ji.zones;return c?c.isActive(ik(),b):!0});Ow(ok(),function(a){var b,c;b=a.entityId;c=a.securityGroups;return AB(Number(a.originalEventData["gtm.uniqueEventId"]))(b,c)})};var CB=function(a,b){this.tagId=a;this.Je=b}; +function DB(a,b){var c=this,d;return d} +DB.F="internal.loadGoogleTag";function EB(a){return new $c("",function(b){var c=this.evaluate(b);if(c instanceof $c)return new $c("",function(){var d=ya.apply(0,arguments),e=this,f=Vc(BA(this),null);f.eventId=a.eventId;f.priorityId=a.priorityId;f.originalEventData=a.originalEventData;var g=d.map(function(m){return e.evaluate(m)}),k=Ha(this.D);k.j=f;return c.nb.apply(c,[k].concat(ua(g)))})})};function FB(a,b,c){var d=this;}FB.F="internal.addGoogleTagRestriction";var GB={},HB=[]; +function OB(a,b){} +OB.F="internal.addHistoryChangeListener";function PB(a,b,c){}PB.T="addWindowEventListener";function QB(a,b){return!0}QB.T="aliasInWindow";function RB(a,b,c){}RB.F="internal.appendRemoteConfigParameter";function SB(a){var b;return b}SB.T="callInWindow";function TB(a){}TB.T="callLater";function UB(a){}UB.F="callOnDomReady";function VB(a){}VB.F="callOnWindowLoad";function WB(a,b){var c;return c}WB.F="internal.computeGtmParameter";function XB(a,b){var c=this;}XB.F="internal.consentScheduleFirstTry";function YB(a,b){var c=this;}YB.F="internal.consentScheduleRetry";function ZB(a){var b;return b}ZB.F="internal.copyFromCrossContainerData";function $B(a,b){var c;var d=hd(c,this.D,vb(BA(this).kb(),"__cvt_")?2:1);d===void 0&&c!==void 0&&V(45);return d}$B.T="copyFromDataLayer"; +function aC(a){var b=void 0;return b}aC.F="internal.copyFromDataLayerCache";function bC(a){var b;return b}bC.T="copyFromWindow";function cC(a){var b=void 0;return hd(b,this.D,1)}cC.F="internal.copyKeyFromWindow";var dC=function(a,b,c){this.eventName=b;this.m=c;this.j={};this.isAborted=!1;this.target=a;this.metadata=Vc(c.eventMetadata||{},{})};dC.prototype.copyToHitData=function(a,b,c){var d=W(this.m,a);d===void 0&&(d=b);if(d!==void 0&&c!==void 0&&z(d)&&R(74))try{d=c(d)}catch(e){}d!==void 0&&(this.j[a]=d)};var Nt=function(a,b,c){var d=Ps(a.target.destinationId);return d&&d[b]!==void 0?d[b]:c};function eC(a,b){var c;K(this.getName(),["preHit:!PixieMap","dustOptions:?PixieMap"],arguments);var d=G(b)||{},e=G(a,this.D,1).Ub(),f=e.m;d.omitEventContext&&(f=Dm(new sm(e.m.eventId,e.m.priorityId)));var g=new dC(e.target,e.eventName,f);d.omitHitData||Vc(e.j,g.j);d.omitMetadata?g.metadata={}:Vc(e.metadata,g.metadata);g.isAborted=e.isAborted;c=hd(Es(g),this.D,1);return c}eC.F="internal.copyPreHit";function fC(a,b){var c=null;return hd(c,this.D,2)}fC.T="createArgumentsQueue";function gC(a){return hd(function(c){var d=ux();if(typeof c==="function")d(function(){c(function(f,g,k){var m=ux(),n=m&&m.getByName&& +m.getByName(f);return jn(B.gaplugins.Linker,n).decorate(g,k)})});else if(Array.isArray(c)){var e=String(c[0]).split(".");b[e.length===1?e[0]:e[1]]&&d.apply(null,c)}else if(c==="isLoaded")return!!d.loaded},this.D,1)}gC.F="internal.createGaCommandQueue";function hC(a){return hd(function(){if(!bb(e.push))throw Error("Object at "+a+" in window is not an array.");e.push.apply(e,Array.prototype.slice.call(arguments,0))},this.D,vb(BA(this).kb(), +"__cvt_")?2:1)}hC.T="createQueue";function iC(a,b){var c=null;return c}iC.F="internal.createRegex";function jC(){var a={};return a};function kC(a){}kC.F="internal.declareConsentState";function lC(a){var b="";return b}lC.F="internal.decodeUrlHtmlEntities";function mC(a,b,c){var d;return d}mC.F="internal.decorateUrlWithGaCookies";function nC(){}nC.F="internal.deferCustomEvents";function oC(a){var b;L(this,"detect_user_provided_data","auto");var c=G(a)||{},d=ot({Hd:!!c.includeSelector,Id:!!c.includeVisibility,Me:c.excludeElementSelectors,Bb:c.fieldFilters,pg:!!c.selectMultipleElements});b=new La;var e=new Yc;b.set("elements",e);for(var f=d.elements,g=0;g0&&isFinite(d)||(d=0);if(tA("fil","init",!1)){var e=tA("fil","reg");if(e)e(b,d);else throw Error("Failed to register trigger: "+b);}else Cc(E,"change",function(f){for(var g=0;g0&&isFinite(d)||(d=0);if(EA("fil","init",!1)){var e=EA("fil","reg");if(e)e(b,d);else throw Error("Failed to register trigger: "+b);}else vc(E,"change",function(f){for(var g=0;g0&&isFinite(f)||(f=2E3);var g=function(m){return Math.max(f,m)};xA("fsl","mwt",g,0);e||xA("fsl","nv.mwt",g,0)}var k=function(m){m.push(b);return m}; -xA("fsl","ids",k,[]);e||xA("fsl","nv.ids",k,[]);tA("fsl","init",!1)||(FC(),uA("fsl","init",!0));return b}GC.F="internal.enableAutoEventOnFormSubmit"; -function LC(){var a=this;}LC.F="internal.enableAutoEventOnGaSend";var MC={},NC=[]; -var PC=function(a,b){var c=""+b;if(MC[c])MC[c].push(a);else{var d=[a];MC[c]=d;var e=OC("gtm.historyChange-v2"),f=-1;NC.push(function(g){f>=0&&C.clearTimeout(f);b?f=C.setTimeout(function(){e(g,d);f=-1},b):e(g,d)})}},OC=function(a){var b=C.location.href,c={source:null,state:C.history.state||null,url:xj(Aj(b)),Ea:uj(Aj(b),"fragment")};return function(d,e){var f=c,g={};g[f.source]=!0;g[d.source]=!0;if(!g.popstate||!g.hashchange||f.Ea!==d.Ea){var k={event:a,"gtm.historyChangeSource":d.source,"gtm.oldUrlFragment":c.Ea, -"gtm.newUrlFragment":d.Ea,"gtm.oldHistoryState":c.state,"gtm.newHistoryState":d.state,"gtm.oldUrl":c.url,"gtm.newUrl":d.url};e&&(k["gtm.triggers"]=e.join(","));c=d;gz(k)}}},QC=function(a,b){var c=C.history,d=c[a];if(mb(d))try{c[a]=function(e,f,g){d.apply(c,[].slice.call(arguments,0));var k=C.location.href;b({source:a,state:e,url:xj(Aj(k)),Ea:uj(Aj(k),"fragment")})}}catch(e){}},SC=function(a){C.addEventListener("popstate",function(b){var c=RC(b);a({source:"popstate",state:b.state,url:xj(Aj(c)),Ea:uj(Aj(c), -"fragment")})})},TC=function(a){C.addEventListener("hashchange",function(b){var c=RC(b);a({source:"hashchange",state:null,url:xj(Aj(c)),Ea:uj(Aj(c),"fragment")})})},RC=function(a){var b,c;return((b=a.target)==null?void 0:(c=b.location)==null?void 0:c.href)||C.location.href}; -function UC(a,b){var c=this;K(this.getName(),["options:?PixieMap","triggerId:?*"],arguments);mA([function(){L(c,"detect_history_change_events")}]);var d=a&&a.get("useV2EventName")?"ehl":"hl",e=Number(a&&a.get("interval"));e>0&&isFinite(e)||(e=0);if(!tA(d,"init",!1)){var f;d==="ehl"?(f=function(k){for(var m=0;m0){var f=xj(Aj(c)),g=xj(Aj(C.location.href));return f!==g}return!0},XC=function(a,b){for(var c=uj(Aj((b.attributes&&b.attributes.formaction?b.formAction:"")||b.action||Nc(b,"href")||b.src||b.code||b.codebase||""),"host"), -d=0;d0&&isFinite(k)||(k=2E3);var m=function(p){return Math.max(k,p)};xA("lcl","mwt",m,0);f||xA("lcl","nv.mwt",m,0)}var n=function(p){p.push(b); -return p};xA("lcl","ids",n,[]);f||xA("lcl","nv.ids",n,[]);g&&xA("lcl","aff.map",function(p){p[b]=g;return p},{});tA("lcl","init",!1)||(YC(),uA("lcl","init",!0));return b}ZC.F="internal.enableAutoEventOnLinkClick";var $C,aD; -var bD=function(a){return tA("sdl",a,{})},cD=function(a,b,c){if(b){var d=Array.isArray(a)?a:[a];xA("sdl",c,function(e){for(var f=0;f=a.limit)a.eg&&C.clearInterval(a.eg);else{a.Uh++;var b=zb();gz({event:a.eventName,"gtm.timerId":a.eg,"gtm.timerEventNumber":a.Uh,"gtm.timerInterval":a.interval,"gtm.timerLimit":a.limit,"gtm.timerStartTime":a.qk,"gtm.timerCurrentTime":b,"gtm.timerElapsedTime":b-a.qk,"gtm.triggers":a.rn})}}} -function nD(a,b){ -return b}nD.F="internal.enableAutoEventOnTimer"; -var oD=function(a,b,c){function d(){var g=a();f+=e?(zb()-e)*g.playbackRate/1E3:0;e=zb()}var e=0,f=0;return{createEvent:function(g,k,m){var n=a(),p=n.xh,q=m?Math.round(m):k?Math.round(n.xh*k):Math.round(n.Rj),r=k!==void 0?Math.round(k*100):p<=0?0:Math.round(q/p*100),t=E.hidden?!1:Qs(c)>=.5;d();var v=void 0;b!==void 0&&(v=[b]);var u=yA(c,"gtm.video",v);u["gtm.videoProvider"]="youtube";u["gtm.videoStatus"]=g;u["gtm.videoUrl"]=n.url;u["gtm.videoTitle"]=n.title;u["gtm.videoDuration"]=Math.round(p);u["gtm.videoCurrentTime"]= -Math.round(q);u["gtm.videoElapsedTime"]=Math.round(f);u["gtm.videoPercent"]=r;u["gtm.videoVisible"]=t;return u},lk:function(){e=zb()},ud:function(){d()}}};var gc=ma(["data-gtm-yt-inspected-"]),pD=["www.youtube.com","www.youtube-nocookie.com"],qD,rD=!1; -var sD=function(a,b,c){var d=a.map(function(g){return{Da:g,df:g,Ze:void 0}});if(!b.length)return d;var e=b.map(function(g){return{Da:g*c,df:void 0,Ze:g}});if(!d.length)return e;var f=d.concat(e);f.sort(function(g,k){return g.Da-k.Da});return f},tD=function(a){a=a===void 0?[]:a;for(var b=[],c=0;c100||a[c]<0||(b[c]=a[c]/100);b.sort(function(d,e){return d- -e});return b},vD=function(a,b){var c,d;function e(){t=oD(function(){return{url:w,title:x,xh:u,Rj:a.getCurrentTime(),playbackRate:y}},b.Fb,a.getIframe());u=0;x=w="";y=1;return f}function f(I){switch(I){case 1:u=Math.round(a.getDuration());w=a.getVideoUrl();if(a.getVideoData){var J=a.getVideoData();x=J?J.title:""}y=a.getPlaybackRate();b.rh?gz(t.createEvent("start")):t.ud();v=sD(b.di,b.bi,a.getDuration());return g(I);default:return f}}function g(){A=a.getCurrentTime();B=yb().getTime();t.lk();r();return k} -function k(I){var J;switch(I){case 0:return n(I);case 2:J="pause";case 3:var H=a.getCurrentTime()-A;J=Math.abs((yb().getTime()-B)/1E3*y-H)>1?"seek":J||"buffering";a.getCurrentTime()&&(b.qh?gz(t.createEvent(J)):t.ud());q();return m;case -1:return e(I);default:return k}}function m(I){switch(I){case 0:return n(I);case 1:return g(I);case -1:return e(I);default:return m}}function n(){for(;d;){var I=c;C.clearTimeout(d);I()}b.ph&&gz(t.createEvent("complete",1));return e(-1)}function p(){}function q(){d&& -(C.clearTimeout(d),d=0,c=p)}function r(){if(v.length&&y!==0){var I=-1,J;do{J=v[0];if(J.Da>a.getDuration())return;I=(J.Da-a.getCurrentTime())/y;if(I<0&&(v.shift(),v.length===0))return}while(I<0);c=function(){d=0;c=p;v.length>0&&v[0].Da===J.Da&&(v.shift(),gz(t.createEvent("progress",J.Ze,J.df)));r()};d=C.setTimeout(c,I*1E3)}}var t,v=[],u,w,x,y,A,B,D=e(-1);d=0;c=p;return{onStateChange:function(I){D=D(I)},onPlaybackRateChange:function(I){A=a.getCurrentTime();B=yb().getTime();t.ud();y=I;q();r()}}},xD= -function(a){F(function(){function b(){for(var d=c.getElementsByTagName("iframe"),e=d.length,f=0;f0)return!0;if(b){var d;var e=c.indexOf("?")!==-1?"&":"?";c.indexOf("origin=")>-1?d=c+e+"enablejsapi=1":(qD||(qD=E.location.protocol+"//"+E.location.hostname,E.location.port&&(qD+=":"+E.location.port)),d=c+e+"enablejsapi=1&origin="+encodeURIComponent(qD));var f;f=Rb(d);a.src=Sb(f).toString();return!0}}return!1},AD=function(a,b){if(!a)return!1;for(var c=0;c=0)return!0;return!1},zD=function(){var a= -""+Math.round(Math.random()*1E9);return E.getElementById(a)?zD():a}; -function BD(a,b){var c=this;var d=function(){xD(p)};K(this.getName(),["dustOptions:!PixieMap","triggerId:?*"],arguments);mA([function(){L(c,"detect_youtube_activity_events",{fixMissingApi:!!a.get("fixMissingApi")})}]);b=sA(b);var e=!!a.get("captureStart"),f=!!a.get("captureComplete"),g=!!a.get("capturePause"),k=uD(G(a.get("progressThresholdsPercent"))),m=tD(G(a.get("progressThresholdsTimeInSeconds"))),n=!!a.get("fixMissingApi"); -if(!(e||f||g||k.length||m.length))return;var p={rh:e,ph:f,qh:g,bi:k,di:m,Je:n,Fb:b},q=C.YT;if(q)return q.ready&&q.ready(d),b;var r=C.onYouTubeIframeAPIReady;C.onYouTubeIframeAPIReady=function(){r&&r();d()};F(function(){for(var t=E.getElementsByTagName("script"),v=t.length,u=0;u0&&(a.j[O.g.Vd]=b)};aa.hm=function(a){a.j[O.g.Vd]=void 0;this.gi();this.C=0};aa.Nh=function(){return this.H&& -this.isVisible&&this.isActive};aa.Xl=function(){return this.C+this.Zf()};aa.Zf=function(){return this.j&&this.j.get()||0};aa.Vm=function(a){this.K=a};aa.kk=function(a){this.P=a};var WF=function(a){var b=a.metadata.event_usage;if(Array.isArray(b))for(var c=0;cd.Ve+f*60))return a;var g=fG(b);if(!g)return a;g.Lc=d.Lc+1;var k;return(k=gG(g.sessionId,g.Lc,g.Fd,g.Ve,g.Rh,g.Hc,g.wd))!=null?k:b},kG=function(a,b){var c=b.metadata.cookie_options,d=iG(b,c),e=ip(a,jG[0],c.domain,c.path),f={Eb:O.g.U,domain:c.domain,path:c.path,expires:c.Db?new Date(zb()+Number(c.Db)*1E3):void 0,flags:c.flags}; -$o(d,void 0,f);return $o(d,e,f)!==1},lG=function(a){var b=a.metadata.cookie_options,c=iG(a,b),d=hp(c,b.domain,b.path,jG,O.g.U);if(!d)return d;var e=Po(c,void 0,void 0,O.g.U);if(d&&e.length>1){U(114);for(var f=void 0,g=void 0,k=0;kg)&&(g=n,f=e[k])}}f&&!Fb(f,d)&&(U(115),d=f.split(".").slice(2).join("."))}return d},mG=function(a){return gG(a.j[O.g.yb],a.j[O.g.je],a.j[O.g.ie],Math.floor(a.metadata.event_start_timestamp_ms/ -1E3),a.metadata.join_timer_sec||0,!!a.metadata[O.g.Af],a.j[O.g.Wd])},gG=function(a,b,c,d,e,f,g){if(a&&b){var k=[a,b,ub(c),d,e];k.push(f?"1":"0");k.push(g||"0");return k.join(".")}},iG=function(a,b){return b.prefix+"_ga_"+a.target.ids[Xl[0]]},jG=["GS1"],fG=function(a){if(a){var b=a.split(".");if(!(b.length<5||b.length>7)){b.length<7&&U(67);var c=Number(b[1]),d=Number(b[3]),e=Number(b[4]||0);c||U(118);d||U(119);isNaN(e)&&U(120);if(c&&d&&!isNaN(e))return{sessionId:b[0],Lc:c,Fd:!!Number(b[2]),Ve:d,Rh:e, -Hc:b[5]==="1",wd:b[6]!=="0"?b[6]:void 0}}}}; -var nG=function(a){var b=V(a.m,O.g.oa),c=a.m.C[O.g.oa];if(c===b)return c;var d=Sa(b,null);c&&c[O.g.W]&&(d[O.g.W]=(d[O.g.W]||[]).concat(c[O.g.W]));return d},oG=function(a,b){var c=Cp(!0);return c._up!=="1"?{}:{clientId:c[a],Ua:c[b]}},pG=function(a,b,c){var d=Cp(!0),e=d[b];e&&(aG(a,e,2),bG(e,a));var f=d[c];f&&kG(f,a);return{clientId:e,Ua:f}},qG=function(){var a=wj(C.location,"host"),b=wj(Aj(E.referrer),"host");return a&&b?a===b||a.indexOf("."+b)>=0||b.indexOf("."+a)>=0?!0:!1:!1},rG=function(a){if(!V(a.m, -O.g.Za))return{};var b=a.metadata.cookie_options,c=b.prefix+"_ga",d=iG(a,b);Kp(function(){var e;if(W("analytics_storage"))e={};else{var f={};e=(f._up="1",f[c]=a.j[O.g.sb],f[d]=mG(a),f)}return e},1);return!W("analytics_storage")&&qG()?oG(c,d):{}},tG=function(a){var b=nG(a)||{},c=a.metadata.cookie_options,d=c.prefix+"_ga",e=iG(a,c),f={};Mp(b[O.g.Cc],!!b[O.g.W])&&(f=pG(a,d,e),f.clientId&&f.Ua&&(sG=!0));b[O.g.W]&&Jp(function(){var g={},k=eG(a);k&&(g[d]=k);var m=lG(a);m&&(g[e]=m);var n=Po("FPLC",void 0, -void 0,O.g.U);n.length&&(g._fplc=n[0]);return g},b[O.g.W],b[O.g.Mb],!!b[O.g.xb]);return f},sG=!1;var uG=function(a){if(!a.metadata.is_merchant_center&&Ij(a.m)){var b=nG(a)||{},c=(Mp(b[O.g.Cc],!!b[O.g.W])?Cp(!0)._fplc:void 0)||(Po("FPLC",void 0,void 0,O.g.U).length>0?void 0:"0");a.j._fplc=c}};function vG(a){if(Nt(a)||bj())a.j[O.g.lj]=nl()||ml();!Nt(a)&&bj()&&(a.j[O.g.uj]="::")}function wG(a){if(Q(67)&&bj()){js(a);ks(a,"cpf",V(a.m,O.g.Ia));var b=V(a.m,O.g.Zb);ks(a,"cu",b===!0?1:b===!1?0:void 0);ks(a,"cf",V(a.m,O.g.Ya));ks(a,"cd",ep(V(a.m,O.g.Pa),V(a.m,O.g.ub)))}};var yG=function(a,b){var c=Hi.grl;c||(c=xG(),Hi.grl=c);c(b)||(U(35),a.isAborted=!0)},xG=function(){var a=zb(),b=a+864E5,c=20,d=5E3;return function(e){var f=zb();f>=b&&(b=f+864E5,d=5E3);c=Math.min(c+(f-a)/1E3*5,20);a=f;var g=!1;d<1||c<1||(g=!0,d--,c--);e&&(e.Hl=d,e.Bl=c);return g}}; -var zG=function(a){if(V(a.m,O.g.fd)!==void 0)a.copyToHitData(O.g.fd);else{var b=V(a.m,O.g.Gf),c,d;a:{if(sG){var e=nG(a)||{};if(e&&e[O.g.W])for(var f=uj(Aj(a.j[O.g.Aa]),"host",!0),g=e[O.g.W],k=0;k=0){d=!0;break a}}d=!1}if(!(c=d)){var m;if(m=b)a:{for(var n=b.include_conditions||[],p=uj(Aj(a.j[O.g.Aa]),"host",!0),q=0;q=0&&(c=a.pathname.substring(0,d));b.transport_url=a.protocol+"//"+a.hostname+c;return b},SG=function(a,b,c){var d=0,e=new C.XMLHttpRequest;e.withCredentials=!0;e.onprogress=function(f){if(e.status===200){var g=e.responseText.substring(d);d=f.loaded;OG(c,g)}};e.open(b?"POST":"GET",a);e.setAttributionReporting&&e.setAttributionReporting({eventSourceEligible:!1,triggerEligible:!0}); -e.send(b)},UG=function(a,b,c){var d=Object.assign({},TG);b&&(d.body=b,d.method="POST");C.fetch(a,d).then(function(e){if(e.ok&&e.body){var f=e.body.getReader(),g=new TextDecoder;return new Promise(function(k){function m(){f.read().then(function(n){var p;p=n.done;var q=g.decode(n.value,{stream:!p});OG(c,q);p?k():m()}).catch(function(){k()})}m()})}}).catch(function(){Q(97)&&(a+="&_z=retryFetch",b?Jc(a,b):Ic(a))})},VG=function(a,b){return NG(new MG(function(c,d){var e=QG(c,a);b&&(e=e.replace("_is_sw=0", -b));var f={};d.attribution_reporting&&(f.attributionsrc="");Ac(e,void 0,void 0,f)}),function(c,d){var e=QG(c,a),f=d.dedupe_key;f&&Bu(e,f)})},WG=function(a,b,c,d){var e=VG(c,d);Q(96)&&Mc()?UG(a,b,e):SG(a,b,e)},XG=function(a,b){var c=Aj(a),d=RG(c),e=PG(c);Q(101)?ju(e,b,d,function(f){WG(e,b,d,f)}):WG(e,b,d)},TG=Object.freeze({cache:"no-store",credentials:"include",method:"GET",keepalive:!0,redirect:"follow"}); -var YG=function(a,b){return a?[a,b].join("&"):b},ZG=function(a,b,c){var d=a+"?"+b;c?Jc(d,c):Ic(d)},aH=function(a,b,c,d){var e=b,f=Oc();f!==void 0&&(e+="&tfd="+Math.round(f));b=e;var g=a+"?"+b;$G&&(d=!Eb(g,CG())&&!Eb(g,BG()));if(d&&!RF)XG(g,c);else{var k=b;Mc()?Lc(a+"?"+k,c,{noFallback:!0})||ZG(a,YG(k,"_z=failedfetch"),c):ZG(a,YG(k,"_z=nofetch"),c)}},bH=function(a,b){function c(v){n.push(v+"="+encodeURIComponent(""+a.ia[v]))}var d=b.gn,e=b.hn,f=b.Zl,g=b.vm,k=b.tm,m=b.Um;if(d||e){var n=[];a.ia._ng&& -c("_ng");c("tid");c("cid");c("gtm");n.push("aip=1");a.Mc.uid&&!k&&n.push("uid="+encodeURIComponent(""+a.Mc.uid));var p=function(){c("dma");a.ia.dma_cps!=null&&c("dma_cps");a.ia.gcs!=null&&c("gcs");c("gcd");a.ia.npa!=null&&c("npa")};p();a.ia.frm!=null&&c("frm");d&&($i.j&&n.push("tag_exp="+$i.j),ZG("https://stats.g.doubleclick.net/g/collect","v=2&"+n.join("&")),n.join("&"));if(e){var q=function(){var v=Du()+"/td/ga/rul?";n=[];c("tid");n.push("gacid="+encodeURIComponent(String(a.ia.cid)));c("gtm");p(); -c("pscdl");a.ia._ng!=null&&c("_ng");n.push("aip=1");n.push("fledge=1");a.ia.frm!=null&&c("frm");$i.j&&n.push("tag_exp="+$i.j);n.push("z="+qb());var u=v+n.join("&");Bu(u,a.ia.tid)};$i.j&&n.push("tag_exp="+$i.j);n.push("z="+qb());if(!g){var r=f&&Eb(f,"google.")&&f!=="google.com"?"https://www.%/ads/ga-audiences?v=1&t=sr&slf_rd=1&_r=4&".replace("%",f):void 0;if(r){var t=r+n.join("&");Ac(t)}}Q(78)&&m&&!RF&&q()}}},$G=!1; -var cH=function(){this.K=1;this.P={};this.C=-1;this.j=new Zf};cH.prototype.H=function(a,b){var c=this,d=new LG(a,this.P,b),e=SF(a);e&&this.j.P(d)||this.flush();if(e&&this.j.add(d)){if(this.C<0){var f=C.setTimeout,g;Nt(a)?dH?(dH=!1,g=eH):g=fH:g=5E3;this.C=f.call(C,function(){c.flush()},g)}}else{var k=bg(d,this.K++);aH(d.baseUrl,k.params,k.body,d.H);var m=a.metadata.create_dc_join,n=a.metadata.create_google_join,p=V(a.m,O.g.za)!==!1,q=yo(a.m),r={eventId:a.m.eventId,priorityId:a.m.priorityId},t=a.j[O.g.Wg], -v={gn:m,hn:n,Zl:sl(),Qn:p,Pn:q,vm:ol(),tm:a.metadata.euid_mode_enabled,Un:r,Um:t,m:a.m};bH(d,v)}iw(a.m.eventId,a.eventName)};cH.prototype.add=function(a){!a.metadata.euid_mode_enabled||RF||Q(92)?this.H(a):this.Z(a)};cH.prototype.flush=function(){if(this.j.events.length){var a=dg(this.j,this.K++);aH(this.j.baseUrl,a.params,a.body,this.j.C);this.j=new Zf;this.C>=0&&(C.clearTimeout(this.C),this.C=-1)}};cH.prototype.Z=function(a){var b=this,c=Mt(a);if(Q(95)){var d=function(k,m){b.H(k,m&&m.ab.split("~").length> -1?m.ab:void 0)};if(yi(c)){var e=mi(c);e?e.then(function(k){d(a,k)},function(){d(a)}):d(a)}else{var f=xi(c);d(a,f)}}else{var g=Q(71)&&!(c!=null&&Object.keys(c).length>0);!c||g?this.H(a):ki(c,function(k){var m;m=k.ab;b.H(a,m.split("~").length===1?void 0:m)})}};var eH=Wh('',500),fH=Wh('',5E3),dH=!0; -var gH=function(a,b,c){c===void 0&&(c={});if(b==null)return c;if(typeof b==="object")for(var d=h(Object.keys(b)),e=d.next();!e.done;e=d.next()){var f=e.value;gH(a+"."+f,b[f],c)}else c[a]=b;return c},hH=function(a){for(var b={},c=h(a),d=c.next();!d.done;d=c.next()){var e=d.value;b[e]=!!W(e)}return b},jH=function(a,b){var c=iH.filter(function(e){return!W(e)});if(c.length){var d=hH(c);Bl(c,function(){for(var e=hH(c),f=[],g=h(c),k=g.next();!k.done;k=g.next()){var m=k.value;!d[m]&&e[m]&&f.push(m);e[m]&& -(d[m]=!0)}if(f.length){b.metadata.is_consent_update=!0;var n=f.map(function(p){return vh[p]}).join(".");n&&Jt(b,"gcut",n);a(b)}})}},kH=function(a){if(Q(117)&&Nt(a)){var b=V(a.m,O.g.Nb),c;b===!0&&(c="1");b===!1&&(c="0");c&&Jt(a,"rdp",c)}},lH=function(a){Q(115)&&Nt(a)&&V(a.m,O.g.Md,!0)===!1&&(a.j[O.g.Md]=0)},mH=function(a,b){if(Nt(b)){var c=b.metadata.is_conversion;(b.eventName==="page_view"||c)&&jH(a,b)}},nH=function(a){if(Nt(a)&&a.eventName===O.g.Pc&&a.metadata.is_consent_update){var b=a.j[O.g.wg]; -b&&(Jt(a,"gcut",b),Jt(a,"syn",1))}},oH=function(a){Q(116)&&Nt(a)&&V(a.m,O.g.za)!==!1&&zu("join-ad-interest-group")&&mb(oc.joinAdInterestGroup)&&Jt(a,"flg",1)},pH=function(a){Nt(a)&&(a.metadata.speculative=!1)},qH=function(a){Nt(a)&&(a.metadata.speculative&&Jt(a,"sp",1),a.metadata.is_syn&&Jt(a,"syn",1),a.metadata.em_event&&(Jt(a,"em_event",1),Jt(a,"sp",1)))},rH=function(a){if(Nt(a)){var b=Ui;b&&Jt(a,"tft",Number(b))}},sH=function(a){function b(e){var f=gH(O.g.Ba,e);z(f,function(g,k){a.j[g]=k})}if(Nt(a)){var c= -Kt(a,"ccd_add_1p_data",!1)?1:0;Jt(a,"ude",c);var d=V(a.m,O.g.Ba);d!==void 0?(b(d),a.j[O.g.od]="c"):b(a.metadata.user_data);a.metadata.user_data=void 0}},tH=function(a){if(Nt(a)){var b=Xr();b&&Jt(a,"us_privacy",b);var c=so();c&&Jt(a,"gdpr",c);var d=ro();d&&Jt(a,"gdpr_consent",d)}},uH=function(a){Nt(a)&&al()&&V(a.m,O.g.fa)&&Jt(a,"adr",1)},vH=function(a){if(Nt(a)){var b=EG?ql():"";b&&Jt(a,"gcsub",b)}},wH=function(a){if(Nt(a)){V(a.m,O.g.rb,void 0,4)===!1&&Jt(a,"ngs",1);ol()&&Jt(a,"ga_rd",1);lE()||Jt(a, -"ngst",1);var b=sl();b&&Jt(a,"etld",b)}},xH=function(a){},yH=function(a){Nt(a)&&al()&&Jt(a,"rnd",Cr())},iH=[O.g.O,O.g.N]; -var zH=function(a,b){var c;a:{var d=mG(a);if(d){if(kG(d,a)){c=d;break a}U(25);a.isAborted=!0}c=void 0}var e=c;return{clientId:cG(a,b),Ua:e}},AH=function(a,b,c,d,e){var f=V(a.m,O.g.sb);if(V(a.m,O.g.Lb)&&V(a.m,O.g.bc))f?aG(a,f,1):(U(127),a.isAborted=!0);else{var g=f?1:8;a.metadata.is_new_to_site=!1;f||(f=eG(a),g=3);f||(f=b,g=5);if(!f){var k=W(O.g.U),m=YF();f=!m.from_cookie||k?m.vid:void 0;g=6}f?f=""+f:(f=gp(),g=7,a.metadata.is_first_visit=a.metadata.is_new_to_site=!0);aG(a,f,g)}var n=Math.floor(a.metadata.event_start_timestamp_ms/ -1E3),p=void 0;a.metadata.is_new_to_site||(p=lG(a)||c);var q=ub(V(a.m,O.g.md,30));q=Math.min(475,q);q=Math.max(5,q);var r=ub(V(a.m,O.g.If,1E4)),t=fG(p);a.metadata.is_first_visit=!1;a.metadata.is_session_start=!1;a.metadata.join_timer_sec=0;t&&t.Rh&&(a.metadata.join_timer_sec=Math.max(0,t.Rh-Math.max(0,n-t.Ve)));var v=!1;t||(v=a.metadata.is_first_visit=!0,t={sessionId:String(n),Lc:1,Fd:!1,Ve:n,Hc:!1,wd:void 0});n>t.Ve+q*60&&(v=!0,t.sessionId=String(n),t.Lc++,t.Fd=!1,t.wd=void 0);if(v)a.metadata.is_session_start= -!0,d.hm(a);else if(d.Xl()>r||a.eventName===O.g.Wb)t.Fd=!0;a.metadata.euid_mode_enabled?V(a.m,O.g.ya)?t.Hc=!0:(t.Hc&&!Q(12)&&(t.wd=void 0),t.Hc=!1):t.Hc=!1;var u=t.wd;if(a.metadata.euid_mode_enabled||Nt(a)){var w=V(a.m,O.g.Wd),x=w?1:8;w||(w=u,x=4);w||(w=fp(),x=7);var y=w.toString(),A=x,B=a.metadata.enhanced_client_id_source;if(B===void 0||A<=B)a.j[O.g.Wd]=y,a.metadata.enhanced_client_id_source=A}e?(a.copyToHitData(O.g.yb,t.sessionId),a.copyToHitData(O.g.je,t.Lc),a.copyToHitData(O.g.ie,t.Fd?1:0)):(a.j[O.g.yb]= -t.sessionId,a.j[O.g.je]=t.Lc,a.j[O.g.ie]=t.Fd?1:0);a.metadata[O.g.Af]=t.Hc?1:0};var BH=window,CH=document,DH=function(a){var b=BH._gaUserPrefs;if(b&&b.ioo&&b.ioo()||CH.documentElement.hasAttribute("data-google-analytics-opt-out")||a&&BH["ga-disable-"+a]===!0)return!0;try{var c=BH.external;if(c&&c._gaUserPrefs&&c._gaUserPrefs=="oo")return!0}catch(p){}for(var d=[],e=String(CH.cookie).split(";"),f=0;f0&&VF(17);ZH(a);AH(a,this.clientId,this.Ua,this.C,!this.Sa);$H(a);aI(a);bI(a); -cI(a);dI(a);eI(a);fI(a);uG(a);zG(a);yH(a);xH(a);wH(a);vH(a);uH(a);tH(a);rH(a);qH(a);oH(a);nH(a);lH(a);kH(a);vG(a);wG(a);gI(a);hI(a);iI(a);hs(a);gs(a);jI(a);kI(a);Es(a);lI(a);sH(a);pH(a);mI(a);!this.K&&a.metadata.em_event&&VF(18);WF(a);if(a.metadata.speculative||a.isAborted){a.m.onFailure();XF();return}this.jk(zH(a,this.clientId));this.Sa=!0;this.mn(a);nI(a);mH(function(f){b.Oj(f)},a);this.C.gi();oI(a);if(a.isAborted){a.m.onFailure();XF();return}this.Oj(a);a.m.onSuccess()}catch(f){a.m.onFailure()}XF()}; -aa.Oj=function(a){this.Z.add(a)};aa.jk=function(a){var b=a.clientId,c=a.Ua;b&&c&&(this.clientId=b,this.Ua=c)};aa.flush=function(){this.Z.flush()};aa.mn=function(a){var b=this;if(!this.P){var c=W(O.g.N),d=W(O.g.U);Bl([O.g.N,O.g.U],function(){var e=W(O.g.N),f=W(O.g.U),g=!1,k={},m={};if(d!==f&&b.j&&b.Ua&&b.clientId){var n=b.clientId,p;var q=fG(b.Ua);p=q?q.wd:void 0;if(f){var r=eG(b.j);if(r){b.clientId=r;var t=lG(b.j);t&&(b.Ua=hG(t,b.Ua,b.j))}else bG(b.clientId,b.j),$F(b.clientId,!0);kG(b.Ua,b.j);g=!0; -k[O.g.Kg]=n;Q(61)&&p&&(k[O.g.Tk]=p)}else b.Ua=void 0,b.clientId=void 0,C.gaGlobal={}}e&&!c&&(g=!0,m.is_consent_update=!0,k[O.g.wg]=vh[O.g.N]);if(g){var v=ly(b.H,O.g.Pc,k);ny(v,a.m.eventId,{eventMetadata:m})}d=f;c=e});this.P=!0}};aa.fl=function(a){a.eventName!==O.g.Wa&&this.C.bl(a)};var RH=function(a){var b=E.location.protocol;b!=="http:"&&b!=="https:"&&(U(29),a.isAborted=!0)},SH=function(a){oc&&oc.loadPurpose==="preview"&&(U(30),a.isAborted=!0)},TH=function(a){var b={prefix:String(V(a.m,O.g.Ia,"")), -path:String(V(a.m,O.g.ub,"/")),flags:String(V(a.m,O.g.Ya,"")),domain:String(V(a.m,O.g.Pa,"auto")),Db:Number(V(a.m,O.g.Qa,63072E3))};a.metadata.cookie_options=b},VH=function(a){if(a.metadata.is_merchant_center)a.metadata.euid_mode_enabled=!1;else if(Kt(a,"ccd_add_1p_data",!1)||Kt(a,"ccd_add_ec_stitching",!1))a.metadata.euid_mode_enabled=!0},WH=function(a){if(a.metadata.euid_mode_enabled&&Kt(a,"ccd_add_1p_data",!1)){var b=a.m.C[O.g.ke];if(qj(b)){var c=V(a.m,O.g.Ba);c===null?a.metadata.user_data_from_code= -null:(b.enable_code&&Qa(c)&&(a.metadata.user_data_from_code=c),Qa(b.selectors)&&!a.metadata.user_data_from_manual&&(a.metadata.user_data_from_manual=oj(b.selectors)))}}},XH=function(a){if(Q(69)&&!Q(68)&&Kt(a,"ga4_ads_linked",!1)&&a.eventName===O.g.aa){var b=V(a.m,O.g.na)!==!1;if(b){var c=Yr(a);c.Db&&(c.Db=Math.min(c.Db,7776E3));Zr({vd:b,Dd:V(a.m,O.g.oa)||{},Hd:V(a.m,O.g.Za),mc:c})}}},gI=function(a){if(!su(C))U(87);else if(xu!==void 0){U(85);var b=qu();b?V(a.m,O.g.he)&&!Nt(a)||uu(b,a):U(86)}},YH=function(a){a.eventName=== -O.g.aa&&(V(a.m,O.g.Ja,!0)?(a.m.j[O.g.da]&&(a.m.H[O.g.da]=a.m.j[O.g.da],a.m.j[O.g.da]=void 0,a.j[O.g.da]=void 0),a.eventName=O.g.Wb):a.isAborted=!0)},UH=function(a){function b(c,d){lh[c]||d===void 0||(a.j[c]=d)}z(a.m.H,b);z(a.m.j,b)},$H=function(a){var b=pm(a.m),c=function(d,e){LH[d]&&(a.j[d]=e)};Qa(b[O.g.Uc])?z(b[O.g.Uc],function(d,e){c((O.g.Uc+"_"+d).toLowerCase(),e)}):z(b,c)},ZH=JH,nI=function(a){if(Q(101)&&W(O.g.U)){Nt(a)&&(a.metadata.is_sgtm_service_worker=!0,Nt(a)&&Jt(a,"sw_exp",1));a:{}}},jI=function(a){if(a.eventName===O.g.Wa){var b=V(a.m,O.g.wb);V(a.m,O.g.Jb)(a.j[b]||V(a.m,b));a.isAborted=!0}},aI=function(a){if(!V(a.m,O.g.bc)||!V(a.m,O.g.Lb)){var b=a.copyToHitData,c=O.g.qa,d="",e=E.location;if(e){var f=e.pathname||"";f.charAt(0)!=="/"&&(f="/"+f);var g=e.search||"";if(g&&g[0]=== -"?")for(var k=g.substring(1).split("&"),m=0;m=0)a.isAborted=!0;else{var b=Lt(a);b&&b.blacklisted&&(a.isAborted=!0)}},dI=function(a){var b=function(c){return!!c&&c.conversion};a.metadata.is_conversion=b(Lt(a));a.metadata.is_first_visit&&(a.metadata.is_first_visit_conversion=b(Lt(a,"first_visit")));a.metadata.is_session_start&&(a.metadata.is_session_start_conversion=b(Lt(a,"session_start")))}, -eI=function(a){ph.hasOwnProperty(a.eventName)&&(a.metadata.is_ecommerce=!0,a.copyToHitData(O.g.ba),a.copyToHitData(O.g.wa))},lI=function(a){if(Q(72)&&a.metadata.is_conversion&&W(O.g.O)&&Kt(a,"ga4_ads_linked",!1)){var b=Yr(a),c=Dq(b.prefix),d=Pr(c);a.j[O.g.nf]=d.Eh;a.j[O.g.qf]=d.Gh;a.j[O.g.pf]=d.Fh}};function OH(a){z(a,function(c){c.charAt(0)==="_"&&delete a[c]});var b=a[O.g.ib]||{};z(b,function(c){c.charAt(0)==="_"&&delete b[c]})}var qI=function(a){if(!pI(a)){var b=!1,c=function(){!b&&pI(a)&&(b=!0,Dc(E,"visibilitychange",c),Q(4)&&Dc(E,"prerenderingchange",c),U(55))};Cc(E,"visibilitychange",c);Q(4)&&Cc(E,"prerenderingchange",c);U(54)}},pI=function(a){if(Q(4)&&"prerendering"in E?E.prerendering:E.visibilityState==="prerender")return!1;a();return!0};function rI(a,b){qI(function(){var c=Ul(a);if(c){var d=sI(c,b);Vm(a,d)}});}function sI(a,b){var c=function(){};var d=new NH(a.id),e=a.prefix==="MC";c=function(f,g,k,m){e&&(m.eventMetadata.is_merchant_center=!0);d.Sm(g,k,m)};ek||tI(a,d,b);return c} -function tI(a,b,c){var d=b.C,e={},f={eventId:c,eventMetadata:(e.batch_on_navigation=!0,e)};Q(46)&&(f.deferrable=!0);d.Vm(function(){RF=!0;Wm.flush();d.Zf()>=1E3&&oc.sendBeacon!==void 0&&Xm(O.g.Pc,{},a.id,f);b.flush();d.kk(function(){RF=!1;d.kk()})});};var uI=sI;function wI(a,b,c){var d=this;}wI.F="internal.gtagConfig";function xI(){var a={};return a}; -function zI(a,b){}zI.R="gtagSet";function AI(){var a={};return a};function BI(a,b){}BI.R="injectHiddenIframe";var CI=bA(); -function DI(a,b,c,d,e){var f=this;}DI.F="internal.injectHtml";var HI={}; -function JI(a,b,c,d){}var KI={dl:1,id:1},LI={}; -function MI(a,b,c,d){}JI.R="injectScript";MI.F="internal.injectScript";function NI(a){var b=!0;return b}NI.R="isConsentGranted";function OI(a){var b=!1;return b}OI.F="internal.isDebugMode";function PI(){return pl()}PI.F="internal.isDmaRegion";function QI(a){var b=!1;return b}QI.F="internal.isEntityInfrastructure";function RI(){var a=Xg(function(b){qA(this).log("error",b)});a.R="JSON";return a};function SI(a){var b=void 0;return dd(b)}SI.F="internal.legacyParseUrl";function TI(){return!1} -var UI={getItem:function(a){var b=null;return b},setItem:function(a,b){return!1},removeItem:function(a){}};function VI(){}VI.R="logToConsole";function WI(a,b){}WI.F="internal.mergeRemoteConfig";function XI(a,b,c){c=c===void 0?!0:c;var d=[];return dd(d)}XI.F="internal.parseCookieValuesFromString";function YI(a){var b=void 0;if(typeof a!=="string")return;a&&Eb(a,"//")&&(a=E.location.protocol+a);if(typeof URL==="function"){var c;a:{var d;try{d=new URL(a)}catch(w){c=void 0;break a}for(var e={},f=Array.from(d.searchParams),g=0;g0&&e.charAt(0)!=="."&&(f--,e="."+e);if(f>=0&&c.indexOf(e,f)===f)return!0}}return!1} -function VJ(a,b,c){for(var d={},e=!1,f=0;a&&f0&&isFinite(f)||(f=2E3);var g=function(m){return Math.max(f,m)};IA("fsl","mwt",g,0);e||IA("fsl","nv.mwt",g,0)}var k=function(m){m.push(b);return m}; +IA("fsl","ids",k,[]);e||IA("fsl","nv.ids",k,[]);EA("fsl","init",!1)||(QC(),FA("fsl","init",!0));return b}RC.F="internal.enableAutoEventOnFormSubmit"; +function WC(){var a=this;}WC.F="internal.enableAutoEventOnGaSend";var XC={},YC=[]; +var $C=function(a,b){var c=""+b;if(XC[c])XC[c].push(a);else{var d=[a];XC[c]=d;var e=ZC("gtm.historyChange-v2"),f=-1;YC.push(function(g){f>=0&&B.clearTimeout(f);b?f=B.setTimeout(function(){e(g,d);f=-1},b):e(g,d)})}},ZC=function(a){var b=B.location.href,c={source:null,state:B.history.state||null,url:Bj(Ej(b)),Ka:yj(Ej(b),"fragment")};return function(d,e){var f=c,g={};g[f.source]=!0;g[d.source]=!0;if(!g.popstate||!g.hashchange||f.Ka!==d.Ka){var k={event:a,"gtm.historyChangeSource":d.source,"gtm.oldUrlFragment":c.Ka, +"gtm.newUrlFragment":d.Ka,"gtm.oldHistoryState":c.state,"gtm.newHistoryState":d.state,"gtm.oldUrl":c.url,"gtm.newUrl":d.url};e&&(k["gtm.triggers"]=e.join(","));c=d;rz(k)}}},aD=function(a,b){var c=B.history,d=c[a];if(bb(d))try{c[a]=function(e,f,g){d.apply(c,[].slice.call(arguments,0));var k=B.location.href;b({source:a,state:e,url:Bj(Ej(k)),Ka:yj(Ej(k),"fragment")})}}catch(e){}},cD=function(a){B.addEventListener("popstate",function(b){var c=bD(b);a({source:"popstate",state:b.state,url:Bj(Ej(c)),Ka:yj(Ej(c), +"fragment")})})},dD=function(a){B.addEventListener("hashchange",function(b){var c=bD(b);a({source:"hashchange",state:null,url:Bj(Ej(c)),Ka:yj(Ej(c),"fragment")})})},bD=function(a){var b,c;return((b=a.target)==null?void 0:(c=b.location)==null?void 0:c.href)||B.location.href}; +function eD(a,b){var c=this;K(this.getName(),["options:?PixieMap","triggerId:?*"],arguments);xA([function(){L(c,"detect_history_change_events")}]);var d=a&&a.get("useV2EventName")?"ehl":"hl",e=Number(a&&a.get("interval"));e>0&&isFinite(e)||(e=0);if(!EA(d,"init",!1)){var f;d==="ehl"?(f=function(k){for(var m=0;m0){var f=Bj(Ej(c)),g=Bj(Ej(B.location.href));return f!==g}return!0},hD=function(a,b){for(var c=yj(Ej((b.attributes&&b.attributes.formaction?b.formAction:"")||b.action||Gc(b,"href")||b.src||b.code||b.codebase||""),"host"), +d=0;d0&&isFinite(k)||(k=2E3);var m=function(p){return Math.max(k,p)};IA("lcl","mwt",m,0);f||IA("lcl","nv.mwt",m,0)}var n=function(p){p.push(b); +return p};IA("lcl","ids",n,[]);f||IA("lcl","nv.ids",n,[]);g&&IA("lcl","aff.map",function(p){p[b]=g;return p},{});EA("lcl","init",!1)||(iD(),FA("lcl","init",!0));return b}jD.F="internal.enableAutoEventOnLinkClick";var kD,lD; +var mD=function(a){return EA("sdl",a,{})},nD=function(a,b,c){if(b){var d=Array.isArray(a)?a:[a];IA("sdl",c,function(e){for(var f=0;f=a.limit)a.lg&&B.clearInterval(a.lg);else{a.ai++;var b=qb();rz({event:a.eventName,"gtm.timerId":a.lg,"gtm.timerEventNumber":a.ai,"gtm.timerInterval":a.interval,"gtm.timerLimit":a.limit,"gtm.timerStartTime":a.Ck,"gtm.timerCurrentTime":b,"gtm.timerElapsedTime":b-a.Ck,"gtm.triggers":a.wn})}}} +function yD(a,b){ +return b}yD.F="internal.enableAutoEventOnTimer"; +var zD=function(a,b,c){function d(){var g=a();f+=e?(qb()-e)*g.playbackRate/1E3:0;e=qb()}var e=0,f=0;return{createEvent:function(g,k,m){var n=a(),p=n.Gh,q=m?Math.round(m):k?Math.round(n.Gh*k):Math.round(n.gk),r=k!==void 0?Math.round(k*100):p<=0?0:Math.round(q/p*100),u=E.hidden?!1:Ts(c)>=.5;d();var v=void 0;b!==void 0&&(v=[b]);var t=JA(c,"gtm.video",v);t["gtm.videoProvider"]="youtube";t["gtm.videoStatus"]=g;t["gtm.videoUrl"]=n.url;t["gtm.videoTitle"]=n.title;t["gtm.videoDuration"]=Math.round(p);t["gtm.videoCurrentTime"]= +Math.round(q);t["gtm.videoElapsedTime"]=Math.round(f);t["gtm.videoPercent"]=r;t["gtm.videoVisible"]=u;return t},yk:function(){e=qb()},zd:function(){d()}}};var Zb=wa(["data-gtm-yt-inspected-"]),AD=["www.youtube.com","www.youtube-nocookie.com"],BD,CD=!1; +var DD=function(a,b,c){var d=a.map(function(g){return{Ja:g,lf:g,hf:void 0}});if(!b.length)return d;var e=b.map(function(g){return{Ja:g*c,lf:void 0,hf:g}});if(!d.length)return e;var f=d.concat(e);f.sort(function(g,k){return g.Ja-k.Ja});return f},ED=function(a){a=a===void 0?[]:a;for(var b=[],c=0;c100||a[c]<0||(b[c]=a[c]/100);b.sort(function(d,e){return d- +e});return b},GD=function(a,b){var c,d;function e(){u=zD(function(){return{url:w,title:x,Gh:t,gk:a.getCurrentTime(),playbackRate:y}},b.Ib,a.getIframe());t=0;x=w="";y=1;return f}function f(I){switch(I){case 1:t=Math.round(a.getDuration());w=a.getVideoUrl();if(a.getVideoData){var J=a.getVideoData();x=J?J.title:""}y=a.getPlaybackRate();b.Ah?rz(u.createEvent("start")):u.zd();v=DD(b.ji,b.ii,a.getDuration());return g(I);default:return f}}function g(){A=a.getCurrentTime();C=pb().getTime();u.yk();r();return k} +function k(I){var J;switch(I){case 0:return n(I);case 2:J="pause";case 3:var H=a.getCurrentTime()-A;J=Math.abs((pb().getTime()-C)/1E3*y-H)>1?"seek":J||"buffering";a.getCurrentTime()&&(b.zh?rz(u.createEvent(J)):u.zd());q();return m;case -1:return e(I);default:return k}}function m(I){switch(I){case 0:return n(I);case 1:return g(I);case -1:return e(I);default:return m}}function n(){for(;d;){var I=c;B.clearTimeout(d);I()}b.yh&&rz(u.createEvent("complete",1));return e(-1)}function p(){}function q(){d&& +(B.clearTimeout(d),d=0,c=p)}function r(){if(v.length&&y!==0){var I=-1,J;do{J=v[0];if(J.Ja>a.getDuration())return;I=(J.Ja-a.getCurrentTime())/y;if(I<0&&(v.shift(),v.length===0))return}while(I<0);c=function(){d=0;c=p;v.length>0&&v[0].Ja===J.Ja&&(v.shift(),rz(u.createEvent("progress",J.hf,J.lf)));r()};d=B.setTimeout(c,I*1E3)}}var u,v=[],t,w,x,y,A,C,D=e(-1);d=0;c=p;return{onStateChange:function(I){D=D(I)},onPlaybackRateChange:function(I){A=a.getCurrentTime();C=pb().getTime();u.zd();y=I;q();r()}}},ID= +function(a){F(function(){function b(){for(var d=c.getElementsByTagName("iframe"),e=d.length,f=0;f0)return!0;if(b){var d;var e=c.indexOf("?")!==-1?"&":"?";c.indexOf("origin=")>-1?d=c+e+"enablejsapi=1":(BD||(BD=E.location.protocol+"//"+E.location.hostname,E.location.port&&(BD+=":"+E.location.port)),d=c+e+"enablejsapi=1&origin="+encodeURIComponent(BD));var f;f=Jb(d);a.src=Kb(f).toString();return!0}}return!1},LD=function(a,b){if(!a)return!1;for(var c=0;c=0)return!0;return!1},KD=function(){var a= +""+Math.round(Math.random()*1E9);return E.getElementById(a)?KD():a}; +function MD(a,b){var c=this;var d=function(){ID(p)};K(this.getName(),["dustOptions:!PixieMap","triggerId:?*"],arguments);xA([function(){L(c,"detect_youtube_activity_events",{fixMissingApi:!!a.get("fixMissingApi")})}]);b=DA(b);var e=!!a.get("captureStart"),f=!!a.get("captureComplete"),g=!!a.get("capturePause"),k=FD(G(a.get("progressThresholdsPercent"))),m=ED(G(a.get("progressThresholdsTimeInSeconds"))),n=!!a.get("fixMissingApi"); +if(!(e||f||g||k.length||m.length))return;var p={Ah:e,yh:f,zh:g,ii:k,ji:m,Qe:n,Ib:b},q=B.YT;if(q)return q.ready&&q.ready(d),b;var r=B.onYouTubeIframeAPIReady;B.onYouTubeIframeAPIReady=function(){r&&r();d()};F(function(){for(var u=E.getElementsByTagName("script"),v=u.length,t=0;t0&&(a.j[O.g.de]=b)};h.sm=function(a){a.j[O.g.de]=void 0;this.mi();this.C=0};h.Th=function(){return this.H&& +this.isVisible&&this.isActive};h.hm=function(){return this.C+this.ig()};h.ig=function(){return this.j&&this.j.get()||0};h.fn=function(a){this.K=a};h.xk=function(a){this.P=a};var hG=function(a){var b=a.metadata.event_usage;if(Array.isArray(b))for(var c=0;cd.cf+f*60))return a;var g=rG(b);if(!g)return a;g.Qc=d.Qc+1;var k;return(k=sG(g.sessionId,g.Qc,g.Nd,g.cf,g.Xh,g.Mc,g.Dd))!=null?k:b},wG=function(a,b){var c=b.metadata.cookie_options,d=uG(b,c),e=jp(a,vG[0],c.domain,c.path),f={Hb:O.g.U,domain:c.domain,path:c.path,expires:c.Fb?new Date(qb()+Number(c.Fb)*1E3):void 0,flags:c.flags}; +ap(d,void 0,f);return ap(d,e,f)!==1},xG=function(a){var b=a.metadata.cookie_options,c=uG(a,b),d=ip(c,b.domain,b.path,vG,O.g.U);if(!d)return d;var e=Qo(c,void 0,void 0,O.g.U);if(d&&e.length>1){V(114);for(var f=void 0,g=void 0,k=0;kg)&&(g=n,f=e[k])}}f&&!wb(f,d)&&(V(115),d=f.split(".").slice(2).join("."))}return d},yG=function(a){return sG(a.j[O.g.zb],a.j[O.g.te],a.j[O.g.se],Math.floor(a.metadata.event_start_timestamp_ms/ +1E3),a.metadata.join_timer_sec||0,!!a.metadata[O.g.Hf],a.j[O.g.ee])},sG=function(a,b,c,d,e,f,g){if(a&&b){var k=[a,b,lb(c),d,e];k.push(f?"1":"0");k.push(g||"0");return k.join(".")}},uG=function(a,b){return b.prefix+"_ga_"+a.target.ids[Zl[0]]},vG=["GS1"],rG=function(a){if(a){var b=a.split(".");if(!(b.length<5||b.length>7)){b.length<7&&V(67);var c=Number(b[1]),d=Number(b[3]),e=Number(b[4]||0);c||V(118);d||V(119);isNaN(e)&&V(120);if(c&&d&&!isNaN(e))return{sessionId:b[0],Qc:c,Nd:!!Number(b[2]),cf:d,Xh:e, +Mc:b[5]==="1",Dd:b[6]!=="0"?b[6]:void 0}}}}; +var zG=function(a){var b=W(a.m,O.g.sa),c=a.m.C[O.g.sa];if(c===b)return c;var d=Vc(b,null);c&&c[O.g.X]&&(d[O.g.X]=(d[O.g.X]||[]).concat(c[O.g.X]));return d},AG=function(a,b){var c=Dp(!0);return c._up!=="1"?{}:{clientId:c[a],Wa:c[b]}},BG=function(a,b,c){var d=Dp(!0),e=d[b];e&&(mG(a,e,2),nG(e,a));var f=d[c];f&&wG(f,a);return{clientId:e,Wa:f}},CG=function(){var a=Aj(B.location,"host"),b=Aj(Ej(E.referrer),"host");return a&&b?a===b||a.indexOf("."+b)>=0||b.indexOf("."+a)>=0?!0:!1:!1},DG=function(a){if(!W(a.m, +O.g.cb))return{};var b=a.metadata.cookie_options,c=b.prefix+"_ga",d=uG(a,b);Lp(function(){var e;if(X("analytics_storage"))e={};else{var f={};e=(f._up="1",f[c]=a.j[O.g.tb],f[d]=yG(a),f)}return e},1);return!X("analytics_storage")&&CG()?AG(c,d):{}},FG=function(a){var b=zG(a)||{},c=a.metadata.cookie_options,d=c.prefix+"_ga",e=uG(a,c),f={};Np(b[O.g.Hc],!!b[O.g.X])&&(f=BG(a,d,e),f.clientId&&f.Wa&&(EG=!0));b[O.g.X]&&Kp(function(){var g={},k=qG(a);k&&(g[d]=k);var m=xG(a);m&&(g[e]=m);var n=Qo("FPLC",void 0, +void 0,O.g.U);n.length&&(g._fplc=n[0]);return g},b[O.g.X],b[O.g.Pb],!!b[O.g.yb]);return f},EG=!1;var GG=function(a){if(!a.metadata.is_merchant_center&&Lj(a.m)){var b=zG(a)||{},c=(Np(b[O.g.Hc],!!b[O.g.X])?Dp(!0)._fplc:void 0)||(Qo("FPLC",void 0,void 0,O.g.U).length>0?void 0:"0");a.j._fplc=c}};function HG(a){if(Qt(a)||fj())a.j[O.g.yj]=pl()||ol();!Qt(a)&&fj()&&(a.j[O.g.Hj]="::")}function IG(a){if(R(69)&&fj()){ls(a);ms(a,"cpf",W(a.m,O.g.Na));var b=W(a.m,O.g.hc);ms(a,"cu",b===!0?1:b===!1?0:void 0);ms(a,"cf",W(a.m,O.g.ab));ms(a,"cd",fp(W(a.m,O.g.Ra),W(a.m,O.g.vb)))}};var KG=function(a,b){var c=Ji.grl;c||(c=JG(),Ji.grl=c);c(b)||(V(35),a.isAborted=!0)},JG=function(){var a=qb(),b=a+864E5,c=20,d=5E3;return function(e){var f=qb();f>=b&&(b=f+864E5,d=5E3);c=Math.min(c+(f-a)/1E3*5,20);a=f;var g=!1;d<1||c<1||(g=!0,d--,c--);e&&(e.Sl=d,e.Ml=c);return g}}; +var LG=function(a){if(W(a.m,O.g.ld)!==void 0)a.copyToHitData(O.g.ld);else{var b=W(a.m,O.g.Nf),c,d;a:{if(EG){var e=zG(a)||{};if(e&&e[O.g.X])for(var f=yj(Ej(a.j[O.g.Fa]),"host",!0),g=e[O.g.X],k=0;k=0){d=!0;break a}}d=!1}if(!(c=d)){var m;if(m=b)a:{for(var n=b.include_conditions||[],p=yj(Ej(a.j[O.g.Fa]),"host",!0),q=0;q0||c.jg)&&(R(100)||(d.em=c.Gb),c.xa)){var g=c.xa.Cd;g&&!R(12)&&(g=g.replace(/./g,"*"));g&&(d.eme=g);d._es=c.xa.status;c.xa.time!==void 0&&(d._est=c.xa.time)}a.metadata.create_google_join&&(d._gaz=1);MG(d,a);Io()&&(d.dma_cps=Go());d.dma=Ho();Xn(mo())&&(d.tcfd=Jo());dj()&&(d.tag_exp=dj());var k=a.j[O.g.hb];k&&(d.gdid=k);e.en=String(a.eventName);a.metadata.is_first_visit&& +(e._fv=a.metadata.is_first_visit_conversion?2:1);a.metadata.is_new_to_site&&(e._nsi=1);a.metadata.is_session_start&&(e._ss=a.metadata.is_session_start_conversion?2:1);a.metadata.is_conversion&&(e._c=1);a.metadata.is_external_event&&(e._ee=1);if(a.metadata.is_ecommerce){var m=a.j[O.g.da]||W(a.m,O.g.da);if(Array.isArray(m))for(var n=0;n=0&&(c=a.pathname.substring(0,d));b.transport_url=a.protocol+"//"+a.hostname+c;return b},dH=function(a,b,c){var d=0,e=new B.XMLHttpRequest;e.withCredentials=!0;e.onprogress=function(f){if(e.status===200){var g=e.responseText.substring(d);d=f.loaded;$G(c,g)}};e.open(b?"POST":"GET",a);e.setAttributionReporting&&e.setAttributionReporting({eventSourceEligible:!1,triggerEligible:!0}); +e.send(b)},fH=function(a,b,c){var d=Object.assign({},eH);b&&(d.body=b,d.method="POST");B.fetch(a,d).then(function(e){if(e.ok&&e.body){var f=e.body.getReader(),g=new TextDecoder;return new Promise(function(k){function m(){f.read().then(function(n){var p;p=n.done;var q=g.decode(n.value,{stream:!p});$G(c,q);p?k():m()}).catch(function(){k()})}m()})}}).catch(function(){R(104)&&(a+="&_z=retryFetch",b?Cc(a,b):Bc(a))})},gH=function(a,b){return ZG(new YG(function(c,d){var e=bH(c,a);b&&(e=e.replace("_is_sw=0", +b));var f={};d.attribution_reporting&&(f.attributionsrc="");uc(e,void 0,void 0,f)}),function(c,d){var e=bH(c,a),f=d.dedupe_key;f&&Fu(e,f)})},hH=function(a,b,c,d){var e=gH(c,d);R(103)&&Fc()?fH(a,b,e):dH(a,b,e)},iH=function(a,b){var c=Ej(a),d=cH(c),e=aH(c);R(108)?mu(e,b,d,function(f){hH(e,b,d,f)}):hH(e,b,d)},eH=Object.freeze({cache:"no-store",credentials:"include",method:"GET",keepalive:!0,redirect:"follow"}); +var jH=function(a,b){return a?[a,b].join("&"):b},kH=function(a,b,c){var d=a+"?"+b;c?Cc(d,c):Bc(d)},mH=function(a,b,c,d){var e=b,f=Hc();f!==void 0&&(e+="&tfd="+Math.round(f));b=e;var g=a+"?"+b;lH&&(d=!vb(g,OG())&&!vb(g,NG()));if(d&&!cG)iH(g,c);else{var k=b;Fc()?Ec(a+"?"+k,c,{noFallback:!0})||kH(a,jH(k,"_z=failedfetch"),c):kH(a,jH(k,"_z=nofetch"),c)}},nH=function(a,b){function c(v){n.push(v+"="+encodeURIComponent(""+a.ja[v]))}var d=b.mn,e=b.nn,f=b.jm,g=b.Dm,k=b.Cm,m=b.dn;if(d||e){var n=[];a.ja._ng&& +c("_ng");c("tid");c("cid");c("gtm");n.push("aip=1");a.Rc.uid&&!k&&n.push("uid="+encodeURIComponent(""+a.Rc.uid));var p=function(){c("dma");a.ja.dma_cps!=null&&c("dma_cps");a.ja.gcs!=null&&c("gcs");c("gcd");a.ja.npa!=null&&c("npa")};p();a.ja.frm!=null&&c("frm");d&&(dj()&&n.push("tag_exp="+dj()),kH("https://stats.g.doubleclick.net/g/collect","v=2&"+n.join("&")),n.join("&"));if(e){var q=function(){var v=Hu()+"/td/ga/rul?";n=[];c("tid");n.push("gacid="+encodeURIComponent(String(a.ja.cid)));c("gtm");p(); +c("pscdl");a.ja._ng!=null&&c("_ng");n.push("aip=1");n.push("fledge=1");a.ja.frm!=null&&c("frm");dj()&&n.push("tag_exp="+dj());n.push("z="+fb());var t=v+n.join("&");Fu(t,a.ja.tid)};dj()&&n.push("tag_exp="+dj());n.push("z="+fb());if(!g){var r=f&&vb(f,"google.")&&f!=="google.com"?"https://www.%/ads/ga-audiences?v=1&t=sr&slf_rd=1&_r=4&".replace("%",f):void 0;if(r){var u=r+n.join("&");uc(u)}}R(84)&&m&&!cG&&q()}}},lH=!1; +var oH=function(){this.K=1;this.P={};this.H=-1;this.C=new ag};oH.prototype.j=function(a,b){var c=this,d=new XG(a,this.P,b),e=dG(a);e&&this.C.P(d)||this.flush();if(e&&this.C.add(d)){if(this.H<0){var f=B.setTimeout,g;Qt(a)?pH?(pH=!1,g=qH):g=rH:g=5E3;this.H=f.call(B,function(){c.flush()},g)}}else{var k=dg(d,this.K++);mH(d.baseUrl,k.params,k.body,d.H);var m=a.metadata.create_dc_join,n=a.metadata.create_google_join,p=W(a.m,O.g.Ea)!==!1,q=zo(a.m),r={eventId:a.m.eventId,priorityId:a.m.priorityId},u=a.j[O.g.hh], +v={mn:m,nn:n,jm:ul(),Wn:p,Vn:q,Dm:ql(),Cm:a.metadata.euid_mode_enabled,ao:r,dn:u,m:a.m};nH(d,v)}nw(a.m.eventId,a.eventName)};oH.prototype.add=function(a){!a.metadata.euid_mode_enabled||cG||R(100)?this.j(a):this.aa(a)};oH.prototype.flush=function(){if(this.C.events.length){var a=fg(this.C,this.K++);mH(this.C.baseUrl,a.params,a.body,this.C.C);this.C=new ag;this.H>=0&&(B.clearTimeout(this.H),this.H=-1)}};oH.prototype.aa=function(a){var b=this,c=Pt(a);if(zi(c)){var d=mi(c,R(75));d?d.then(function(g){b.j(a, +g)},function(){b.j(a)}):this.j(a)}else{var e=yi(c);if(R(75)){var f=ki(e);f?f.then(function(g){b.j(a,g)},function(){b.j(a,e)}):this.j(a,e)}else this.j(a,e)}};var qH=Yh('',500),rH=Yh('',5E3),pH=!0; +var sH=function(a,b,c){c===void 0&&(c={});if(b==null)return c;if(typeof b==="object")for(var d=l(Object.keys(b)),e=d.next();!e.done;e=d.next()){var f=e.value;sH(a+"."+f,b[f],c)}else c[a]=b;return c},tH=function(a){for(var b={},c=l(a),d=c.next();!d.done;d=c.next()){var e=d.value;b[e]=!!X(e)}return b},vH=function(a,b){var c=uH.filter(function(e){return!X(e)});if(c.length){var d=tH(c);Dl(c,function(){for(var e=tH(c),f=[],g=l(c),k=g.next();!k.done;k=g.next()){var m=k.value;!d[m]&&e[m]&&f.push(m);e[m]&& +(d[m]=!0)}if(f.length){b.metadata.is_consent_update=!0;var n=f.map(function(p){return Ah[p]}).join(".");n&&Mt(b,"gcut",n);a(b)}})}},wH=function(a){if(R(125)&&Qt(a)){var b=W(a.m,O.g.Qb),c;b===!0&&(c="1");b===!1&&(c="0");c&&Mt(a,"rdp",c)}},xH=function(a){R(123)&&Qt(a)&&W(a.m,O.g.Ud,!0)===!1&&(a.j[O.g.Ud]=0)},yH=function(a,b){if(Qt(b)){var c=b.metadata.is_conversion;(b.eventName==="page_view"||c)&&vH(a,b)}},zH=function(a){if(Qt(a)&&a.eventName===O.g.Uc&&a.metadata.is_consent_update){var b=a.j[O.g.Cg]; +b&&(Mt(a,"gcut",b),Mt(a,"syn",1))}},AH=function(a){R(124)&&Qt(a)&&W(a.m,O.g.Ea)!==!1&&Du("join-ad-interest-group")&&bb(gc.joinAdInterestGroup)&&Mt(a,"flg",1)},BH=function(a){Qt(a)&&(a.metadata.speculative=!1)},CH=function(a){Qt(a)&&(a.metadata.speculative&&Mt(a,"sp",1),a.metadata.is_syn&&Mt(a,"syn",1),a.metadata.em_event&&(Mt(a,"em_event",1),Mt(a,"sp",1)))},DH=function(a){if(Qt(a)){var b=Wi;b&&Mt(a,"tft",Number(b))}},EH=function(a){function b(e){var f=sH(O.g.Ga,e);ib(f,function(g,k){a.j[g]=k})}if(Qt(a)){var c= +Nt(a,"ccd_add_1p_data",!1)?1:0;Mt(a,"ude",c);var d=W(a.m,O.g.Ga);d!==void 0?(b(d),a.j[O.g.vd]="c"):b(a.metadata.user_data);a.metadata.user_data=void 0}},FH=function(a){if(Qt(a)){var b=Yr();b&&Mt(a,"us_privacy",b);var c=to();c&&Mt(a,"gdpr",c);var d=so();d&&Mt(a,"gdpr_consent",d)}},GH=function(a){Qt(a)&&cl()&&W(a.m,O.g.ia)&&Mt(a,"adr",1)},HH=function(a){if(Qt(a)){var b=QG?sl():"";b&&Mt(a,"gcsub",b)}},IH=function(a){if(Qt(a)){W(a.m,O.g.sb,void 0,4)===!1&&Mt(a,"ngs",1);ql()&&Mt(a,"ga_rd",1);wE()||Mt(a, +"ngst",1);var b=ul();b&&Mt(a,"etld",b)}},JH=function(a){},KH=function(a){Qt(a)&&cl()&&Mt(a,"rnd",Er())},uH=[O.g.O,O.g.N]; +var LH=function(a,b){var c;a:{var d=yG(a);if(d){if(wG(d,a)){c=d;break a}V(25);a.isAborted=!0}c=void 0}var e=c;return{clientId:oG(a,b),Wa:e}},MH=function(a,b,c,d,e){var f=W(a.m,O.g.tb);if(W(a.m,O.g.Ob)&&W(a.m,O.g.jc))f?mG(a,f,1):(V(127),a.isAborted=!0);else{var g=f?1:8;a.metadata.is_new_to_site=!1;f||(f=qG(a),g=3);f||(f=b,g=5);if(!f){var k=X(O.g.U),m=jG();f=!m.from_cookie||k?m.vid:void 0;g=6}f?f=""+f:(f=hp(),g=7,a.metadata.is_first_visit=a.metadata.is_new_to_site=!0);mG(a,f,g)}var n=Math.floor(a.metadata.event_start_timestamp_ms/ +1E3),p=void 0;a.metadata.is_new_to_site||(p=xG(a)||c);var q=lb(W(a.m,O.g.sd,30));q=Math.min(475,q);q=Math.max(5,q);var r=lb(W(a.m,O.g.Pf,1E4)),u=rG(p);a.metadata.is_first_visit=!1;a.metadata.is_session_start=!1;a.metadata.join_timer_sec=0;u&&u.Xh&&(a.metadata.join_timer_sec=Math.max(0,u.Xh-Math.max(0,n-u.cf)));var v=!1;u||(v=a.metadata.is_first_visit=!0,u={sessionId:String(n),Qc:1,Nd:!1,cf:n,Mc:!1,Dd:void 0});n>u.cf+q*60&&(v=!0,u.sessionId=String(n),u.Qc++,u.Nd=!1,u.Dd=void 0);if(v)a.metadata.is_session_start= +!0,d.sm(a);else if(d.hm()>r||a.eventName===O.g.ac)u.Nd=!0;a.metadata.euid_mode_enabled?W(a.m,O.g.Ca)?u.Mc=!0:(u.Mc&&!R(13)&&(u.Dd=void 0),u.Mc=!1):u.Mc=!1;var t=u.Dd;if(a.metadata.euid_mode_enabled||Qt(a)){var w=W(a.m,O.g.ee),x=w?1:8;w||(w=t,x=4);w||(w=gp(),x=7);var y=w.toString(),A=x,C=a.metadata.enhanced_client_id_source;if(C===void 0||A<=C)a.j[O.g.ee]=y,a.metadata.enhanced_client_id_source=A}e?(a.copyToHitData(O.g.zb,u.sessionId),a.copyToHitData(O.g.te,u.Qc),a.copyToHitData(O.g.se,u.Nd?1:0)):(a.j[O.g.zb]= +u.sessionId,a.j[O.g.te]=u.Qc,a.j[O.g.se]=u.Nd?1:0);a.metadata[O.g.Hf]=u.Mc?1:0};var NH=window,OH=document,PH=function(a){var b=NH._gaUserPrefs;if(b&&b.ioo&&b.ioo()||OH.documentElement.hasAttribute("data-google-analytics-opt-out")||a&&NH["ga-disable-"+a]===!0)return!0;try{var c=NH.external;if(c&&c._gaUserPrefs&&c._gaUserPrefs=="oo")return!0}catch(p){}for(var d=[],e=String(OH.cookie).split(";"),f=0;f0&&gG(17);kI(a);MH(a,this.clientId,this.Wa,this.C,!this.Ua);lI(a);mI(a);nI(a);oI(a);pI(a);qI(a);rI(a);GG(a);LG(a);KH(a);JH(a);IH(a);HH(a);GH(a);FH(a);DH(a);CH(a);AH(a);zH(a);xH(a);wH(a);HG(a);IG(a);sI(a);tI(a);uI(a);js(a);is(a);vI(a);wI(a);Gs(a);xI(a);EH(a);BH(a);yI(a);!this.K&&a.metadata.em_event&&gG(18);hG(a);if(a.metadata.speculative||a.isAborted){a.m.onFailure();iG();return}this.wk(LH(a,this.clientId));this.Ua=!0;this.rn(a);zI(a);yH(function(f){b.dk(f)},a);this.C.mi();AI(a);if(a.isAborted){a.m.onFailure(); +iG();return}this.dk(a);a.m.onSuccess()}catch(f){a.m.onFailure()}iG()};h.dk=function(a){this.aa.add(a)};h.wk=function(a){var b=a.clientId,c=a.Wa;b&&c&&(this.clientId=b,this.Wa=c)};h.flush=function(){this.aa.flush()};h.rn=function(a){var b=this;if(!this.P){var c=X(O.g.N),d=X(O.g.U);Dl([O.g.N,O.g.U],function(){var e=X(O.g.N),f=X(O.g.U),g=!1,k={},m={};if(d!==f&&b.j&&b.Wa&&b.clientId){var n=b.clientId,p;var q=rG(b.Wa);p=q?q.Dd:void 0;if(f){var r=qG(b.j);if(r){b.clientId=r;var u=xG(b.j);u&&(b.Wa=tG(u,b.Wa, +b.j))}else nG(b.clientId,b.j),lG(b.clientId,!0);wG(b.Wa,b.j);g=!0;k[O.g.Tg]=n;R(64)&&p&&(k[O.g.kl]=p)}else b.Wa=void 0,b.clientId=void 0,B.gaGlobal={}}e&&!c&&(g=!0,m.is_consent_update=!0,k[O.g.Cg]=Ah[O.g.N]);if(g){var v=py(b.H,O.g.Uc,k);ry(v,a.m.eventId,{eventMetadata:m})}d=f;c=e});this.P=!0}};h.tl=function(a){a.eventName!==O.g.Ya&&this.C.sl(a)};var cI=function(a){var b=E.location.protocol;b!=="http:"&&b!=="https:"&&(V(29),a.isAborted=!0)},dI=function(a){gc&&gc.loadPurpose==="preview"&&(V(30),a.isAborted= +!0)},eI=function(a){var b={prefix:String(W(a.m,O.g.Na,"")),path:String(W(a.m,O.g.vb,"/")),flags:String(W(a.m,O.g.ab,"")),domain:String(W(a.m,O.g.Ra,"auto")),Fb:Number(W(a.m,O.g.Sa,63072E3))};a.metadata.cookie_options=b},gI=function(a){if(a.metadata.is_merchant_center)a.metadata.euid_mode_enabled=!1;else if(Nt(a,"ccd_add_1p_data",!1)||Nt(a,"ccd_add_ec_stitching",!1))a.metadata.euid_mode_enabled=!0},hI=function(a){if(a.metadata.euid_mode_enabled&&Nt(a,"ccd_add_1p_data",!1)){var b=a.m.C[O.g.ue];if(uj(b)){var c= +W(a.m,O.g.Ga);c===null?a.metadata.user_data_from_code=null:(b.enable_code&&Uc(c)&&(a.metadata.user_data_from_code=c),Uc(b.selectors)&&!a.metadata.user_data_from_manual&&(a.metadata.user_data_from_manual=sj(b.selectors)))}}},iI=function(a){if(R(73)&&!R(72)&&Nt(a,"ga4_ads_linked",!1)&&a.eventName===O.g.ba){var b=W(a.m,O.g.ra)!==!1;if(b){var c=Zr(a);c.Fb&&(c.Fb=Math.min(c.Fb,7776E3));$r({Bd:b,Kd:W(a.m,O.g.sa)||{},Pd:W(a.m,O.g.cb),rc:c})}}},sI=function(a){if(!vu(B))V(87);else if(Bu!==void 0){V(85);var b= +tu();b?W(a.m,O.g.qe)&&!Qt(a)||yu(b,a):V(86)}},jI=function(a){a.eventName===O.g.ba&&(W(a.m,O.g.Oa,!0)?(a.m.j[O.g.fa]&&(a.m.H[O.g.fa]=a.m.j[O.g.fa],a.m.j[O.g.fa]=void 0,a.j[O.g.fa]=void 0),a.eventName=O.g.ac):a.isAborted=!0)},fI=function(a){function b(c,d){nh[c]||d===void 0||(a.j[c]=d)}ib(a.m.H,b);ib(a.m.j,b)},lI=function(a){var b=rm(a.m),c=function(d,e){XH[d]&&(a.j[d]=e)};Uc(b[O.g.Zc])?ib(b[O.g.Zc],function(d,e){c((O.g.Zc+"_"+d).toLowerCase(),e)}):ib(b,c)},kI=VH,zI=function(a){if(R(108)&&X(O.g.U)){Qt(a)&& +(a.metadata.is_sgtm_service_worker=!0,Qt(a)&&Mt(a,"sw_exp",1));a:{}}},vI=function(a){if(a.eventName===O.g.Ya){var b=W(a.m,O.g.xb);W(a.m,O.g.Mb)(a.j[b]||W(a.m,b));a.isAborted=!0}},mI=function(a){if(!W(a.m,O.g.jc)||!W(a.m,O.g.Ob)){var b=a.copyToHitData, +c=O.g.wa,d="",e=E.location;if(e){var f=e.pathname||"";f.charAt(0)!=="/"&&(f="/"+f);var g=e.search||"";if(g&&g[0]==="?")for(var k=g.substring(1).split("&"),m=0;m=0)a.isAborted=!0;else{var b=Ot(a);b&&b.blacklisted&&(a.isAborted=!0)}},pI=function(a){var b=function(c){return!!c&&c.conversion};a.metadata.is_conversion=b(Ot(a));a.metadata.is_first_visit&&(a.metadata.is_first_visit_conversion=b(Ot(a, +"first_visit")));a.metadata.is_session_start&&(a.metadata.is_session_start_conversion=b(Ot(a,"session_start")))},qI=function(a){rh.hasOwnProperty(a.eventName)&&(a.metadata.is_ecommerce=!0,a.copyToHitData(O.g.da),a.copyToHitData(O.g.Aa))},xI=function(a){if(R(79)&&a.metadata.is_conversion&&X(O.g.O)&&Nt(a,"ga4_ads_linked",!1)){var b=Zr(a),c=Eq(b.prefix),d=Rr(c);a.j[O.g.wf]=d.Mh;a.j[O.g.yf]=d.Oh;a.j[O.g.xf]=d.Nh}}; +function $H(a){ib(a,function(c){c.charAt(0)==="_"&&delete a[c]});var b=a[O.g.jb]||{};ib(b,function(c){c.charAt(0)==="_"&&delete b[c]})}var CI=function(a){if(!BI(a)){var b=!1,c=function(){!b&&BI(a)&&(b=!0,wc(E,"visibilitychange",c),R(4)&&wc(E,"prerenderingchange",c),V(55))};vc(E,"visibilitychange",c);R(4)&&vc(E,"prerenderingchange",c);V(54)}},BI=function(a){if(R(4)&&"prerendering"in E?E.prerendering:E.visibilityState==="prerender")return!1;a();return!0};function DI(a,b){CI(function(){var c=Wl(a);if(c){var d=EI(c,b);Xm(a,d)}});}function EI(a,b){var c=function(){};var d=new ZH(a.id),e=a.prefix==="MC";c=function(f,g,k,m){e&&(m.eventMetadata.is_merchant_center=!0);d.Zm(g,k,m)};fk||FI(a,d,b);return c} +function FI(a,b,c){var d=b.C,e={},f={eventId:c,eventMetadata:(e.batch_on_navigation=!0,e)};R(49)&&(f.deferrable=!0);d.fn(function(){cG=!0;Ym.flush();d.ig()>=1E3&&gc.sendBeacon!==void 0&&Zm(O.g.Uc,{},a.id,f);b.flush();d.xk(function(){cG=!1;d.xk()})});};var GI=EI;function II(a,b,c){var d=this;}II.F="internal.gtagConfig";function JI(){var a={};return a}; +function LI(a,b){}LI.T="gtagSet";function MI(){var a={};return a};function NI(a,b){}NI.T="injectHiddenIframe";var OI=mA(); +function PI(a,b,c,d,e){var f=this;}PI.F="internal.injectHtml";var TI={}; +function VI(a,b,c,d){}var WI={dl:1,id:1},XI={}; +function YI(a,b,c,d){}VI.T="injectScript";YI.F="internal.injectScript";function ZI(a){var b=!0;return b}ZI.T="isConsentGranted";function $I(a){var b=!1;return b}$I.F="internal.isDebugMode";function aJ(){return rl()}aJ.F="internal.isDmaRegion";function bJ(a){var b=!1;return b}bJ.F="internal.isEntityInfrastructure";function cJ(){var a=!1;return a}cJ.F="internal.isLandingPage";function dJ(){var a=Zg(function(b){BA(this).log("error",b)});a.T="JSON";return a};function eJ(a){var b=void 0;return hd(b)}eJ.F="internal.legacyParseUrl";function fJ(){return!1} +var gJ={getItem:function(a){var b=null;return b},setItem:function(a,b){return!1},removeItem:function(a){}};function hJ(){}hJ.T="logToConsole";function iJ(a,b){}iJ.F="internal.mergeRemoteConfig";function jJ(a,b,c){c=c===void 0?!0:c;var d=[];return hd(d)}jJ.F="internal.parseCookieValuesFromString";function kJ(a){var b=void 0;if(typeof a!=="string")return;a&&vb(a,"//")&&(a=E.location.protocol+a);if(typeof URL==="function"){var c;a:{var d;try{d=new URL(a)}catch(w){c=void 0;break a}for(var e={},f=Array.from(d.searchParams),g=0;g0&&e.charAt(0)!=="."&&(f--,e="."+e);if(f>=0&&c.indexOf(e,f)===f)return!0}}return!1} +function jK(a,b,c){for(var d={},e=!1,f=0;a&&f=0))throw e(f,{eventName:g},"Prohibited listen on data layer event.");},M:a}})}(); Z.securityGroups.detect_user_provided_data=["google"],function(){function a(b,c){return{dataSource:c}}(function(b){Z.__detect_user_provided_data=b;Z.__detect_user_provided_data.o="detect_user_provided_data";Z.__detect_user_provided_data.isVendorTemplate=!0;Z.__detect_user_provided_data.priorityOverride=0;Z.__detect_user_provided_data.isInfrastructure=!1;Z.__detect_user_provided_data.runInSiloedMode=!1})(function(b){var c=b.vtp_createPermissionError;return{assert:function(d,e){if(e!=="auto"&&e!=="manual"&& e!=="code")throw c(d,{},"Unknown user provided data source.");if(b.vtp_limitDataSources)if(e!=="auto"||b.vtp_allowAutoDataSources){if(e==="manual"&&!b.vtp_allowManualDataSources)throw c(d,{},"Detection of user provided data via manually specified CSS selectors is not allowed.");if(e==="code"&&!b.vtp_allowCodeDataSources)throw c(d,{},"Detection of user provided data from an in-page variable is not allowed.");}else throw c(d,{},"Automatic detection of user provided data is not allowed.");},M:a}})}(); @@ -5254,38 +5256,38 @@ Z.securityGroups.get_url=["google"],function(){function a(b,c,d){return{component:c,queryKey:d}}(function(b){Z.__get_url=b;Z.__get_url.o="get_url";Z.__get_url.isVendorTemplate=!0;Z.__get_url.priorityOverride=0;Z.__get_url.isInfrastructure=!1;Z.__get_url.runInSiloedMode=!1})(function(b){var c=b.vtp_urlParts==="any"?null:[];c&&(b.vtp_protocol&&c.push("protocol"),b.vtp_host&&c.push("host"),b.vtp_port&&c.push("port"),b.vtp_path&&c.push("path"),b.vtp_extension&&c.push("extension"),b.vtp_query&&c.push("query"), -b.vtp_fragment&&c.push("fragment"));var d=c&&b.vtp_queriesAllowed!=="any"?b.vtp_queryKeys||[]:null,e=b.vtp_createPermissionError;return{assert:function(f,g,k){if(g){if(!l(g))throw e(f,{},"URL component must be a string.");if(c&&c.indexOf(g)<0)throw e(f,{},"Prohibited URL component: "+g);if(g==="query"&&d){if(!k)throw e(f,{},"Prohibited from getting entire URL query when query keys are specified.");if(!l(k))throw e(f,{},"Query key must be a string.");if(d.indexOf(k)<0)throw e(f,{},"Prohibited query key: "+ +b.vtp_fragment&&c.push("fragment"));var d=c&&b.vtp_queriesAllowed!=="any"?b.vtp_queryKeys||[]:null,e=b.vtp_createPermissionError;return{assert:function(f,g,k){if(g){if(!z(g))throw e(f,{},"URL component must be a string.");if(c&&c.indexOf(g)<0)throw e(f,{},"Prohibited URL component: "+g);if(g==="query"&&d){if(!k)throw e(f,{},"Prohibited from getting entire URL query when query keys are specified.");if(!z(k))throw e(f,{},"Query key must be a string.");if(d.indexOf(k)<0)throw e(f,{},"Prohibited query key: "+ k);}}else if(c)throw e(f,{},"Prohibited from getting entire URL when components are specified.");},M:a}})}(); -Z.securityGroups.gct=["google"],function(){function a(b){for(var c=[],d=0;d0&&(c[O.g.md]=d);c[O.g.Zd]=b.vtp_eventSettings;c[O.g.zg]=b.vtp_dynamicEventSettings;c[O.g.Bc]=b.vtp_googleSignals===1;c[O.g.Mg]=b.vtp_foreignTld;c[O.g.Jg]=b.vtp_restrictDomain=== -1;c[O.g.Cf]=b.vtp_internalTrafficResults;var e=O.g.oa,f=b.vtp_linker;f&&f[O.g.W]&&(f[O.g.W]=a(f[O.g.W]));c[e]=f;var g=O.g.Gf,k=b.vtp_referralExclusionDefinition;k&&k.include_conditions&&(k.include_conditions=a(k.include_conditions));c[g]=k;var m=qk(b.vtp_trackingId);an(m,c);rI(m,b.vtp_gtmEventId);F(b.vtp_gtmOnSuccess)})}(); +Z.securityGroups.gct=["google"],function(){function a(b){for(var c=[],d=0;d0&&(c[O.g.sd]=d);c[O.g.ie]=b.vtp_eventSettings;c[O.g.Ig]=b.vtp_dynamicEventSettings;c[O.g.Gc]=b.vtp_googleSignals===1;c[O.g.Vg]=b.vtp_foreignTld;c[O.g.Sg]=b.vtp_restrictDomain=== +1;c[O.g.Jf]=b.vtp_internalTrafficResults;var e=O.g.sa,f=b.vtp_linker;f&&f[O.g.X]&&(f[O.g.X]=a(f[O.g.X]));c[e]=f;var g=O.g.Nf,k=b.vtp_referralExclusionDefinition;k&&k.include_conditions&&(k.include_conditions=a(k.include_conditions));c[g]=k;var m=sk(b.vtp_trackingId);cn(m,c);DI(m,b.vtp_gtmEventId);F(b.vtp_gtmOnSuccess)})}(); -Z.securityGroups.get=["google"],Z.__get=function(a){var b=a.vtp_settings,c=b.eventParameters||{},d=String(a.vtp_eventName),e={};e.eventId=a.vtp_gtmEventId;e.priorityId=a.vtp_gtmPriorityId;a.vtp_deferrable&&(e.deferrable=!0);var f=ly(String(b.streamId),d,c);ny(f,e.eventId,e);a.vtp_gtmOnSuccess()},Z.__get.o="get",Z.__get.isVendorTemplate=!0,Z.__get.priorityOverride=0,Z.__get.isInfrastructure=!1,Z.__get.runInSiloedMode=!1; +Z.securityGroups.get=["google"],Z.__get=function(a){var b=a.vtp_settings,c=b.eventParameters||{},d=String(a.vtp_eventName),e={};e.eventId=a.vtp_gtmEventId;e.priorityId=a.vtp_gtmPriorityId;a.vtp_deferrable&&(e.deferrable=!0);var f=py(String(b.streamId),d,c);ry(f,e.eventId,e);a.vtp_gtmOnSuccess()},Z.__get.o="get",Z.__get.isVendorTemplate=!0,Z.__get.priorityOverride=0,Z.__get.isInfrastructure=!1,Z.__get.runInSiloedMode=!1; Z.securityGroups.detect_scroll_events=["google"],function(){function a(){return{}}(function(b){Z.__detect_scroll_events=b;Z.__detect_scroll_events.o="detect_scroll_events";Z.__detect_scroll_events.isVendorTemplate=!0;Z.__detect_scroll_events.priorityOverride=0;Z.__detect_scroll_events.isInfrastructure=!1;Z.__detect_scroll_events.runInSiloedMode=!1})(function(){return{assert:function(){},M:a}})}(); Z.securityGroups.detect_form_interaction_events=["google"],function(){function a(){return{}}(function(b){Z.__detect_form_interaction_events=b;Z.__detect_form_interaction_events.o="detect_form_interaction_events";Z.__detect_form_interaction_events.isVendorTemplate=!0;Z.__detect_form_interaction_events.priorityOverride=0;Z.__detect_form_interaction_events.isInfrastructure=!1;Z.__detect_form_interaction_events.runInSiloedMode=!1})(function(){return{assert:function(){},M:a}})}(); -var mK={};mK.dataLayer=ij;mK.callback=function(a){Wi.hasOwnProperty(a)&&mb(Wi[a])&&Wi[a]();delete Wi[a]};mK.bootstrap=0;mK._spx=!1; -function nK(){Hi[kk()]=Hi[kk()]||mK;uk();yk()||z(zk(),function(d,e){$w(d,e.transportUrl,e.context);U(92)});Cb(Xi,Z.securityGroups);var a=ok(pk()),b,c=a==null?void 0:(b=a.context)==null?void 0:b.source;c!==2&&c!==4&&c!==3||U(142);qf=Hf}var oK=!1; -(function(a){function b(){n=E.documentElement.getAttribute("data-tag-assistant-present");qz(n)&&(m=k.pj)}function c(){m&&rc?g(m):a()}if(!C["__TAGGY_INSTALLED"]){var d=!1;if(E.referrer){var e=Aj(E.referrer);d=wj(e,"host")==="cct.google"}if(!d){var f=Po("googTaggyReferrer");d=!(!f.length||!f[0].length)}d&&(C["__TAGGY_INSTALLED"]=!0,xc("https://cct.google/taggy/agent.js"))}var g=function(v){var u="GTM",w="GTM";Ni&&(u="OGT",w="GTAG");var x=C["google.tagmanager.debugui2.queue"];x||(x= -[],C["google.tagmanager.debugui2.queue"]=x,xc("https://"+Gi.lf+"/debug/bootstrap?id="+Nf.ctid+"&src="+w+"&cond="+v+">m="+Mo()));var y={messageType:"CONTAINER_STARTING",data:{scriptSource:rc,containerProduct:u,debug:!1,id:Nf.ctid,targetRef:{ctid:Nf.ctid,isDestination:dk.qe},aliases:gk(),destinations:jk()}};y.data.resume=function(){a()};Gi.Dk&&(y.data.initialPublish=!0);x.push(y)},k={Xk:1,rj:2,Fj:3,zi:4,pj:5};k[k.Xk]="GTM_DEBUG_LEGACY_PARAM";k[k.rj]="GTM_DEBUG_PARAM";k[k.Fj]="REFERRER";k[k.zi]="COOKIE";k[k.pj]="EXTENSION_PARAM"; -var m=void 0,n=void 0,p=uj(C.location,"query",!1,void 0,"gtm_debug");qz(p)&&(m=k.rj);if(!m&&E.referrer){var q=Aj(E.referrer);wj(q,"host")==="tagassistant.google.com"&&(m=k.Fj)}if(!m){var r=Po("__TAG_ASSISTANT");r.length&&r[0].length&&(m=k.zi)}m||b();if(!m&&rz(n)){var t=!1;Cc(E,"TADebugSignal",function(){t||(t=!0,b(),c())},!1);C.setTimeout(function(){t||(t=!0,b(),c())},200)}else c()})(function(){try{var a;if(!(a=!Q(62))){var b;if(!(b=oK)){var c;a:{for(var d=ak(),e=h(fk()),f=e.next();!f.done;f=e.next())if(d.injectedFirstPartyContainers[f.value]){c= -!0;break a}c=!1}b=!c}a=b}if(a){sk();if(Q(77)){}ib[10]=!0;if(!Gl){Gl=!0;for(var g=Hl.length-1;g>=0;g--)Hl[g]();Hl=[]}mo();Ql();var k=mk();if(ak().canonical[k]){var m=Hi.zones;m&&m.unregisterChild(fk());Lw().removeExternalRestrictions(mk());}else{ -yu();$i.j="101533421~101686685~101823848~101925629";$i.K="";$i.Sa="ad_storage|analytics_storage|ad_user_data|ad_personalization"; -$i.Z="ad_storage|analytics_storage|ad_user_data";$i.P="4a90";$i.P="4al0";Ww();for(var n=data.resource||{},p=n.macros||[],q=0;q=0;f--)Jl[f]();Jl=[]}no();Sl();var g=ok();if(bk().canonical[g]){var k=Ji.zones;k&&k.unregisterChild(ik());Pw().removeExternalRestrictions(ok());}else{ +Cu();var m=cj.aa,n=Hi.An;m.j=new Set;if(n!=="")for(var p=l(n.split("~")),q=p.next();!q.done;q=p.next()){var r=Number(q.value);isNaN(r)||m.j.add(r)} +cj.H="";cj.Ua="ad_storage|analytics_storage|ad_user_data|ad_personalization";cj.P="ad_storage|analytics_storage|ad_user_data";cj.K="4a90";cj.K="4al0";$w();for(var u=data.resource||{},v=u.macros||[],t= +0;t1. Self overlap
1
-creates an empty circuit object with no gates +creates an empty circuit object with no gates
2
-add a hadamard gate to qubit 0 +add a hadamard gate to qubit 0
3
-add a \(CNOT\) with control in qubit 1 and target in 1 +add a \(CNOT\) with control in qubit 1 and target in 1
@@ -309,11 +309,11 @@

1. Self overlap

1
-get the real and the imaginary part of the state +get the real and the imaginary part of the state
2
-join the save and imaginary part of the overlap. self_overlap is not a complex number +join the save and imaginary part of the overlap. self_overlap is not a complex number
@@ -327,11 +327,11 @@

1. Self overlap

1
-compute the self overlap of the state +compute the self overlap of the state
2
-if the self overlap is not equal to \(1\), this should throw an exception +if the self overlap is not equal to \(1\), this should throw an exception
@@ -348,7 +348,7 @@

1. Self overlap

1
-printing the overlap shows all of its object attributes +printing the overlap shows all of its object attributes
@@ -371,11 +371,11 @@

2. Ov
1
-this circuit will perpare the two-qubit state |10> since we assume two input-qubits in state |0> and a \(X\) (NOT) is applied to the first one +this circuit will perpare the two-qubit state |10> since we assume two input-qubits in state |0> and a \(X\) (NOT) is applied to the first one
2
-also here we assume an input of |00> and send it through the circuit that generated the 4 bell-states +also here we assume an input of |00> and send it through the circuit that generated the 4 bell-states
@@ -391,19 +391,19 @@

2. Ov
1
-specify input states for writing them in the braket notation +specify input states for writing them in the braket notation
2
-joining real and imaginary part based on the states produced by the circuits U0 and U1 +joining real and imaginary part based on the states produced by the circuits U0 and U1
3
-simulates the tq.Objective object to obtain a numeric values +simulates the tq.Objective object to obtain a numeric values
4
-prints the overlap, this one should be equal to \(0\) +prints the overlap, this one should be equal to \(0\)
@@ -439,43 +439,43 @@

2. Ov
1
-declare a variable of for a parametrized angle +declare a variable of for a parametrized angle
2
-Bell state followed by a rotation around X-axis +Bell state followed by a rotation around X-axis
3
-fetch once again the real and imaginary components after writing the input states in braket form +fetch once again the real and imaginary components after writing the input states in braket form
4
-prepare real and imaginary part for overlap computation +prepare real and imaginary part for overlap computation
5
-translate to backend - compile the state with an arbitrary parametrized angle +translate to backend - compile the state with an arbitrary parametrized angle
6
-generates values from the intervall \([0,4.1]\) with steps of \(0.1\) for simulating multiple angles +generates values from the intervall \([0,4.1]\) with steps of \(0.1\) for simulating multiple angles
7
-associate angle with generated value from range above +associate angle with generated value from range above
8
-simulate the tq.Objective object ad get the computed overlap +simulate the tq.Objective object ad get the computed overlap
9
-append the achieved value to a list of overlaps, since we compute multiple overlaps for multiple angles +append the achieved value to a list of overlaps, since we compute multiple overlaps for multiple angles
10
-display the resulted numerical values of the overlaps as a graph +display the resulted numerical values of the overlaps as a graph
@@ -500,11 +500,11 @@

3. Exp
1
-as before define the first bell state with the circuit generating the bell-basis and an input of |00> +as before define the first bell state with the circuit generating the bell-basis and an input of |00>
2
-define an hamiltonian - this one is a sequence of Pauli-\(X\) matrices acting on the second and the first qubits respectivly and then a scale factor of \(-1\) +define an hamiltonian - this one is a sequence of Pauli-\(X\) matrices acting on the second and the first qubits respectivly and then a scale factor of \(-1\)
@@ -523,19 +523,19 @@

3. Exp
1
-applying the braket function on the bell-state and the hamiltonian, defining the hamiltonian as an operator - important +applying the braket function on the bell-state and the hamiltonian, defining the hamiltonian as an operator - important
2
-joining real and imaginary part for computation +joining real and imaginary part for computation
3
-simulate the expectation value +simulate the expectation value
4
-show the expectatino value, should be equal to \(1\) +show the expectatino value, should be equal to \(1\)
@@ -580,47 +580,47 @@

4. Tr
1
-create the bell state the same way as before +create the bell state the same way as before
2
-define a general angle for later computations as in the last example +define a general angle for later computations as in the last example
3
-add a rotation after the bell state +add a rotation after the bell state
4
-define the hamiltonian the same way as before +define the hamiltonian the same way as before
5
-apply braket function, specify the ket and the bra as the bell state and the bell state followed by the \(X\) rotation respectively and get the real and imaginary part +apply braket function, specify the ket and the bra as the bell state and the bell state followed by the \(X\) rotation respectively and get the real and imaginary part
6
-use the real and imaginary part for creating a complex number +use the real and imaginary part for creating a complex number
7
-compile this complex number by translating it to the backend +compile this complex number by translating it to the backend
8
-use the same interval as a range for angle generation as before and the same step size +use the same interval as a range for angle generation as before and the same step size
9
-set the of the angle we want to simulate +set the of the angle we want to simulate
10
-simulate the tq.Objective to get the computed value +simulate the tq.Objective to get the computed value
11
-store these values rounded by 3 digits after the comma into a list of transitions for later plot +store these values rounded by 3 digits after the comma into a list of transitions for later plot
@@ -674,43 +674,43 @@

4. Tr
1
-declare a variable of a general angle \(a\) +declare a variable of a general angle \(a\)
2
-declare a rotation around \(X\) with the angle \(a\pi\) +declare a rotation around \(X\) with the angle \(a\pi\)
3
-rotation around \(Y\) axis with a fixed angle of \(\pi\) +rotation around \(Y\) axis with a fixed angle of \(\pi\)
4
-hamiltonian with a paulii \(Z\) gate on the first qubit +hamiltonian with a paulii \(Z\) gate on the first qubit
5
-specify ket, bra and operator and fetch the imaginary and real part +specify ket, bra and operator and fetch the imaginary and real part
6
-transalte to backend and get the operator +transalte to backend and get the operator
7
-same range and step size as before +same range and step size as before
8
-set the angle values we want to simulate +set the angle values we want to simulate
9
-simulate the tq.Objective to get the computed value +simulate the tq.Objective to get the computed value
10
-store the computed values in a list for plotting +store the computed values in a list for plotting
@@ -786,19 +786,19 @@

Mak
1
-assume two qubits in \(|00>\) and flip the first qubit to get \(|10>\) +assume two qubits in \(|00>\) and flip the first qubit to get \(|10>\)
2
-prepare a bell state as before +prepare a bell state as before
3
-get the real and imaginary parts consistently with the explained notation +get the real and imaginary parts consistently with the explained notation
4
-optionally draw the resulted circuit, should look like the one below +optionally draw the resulted circuit, should look like the one below
@@ -825,23 +825,23 @@

Mak
1
-prepare state for \(U_0\) the same way as before +prepare state for \(U_0\) the same way as before
2
-prepare bell state +prepare bell state
3
-decalre hermitian operator consisting of a \(Z\) and two \(X\) paulis +decalre hermitian operator consisting of a \(Z\) and two \(X\) paulis
4
-use the braketfunction to fetch imaginary and real consistently with the explained notation as before +use the braketfunction to fetch imaginary and real consistently with the explained notation as before
5
-optional: draw the circuits, thuy should look like the two circuits below +optional: draw the circuits, thuy should look like the two circuits below
diff --git a/Tutorials/CircuitCompiler/CircuitCompiler.html b/Tutorials/CircuitCompiler/CircuitCompiler.html index 5a061ed..4a308c6 100644 --- a/Tutorials/CircuitCompiler/CircuitCompiler.html +++ b/Tutorials/CircuitCompiler/CircuitCompiler.html @@ -275,19 +275,19 @@

On this page

1
-create a circuit object +create a circuit object
2
-add a rotation Z gate with an angle of 90 deg. +add a rotation Z gate with an angle of 90 deg.
3
-add a Z gate with a power of 0.5 +add a Z gate with a power of 0.5
4
-print the gates with their names and generator values +print the gates with their names and generator values
@@ -327,19 +327,19 @@

On this page

1
-add a conrtolled X rotation of 90 deg. with. Control qubit is the first and target the second +add a conrtolled X rotation of 90 deg. with. Control qubit is the first and target the second
2
-collect generators parameters of each generator in circuit qc +collect generators parameters of each generator in circuit qc
3
-collect parameters of full generators in qc +collect parameters of full generators in qc
4
-output the parameters of each gate in circuit qc +output the parameters of each gate in circuit qc
@@ -367,11 +367,11 @@

Gates decomposition

1
-create a squared hadamard gate with a target qubit +create a squared hadamard gate with a target qubit
2
-compile the circuit qc, containing only one hadamard gate, - this will decompose the gate as shown above to rotations and paulis +compile the circuit qc, containing only one hadamard gate, - this will decompose the gate as shown above to rotations and paulis
@@ -401,15 +401,15 @@

Gates decomposition

1
-create a parametrized rotation \(Z\) gate with two controls and an angle of 180 deg. +create a parametrized rotation \(Z\) gate with two controls and an angle of 180 deg.
2
-compile the circuit - this will decompose it to a sequence of parametrized rotation \(Z\) gates and \(CNOT\) gates +compile the circuit - this will decompose it to a sequence of parametrized rotation \(Z\) gates and \(CNOT\) gates
3
-display the compiled circuit +display the compiled circuit
@@ -438,11 +438,11 @@

Gates decomposition

1
-create a gate based of a given Pauli-String of \(Z\) gates parameterized with an angle of 45 deg. +create a gate based of a given Pauli-String of \(Z\) gates parameterized with an angle of 45 deg.
2
-compile this gate - this will decompose it to a combination of \(CNOT\) gates and rotations +compile this gate - this will decompose it to a combination of \(CNOT\) gates and rotations
@@ -463,11 +463,11 @@

Gates decomposition

1
-create a controlled gate in qubit 1. with control qubit in 0. and a phase of 180 deg. +create a controlled gate in qubit 1. with control qubit in 0. and a phase of 180 deg.
2
-compile this gate - thus decompose it to rotations and \(CNOT\)s +compile this gate - thus decompose it to rotations and \(CNOT\)s
@@ -489,11 +489,11 @@

Gates decomposition

1
-create a Toffoli gate with controls in qubits 1 and 2 and target in qubit 2 +create a Toffoli gate with controls in qubits 1 and 2 and target in qubit 2
2
-compile this gate - since this gate is recognized by the backend it won’t get decomposed to rotations and \(CNOT\) gates +compile this gate - since this gate is recognized by the backend it won’t get decomposed to rotations and \(CNOT\) gates
@@ -510,11 +510,11 @@

Gates decomposition

1
-create the same Toffoli gate as before +create the same Toffoli gate as before
2
-compile the gate with a different backend “qiskit”. Since this backend doesn’t recognize this gate it will decompose it to smaller gates +compile the gate with a different backend “qiskit”. Since this backend doesn’t recognize this gate it will decompose it to smaller gates
diff --git a/Tutorials/KrylovTutorial/KrylovTutorial.html b/Tutorials/KrylovTutorial/KrylovTutorial.html index 4bc9158..49cb83c 100644 --- a/Tutorials/KrylovTutorial/KrylovTutorial.html +++ b/Tutorials/KrylovTutorial/KrylovTutorial.html @@ -268,19 +268,19 @@

Simple example

1
-Set the random seed for reproducibility +Set the random seed for reproducibility
2
-Number of Krylov states to generate +Number of Krylov states to generate
3
-Create random quantum circuits, in this way it is very unlikely they will be orthogonal +Create random quantum circuits, in this way it is very unlikely they will be orthogonal
4
-Create the wavefunctions from the circuits +Create the wavefunctions from the circuits
@@ -297,19 +297,19 @@

Simple example

1
-Generate a list of all posible couples of Krylov states +Generate a list of all posible couples of Krylov states
2
-Create a Hamiltonian from the obtained wavefunctions +Create a Hamiltonian from the obtained wavefunctions
3
-Initialize an empty QubitHamiltonian object +Initialize an empty QubitHamiltonian object
4
-For each couple of Krylov states, compute the braket and substract the term from the Hamiltonian +For each couple of Krylov states, compute the braket and substract the term from the Hamiltonian
@@ -324,15 +324,15 @@

Simple example

1
-Applying the Krylov method +Applying the Krylov method
2
-Extract the ground state energy +Extract the ground state energy
3
-Extract the coefficients +Extract the coefficients
@@ -344,7 +344,7 @@

Simple example

1
-Perform exact diagonalization of the Hamiltonian +Perform exact diagonalization of the Hamiltonian
@@ -369,15 +369,15 @@

Simple example

1
-Initialize the ground state +Initialize the ground state
2
-Construct the ground state wavefunction by adding the scaled Krylov states +Construct the ground state wavefunction by adding the scaled Krylov states
3
-Print the ground state +Print the ground state
@@ -393,7 +393,7 @@

Simple example

1
-Create a QubitWaveFunction object from the array representing the first eigenvector +Create a QubitWaveFunction object from the array representing the first eigenvector
@@ -410,7 +410,7 @@

Simple example

1
-Compute the fidelity between the two states +Compute the fidelity between the two states
diff --git a/Tutorials/OpenQASMConversions/OpenQASMConversions.html b/Tutorials/OpenQASMConversions/OpenQASMConversions.html index e55f34d..848597c 100644 --- a/Tutorials/OpenQASMConversions/OpenQASMConversions.html +++ b/Tutorials/OpenQASMConversions/OpenQASMConversions.html @@ -304,11 +304,11 @@

Export to OpenQASM

1
-A circuit is being created +A circuit is being created
2
-The corresponding qpic-file to this circuit is being created. For generating the corresponding png one has to write “qpic -f png C1_new.qpic” into the command line +The corresponding qpic-file to this circuit is being created. For generating the corresponding png one has to write “qpic -f png C1_new.qpic” into the command line
@@ -325,7 +325,7 @@

Export to OpenQASM

1
-Shows the circuit of openqasmcode +Shows the circuit of openqasmcode
@@ -369,7 +369,7 @@

Export to OpenQASM

1
-Shows the circuit of openqasmcode +Shows the circuit of openqasmcode
@@ -424,7 +424,7 @@

Import from OpenQASM

1
-In the case of having the OpenQASM code in a file, it is possible to load that file to generate the Tequila circuit from there, for this the import_open_qasm_from_file function is used +In the case of having the OpenQASM code in a file, it is possible to load that file to generate the Tequila circuit from there, for this the import_open_qasm_from_file function is used
@@ -501,7 +501,7 @@

Import from OpenQASM

1
-Shows the circuit of openqasmcode_no_y +Shows the circuit of openqasmcode_no_y
@@ -529,7 +529,7 @@

Import from OpenQASM

1
-Shows the circuit of openqasmcode +Shows the circuit of openqasmcode
diff --git a/Tutorials/QTensor/QTensor.html b/Tutorials/QTensor/QTensor.html index d99d39c..201ea88 100644 --- a/Tutorials/QTensor/QTensor.html +++ b/Tutorials/QTensor/QTensor.html @@ -499,11 +499,11 @@

Apply
1
-Dot product of two arrays: +Dot product of two arrays:
2
-Some operations on the results +Some operations on the results
diff --git a/Tutorials/optimizer/Optimizers.html b/Tutorials/optimizer/Optimizers.html index 51299b0..c4b9dfe 100644 --- a/Tutorials/optimizer/Optimizers.html +++ b/Tutorials/optimizer/Optimizers.html @@ -279,7 +279,7 @@

Overview

1
-Get a list of all available optimizers +Get a list of all available optimizers
@@ -343,19 +343,19 @@

Overview

1
-Optimizing the circuit in terms of pi makes the result of the optimization easier to interpret +Optimizing the circuit in terms of pi makes the result of the optimization easier to interpret
2
-Create a 2-qubit quantum circuit for the Objective \(O_1\) +Create a 2-qubit quantum circuit for the Objective \(O_1\)
3
-Define the Hamiltonian for \(O_1\) to optimize over +Define the Hamiltonian for \(O_1\) to optimize over
4
-Define the expectation value of the Hamiltonian after applying the quantum circuit +Define the expectation value of the Hamiltonian after applying the quantum circuit
@@ -382,19 +382,19 @@

Overview

1
-This time, we don’t optimize the circuit in terms of pi +This time, we don’t optimize the circuit in terms of pi
2
-Create a 3-qubit quantum circuit for the Objective \(O_2\) +Create a 3-qubit quantum circuit for the Objective \(O_2\)
3
-Define the Hamiltonian for \(O_2\) to optimize over +Define the Hamiltonian for \(O_2\) to optimize over
4
-Define the expectation value of the Hamiltonian after applying the quantum circuit +Define the expectation value of the Hamiltonian after applying the quantum circuit
@@ -418,7 +418,7 @@

The GD Optimizer

1
-Get a list of all available optimization methods for the GD optimizer +Get a list of all available optimization methods for the GD optimizer
@@ -454,19 +454,19 @@

The GD Optimizer

1
-Initialize all four variables to \(\frac{1}{4}\pi\) +Initialize all four variables to \(\frac{1}{4}\pi\)
2
-Set the learning rate to 0.1 +Set the learning rate to 0.1
3
-Optimize the objective \(O_1\) using the Adam method with learning rate 0.1 and maximal iterations 80 +Optimize the objective \(O_1\) using the Adam method with learning rate 0.1 and maximal iterations 80
4
-Set silent=True to suppress output +Set silent=True to suppress output
@@ -481,11 +481,11 @@

The GD Optimizer

1
-Plot energy from Adam optimization +Plot energy from Adam optimization
2
-Plot angles from Adam optimization +Plot angles from Adam optimization
@@ -527,23 +527,23 @@

The GD Optimizer

1
-Initialize all four variables to \(\frac{1}{4}\pi\) +Initialize all four variables to \(\frac{1}{4}\pi\)
2
-Set the learning rate to 0.01 +Set the learning rate to 0.01
3
-Optimize the objective \(O_1\) using the RMSprop method with learning rate 0.01 and maximal iterations 80 +Optimize the objective \(O_1\) using the RMSprop method with learning rate 0.01 and maximal iterations 80
4
-Plot energy from RMSprop optimization +Plot energy from RMSprop optimization
5
-Plot angles from RMSprop optimization +Plot angles from RMSprop optimization
@@ -584,23 +584,23 @@

The GD Optimizer

1
-Initialize all four variables to \(\frac{1}{4}\pi\) +Initialize all four variables to \(\frac{1}{4}\pi\)
2
-Set the learning rate to 0.1 +Set the learning rate to 0.1
3
-Optimize the objective \(O_1\) using the Momentum method with learning rate 0.1 and maximal iterations 80 +Optimize the objective \(O_1\) using the Momentum method with learning rate 0.1 and maximal iterations 80
4
-Plot energy from Momentum optimization +Plot energy from Momentum optimization
5
-Plot angles from Momentum optimization +Plot angles from Momentum optimization
@@ -640,15 +640,15 @@

The GD Optimizer

1
-Initialize variables: \(a = 0.18\), \(b = 0.8\), \(c = -0.1\), \(d = -0.4\) +Initialize variables: \(a = 0.18\), \(b = 0.8\), \(c = -0.1\), \(d = -0.4\)
2
-Set the learning rate to 0.1 +Set the learning rate to 0.1
3
-Optimize the objective \(O_1\) using the standard gradient descent method with learning rate 0.1, maximal iterations 80 and a tolerance of 1e-10 +Optimize the objective \(O_1\) using the standard gradient descent method with learning rate 0.1, maximal iterations 80 and a tolerance of 1e-10
@@ -668,11 +668,11 @@

The GD Optimizer

1
-Optimize the objective \(O_1\) using the standard gradient descent method with learning rate 0.1, maximal iterations 80, a tolerance of 1e-10 and DIIS acceleration +Optimize the objective \(O_1\) using the standard gradient descent method with learning rate 0.1, maximal iterations 80, a tolerance of 1e-10 and DIIS acceleration
2
-Set the DIIS acceleration with a tolerance of 1e-10 +Set the DIIS acceleration with a tolerance of 1e-10
@@ -695,27 +695,27 @@

The GD Optimizer

1
-Import the numpy library +Import the numpy library
2
-Extract the last energy values from the DISS optimization +Extract the last energy values from the DISS optimization
3
-Plot the error on energy for every step in the optimization without DIIS acceleration +Plot the error on energy for every step in the optimization without DIIS acceleration
4
-Plot the error on energy for every step in the optimization with DIIS acceleration +Plot the error on energy for every step in the optimization with DIIS acceleration
5
-Label the y-axis of the plot as ‘Error on Energy’ +Label the y-axis of the plot as ‘Error on Energy’
6
-Add a legend to the plot to differentiate between the results with and without DIIS +Add a legend to the plot to differentiate between the results with and without DIIS
@@ -749,23 +749,23 @@

The GD Optimizer

1
-keyword ‘stop_count’ stops optimization if no improvement occurs after 50 epochs +keyword ‘stop_count’ stops optimization if no improvement occurs after 50 epochs
2
-Initialize the four variables to random values between -2 and 2 +Initialize the four variables to random values between -2 and 2
3
-Set the learning rate to 0.01 +Set the learning rate to 0.01
4
-Optimize the objective \(O_2\) using the standard gradient descent method with learning rate 0.01, maximal iterations 200 and the Quantum Natural Gradient (QNG) +Optimize the objective \(O_2\) using the standard gradient descent method with learning rate 0.01, maximal iterations 200 and the Quantum Natural Gradient (QNG)
5
-Set the gradient to the Quantum Natural Gradient (QNG) +Set the gradient to the Quantum Natural Gradient (QNG)
@@ -780,11 +780,11 @@

The GD Optimizer

1
-Plot the energy from the optimization with the Quantum Natural Gradient +Plot the energy from the optimization with the Quantum Natural Gradient
2
-Plot the angles from the optimization with the Quantum Natural Gradient +Plot the angles from the optimization with the Quantum Natural Gradient
@@ -826,19 +826,19 @@

The GD Optimizer

1
-Set the learning rate to 0.01 +Set the learning rate to 0.01
2
-Optimize the objective \(O_2\) using the standard gradient descent method with learning rate 0.01 and maximal iterations 200 +Optimize the objective \(O_2\) using the standard gradient descent method with learning rate 0.01 and maximal iterations 200
3
-Plot the energy from the optimization without the Quantum Natural Gradient +Plot the energy from the optimization without the Quantum Natural Gradient
4
-Plot the angles from the optimization without the Quantum Natural Gradient +Plot the angles from the optimization without the Quantum Natural Gradient
@@ -869,7 +869,7 @@

The SciPy Optimizer
1
-Get a list of all available optimization methods for the SciPy optimizer +Get a list of all available optimization methods for the SciPy optimizer
@@ -915,23 +915,23 @@

The SciPy Optimizer
1
-Initialize all four variables to fixed values of \(0.25\) +Initialize all four variables to fixed values of \(0.25\)
2
-Optimize the objective \(O_1\) using the COBYLA method with a tolerance of \(1.e-3\) +Optimize the objective \(O_1\) using the COBYLA method with a tolerance of \(1.e-3\)
3
-Set the gradient tolerance to \(1.e-3\) +Set the gradient tolerance to \(1.e-3\)
4
-Plot the energy from the optimization with the COBYLA method +Plot the energy from the optimization with the COBYLA method
5
-Plot the angles from the optimization with the COBYLA method +Plot the angles from the optimization with the COBYLA method
@@ -967,19 +967,19 @@

The SciPy Optimizer
1
-Optimize the objective \(O_1\) using the L-BFGS-B method with a tolerance of \(1.e-3\) +Optimize the objective \(O_1\) using the L-BFGS-B method with a tolerance of \(1.e-3\)
2
-Set the gradient tolerance to \(1.e-3\) +Set the gradient tolerance to \(1.e-3\)
3
-Plot the energy from the optimization with the L-BFGS-B method +Plot the energy from the optimization with the L-BFGS-B method
4
-Plot the angles from the optimization with the L-BFGS-B method +Plot the angles from the optimization with the L-BFGS-B method
@@ -1015,19 +1015,19 @@

The SciPy Optimizer
1
-Optimize the objective \(O_1\) using the NEWTON-CG method with a tolerance of \(1.e-3\) +Optimize the objective \(O_1\) using the NEWTON-CG method with a tolerance of \(1.e-3\)
2
-Set the gradient tolerance to \(1.e-3\) +Set the gradient tolerance to \(1.e-3\)
3
-Plot the energy from the optimization with the NEWTON-CG method +Plot the energy from the optimization with the NEWTON-CG method
4
-Plot the angles from the optimization with the NEWTON-CG method +Plot the angles from the optimization with the NEWTON-CG method
@@ -1068,23 +1068,23 @@

The SciPy Optimizer
1
-Optimize the objective \(O_1\) using the L-BFGS-B method with a tolerance of \(1.e-3\), numerical gradients, and a step size of \(1.e-4\) +Optimize the objective \(O_1\) using the L-BFGS-B method with a tolerance of \(1.e-3\), numerical gradients, and a step size of \(1.e-4\)
2
-Set the gradient to 2-point to use numerical gradients +Set the gradient to 2-point to use numerical gradients
3
-Set the step size to \(1.e-4\) +Set the step size to \(1.e-4\)
4
-Plot the energy from the optimization with the L-BFGS-B method and numerical gradients +Plot the energy from the optimization with the L-BFGS-B method and numerical gradients
5
-Plot the angles from the optimization with the L-BFGS-B method and numerical gradients +Plot the angles from the optimization with the L-BFGS-B method and numerical gradients
@@ -1128,27 +1128,27 @@

The SciPy Optimizer
1
-Initialize the four variables to random values between -2 and 2 +Initialize the four variables to random values between -2 and 2
2
-Set the learning rate to 0.01 +Set the learning rate to 0.01
3
-Optimize the objective \(O_2\) using the BFGS method with learning rate 0.01, maximal iterations 200 and the Quantum Natural Gradient (QNG) +Optimize the objective \(O_2\) using the BFGS method with learning rate 0.01, maximal iterations 200 and the Quantum Natural Gradient (QNG)
4
-Set the gradient to the Quantum Natural Gradient (QNG) +Set the gradient to the Quantum Natural Gradient (QNG)
5
-Plot the energy from the optimization with the BFGS method and the Quantum Natural Gradient +Plot the energy from the optimization with the BFGS method and the Quantum Natural Gradient
6
-Plot the angles from the optimization with the BFGS method and the Quantum Natural Gradient +Plot the angles from the optimization with the BFGS method and the Quantum Natural Gradient
@@ -1188,19 +1188,19 @@

The SciPy Optimizer
1
-Optimize the objective \(O_2\) using the BFGS method with learning rate 0.01 and maximal iterations 200 +Optimize the objective \(O_2\) using the BFGS method with learning rate 0.01 and maximal iterations 200
2
-Set the gradient to None +Set the gradient to None
3
-Plot the energy from the optimization with the BFGS method +Plot the energy from the optimization with the BFGS method
4
-Plot the angles from the optimization with the BFGS method +Plot the angles from the optimization with the BFGS method
@@ -1241,15 +1241,15 @@

Numerical and Customized Gradients

1
-Set the learning rate to 0.01 +Set the learning rate to 0.01
2
-Optimize the objective \(O_2\) using the standard gradient descent method with learning rate 0.01, maximal iterations 200 and numerical gradients with a step size of \(1.e-4\) +Optimize the objective \(O_2\) using the standard gradient descent method with learning rate 0.01, maximal iterations 200 and numerical gradients with a step size of \(1.e-4\)
3
-Set the gradient to a dictionary with the method 2-point for numerical gradients and a step size of $1.e-4 +Set the gradient to a dictionary with the method 2-point for numerical gradients and a step size of $1.e-4
@@ -1260,7 +1260,7 @@

Numerical and Customized Gradients

1
-Plot the energy from the ‘standard gradient descent’ optimization with numerical gradients +Plot the energy from the ‘standard gradient descent’ optimization with numerical gradients
@@ -1313,35 +1313,35 @@

Numerical and Customized Gradients

1
-Import the copy library to deep copy objects +Import the copy library to deep copy objects
2
-Create a deep copy of the variable +Create a deep copy of the variable
3
-Shift the variable to the right by half of the step size +Shift the variable to the right by half of the step size
4
-Create another deep copy of the variable +Create another deep copy of the variable
5
-Shift the variable to the left by half of the step size +Shift the variable to the left by half of the step size
6
-Calculate the difference gradient using the symmetric difference quotient. +Calculate the difference gradient using the symmetric difference quotient.
7
-Optimize the objective \(O_2\) using the standard gradient descent method with learning rate 0.01, maximal iterations 200 and an objective gradient with a step size of \(1.e-4\) +Optimize the objective \(O_2\) using the standard gradient descent method with learning rate 0.01, maximal iterations 200 and an objective gradient with a step size of \(1.e-4\)
8
-Set the gradient to a dictionary with the method my_finite_difference_stencil and a step size of \(1.e-4\) +Set the gradient to a dictionary with the method my_finite_difference_stencil and a step size of \(1.e-4\)
diff --git a/Tutorials/tq-circuits/index.html b/Tutorials/tq-circuits/index.html index 87c4af2..61e9eb3 100644 --- a/Tutorials/tq-circuits/index.html +++ b/Tutorials/tq-circuits/index.html @@ -271,7 +271,7 @@

Initialize Tequila Circuits

wfn = tq.simulate(U)
 print(wfn)
-
+0.8776|00> +0.4794|11> 
+
(0.8775825618903728+0j) |00> (0.479425538604203+0j) |11> 

In the code block above, we did not specify the simulator to be used, tequila determines this automatically. You can however specify the similator via the backend keyword. If you are not sure which simulators are installed on your system, use tq.show_available_simulators()

@@ -307,7 +307,7 @@

Parametrization

wfn = tq.simulate(U, variables={"a":1.0}) print(wfn)
-
+0.8776|00> +0.4794|11> 
+
(0.8775825618903728+0j) |00> (0.479425538604203+0j) |11> 

note that we need to specify the values of all parameters when we are simulating the circuit. The same example with the tq.Variable type

@@ -317,7 +317,7 @@

Parametrization

wfn = tq.simulate(U, variables={"a":1.0}) print(wfn)
-
+0.8776|00> +0.4794|11> 
+
(0.8775825618903728+0j) |00> (0.479425538604203+0j) |11> 

note here, that the variables dictionary does not need to be initialized with the variable type, the plain names (as hashable types like strings) are enough - in the background this will all be converted to tq.Variable.

@@ -342,7 +342,7 @@

Parametrization

wfn = tq.simulate(U, variables={"a":1.0}) print(wfn)
-
+0.8776|00> +0.4794|11> 
+
(0.8775825618903728+0j) |00> (0.479425538604203+0j) |11> 
diff --git a/docs/sphinx/_modules/collections.html b/docs/sphinx/_modules/collections.html new file mode 100644 index 0000000..c269a35 --- /dev/null +++ b/docs/sphinx/_modules/collections.html @@ -0,0 +1,1693 @@ + + + + + + + + collections — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for collections

+'''This module implements specialized container datatypes providing
+alternatives to Python's general purpose built-in containers, dict,
+list, set, and tuple.
+
+* namedtuple   factory function for creating tuple subclasses with named fields
+* deque        list-like container with fast appends and pops on either end
+* ChainMap     dict-like class for creating a single view of multiple mappings
+* Counter      dict subclass for counting hashable objects
+* OrderedDict  dict subclass that remembers the order entries were added
+* defaultdict  dict subclass that calls a factory function to supply missing values
+* UserDict     wrapper around dictionary objects for easier dict subclassing
+* UserList     wrapper around list objects for easier list subclassing
+* UserString   wrapper around string objects for easier string subclassing
+
+'''
+
+__all__ = [
+    'ChainMap',
+    'Counter',
+    'OrderedDict',
+    'UserDict',
+    'UserList',
+    'UserString',
+    'defaultdict',
+    'deque',
+    'namedtuple',
+]
+
+import _collections_abc
+import sys as _sys
+
+from itertools import chain as _chain
+from itertools import repeat as _repeat
+from itertools import starmap as _starmap
+from keyword import iskeyword as _iskeyword
+from operator import eq as _eq
+from operator import itemgetter as _itemgetter
+from reprlib import recursive_repr as _recursive_repr
+from _weakref import proxy as _proxy
+
+try:
+    from _collections import deque
+except ImportError:
+    pass
+else:
+    _collections_abc.MutableSequence.register(deque)
+
+try:
+    from _collections import _deque_iterator
+except ImportError:
+    pass
+
+try:
+    from _collections import defaultdict
+except ImportError:
+    pass
+
+
+################################################################################
+### OrderedDict
+################################################################################
+
+class _OrderedDictKeysView(_collections_abc.KeysView):
+
+    def __reversed__(self):
+        yield from reversed(self._mapping)
+
+class _OrderedDictItemsView(_collections_abc.ItemsView):
+
+    def __reversed__(self):
+        for key in reversed(self._mapping):
+            yield (key, self._mapping[key])
+
+class _OrderedDictValuesView(_collections_abc.ValuesView):
+
+    def __reversed__(self):
+        for key in reversed(self._mapping):
+            yield self._mapping[key]
+
+class _Link(object):
+    __slots__ = 'prev', 'next', 'key', '__weakref__'
+
+class OrderedDict(dict):
+    'Dictionary that remembers insertion order'
+    # An inherited dict maps keys to values.
+    # The inherited dict provides __getitem__, __len__, __contains__, and get.
+    # The remaining methods are order-aware.
+    # Big-O running times for all methods are the same as regular dictionaries.
+
+    # The internal self.__map dict maps keys to links in a doubly linked list.
+    # The circular doubly linked list starts and ends with a sentinel element.
+    # The sentinel element never gets deleted (this simplifies the algorithm).
+    # The sentinel is in self.__hardroot with a weakref proxy in self.__root.
+    # The prev links are weakref proxies (to prevent circular references).
+    # Individual links are kept alive by the hard reference in self.__map.
+    # Those hard references disappear when a key is deleted from an OrderedDict.
+
+    def __new__(cls, /, *args, **kwds):
+        "Create the ordered dict object and set up the underlying structures."
+        self = dict.__new__(cls)
+        self.__hardroot = _Link()
+        self.__root = root = _proxy(self.__hardroot)
+        root.prev = root.next = root
+        self.__map = {}
+        return self
+
+    def __init__(self, other=(), /, **kwds):
+        '''Initialize an ordered dictionary.  The signature is the same as
+        regular dictionaries.  Keyword argument order is preserved.
+        '''
+        self.__update(other, **kwds)
+
+    def __setitem__(self, key, value,
+                    dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
+        'od.__setitem__(i, y) <==> od[i]=y'
+        # Setting a new item creates a new link at the end of the linked list,
+        # and the inherited dictionary is updated with the new key/value pair.
+        if key not in self:
+            self.__map[key] = link = Link()
+            root = self.__root
+            last = root.prev
+            link.prev, link.next, link.key = last, root, key
+            last.next = link
+            root.prev = proxy(link)
+        dict_setitem(self, key, value)
+
+    def __delitem__(self, key, dict_delitem=dict.__delitem__):
+        'od.__delitem__(y) <==> del od[y]'
+        # Deleting an existing item uses self.__map to find the link which gets
+        # removed by updating the links in the predecessor and successor nodes.
+        dict_delitem(self, key)
+        link = self.__map.pop(key)
+        link_prev = link.prev
+        link_next = link.next
+        link_prev.next = link_next
+        link_next.prev = link_prev
+        link.prev = None
+        link.next = None
+
+    def __iter__(self):
+        'od.__iter__() <==> iter(od)'
+        # Traverse the linked list in order.
+        root = self.__root
+        curr = root.next
+        while curr is not root:
+            yield curr.key
+            curr = curr.next
+
+    def __reversed__(self):
+        'od.__reversed__() <==> reversed(od)'
+        # Traverse the linked list in reverse order.
+        root = self.__root
+        curr = root.prev
+        while curr is not root:
+            yield curr.key
+            curr = curr.prev
+
+    def clear(self):
+        'od.clear() -> None.  Remove all items from od.'
+        root = self.__root
+        root.prev = root.next = root
+        self.__map.clear()
+        dict.clear(self)
+
+    def popitem(self, last=True):
+        '''Remove and return a (key, value) pair from the dictionary.
+
+        Pairs are returned in LIFO order if last is true or FIFO order if false.
+        '''
+        if not self:
+            raise KeyError('dictionary is empty')
+        root = self.__root
+        if last:
+            link = root.prev
+            link_prev = link.prev
+            link_prev.next = root
+            root.prev = link_prev
+        else:
+            link = root.next
+            link_next = link.next
+            root.next = link_next
+            link_next.prev = root
+        key = link.key
+        del self.__map[key]
+        value = dict.pop(self, key)
+        return key, value
+
+    def move_to_end(self, key, last=True):
+        '''Move an existing element to the end (or beginning if last is false).
+
+        Raise KeyError if the element does not exist.
+        '''
+        link = self.__map[key]
+        link_prev = link.prev
+        link_next = link.next
+        soft_link = link_next.prev
+        link_prev.next = link_next
+        link_next.prev = link_prev
+        root = self.__root
+        if last:
+            last = root.prev
+            link.prev = last
+            link.next = root
+            root.prev = soft_link
+            last.next = link
+        else:
+            first = root.next
+            link.prev = root
+            link.next = first
+            first.prev = soft_link
+            root.next = link
+
+    def __sizeof__(self):
+        sizeof = _sys.getsizeof
+        n = len(self) + 1                       # number of links including root
+        size = sizeof(self.__dict__)            # instance dictionary
+        size += sizeof(self.__map) * 2          # internal dict and inherited dict
+        size += sizeof(self.__hardroot) * n     # link objects
+        size += sizeof(self.__root) * n         # proxy objects
+        return size
+
+    update = __update = _collections_abc.MutableMapping.update
+
+    def keys(self):
+        "D.keys() -> a set-like object providing a view on D's keys"
+        return _OrderedDictKeysView(self)
+
+    def items(self):
+        "D.items() -> a set-like object providing a view on D's items"
+        return _OrderedDictItemsView(self)
+
+    def values(self):
+        "D.values() -> an object providing a view on D's values"
+        return _OrderedDictValuesView(self)
+
+    __ne__ = _collections_abc.MutableMapping.__ne__
+
+    __marker = object()
+
+    def pop(self, key, default=__marker):
+        '''od.pop(k[,d]) -> v, remove specified key and return the corresponding
+        value.  If key is not found, d is returned if given, otherwise KeyError
+        is raised.
+
+        '''
+        marker = self.__marker
+        result = dict.pop(self, key, marker)
+        if result is not marker:
+            # The same as in __delitem__().
+            link = self.__map.pop(key)
+            link_prev = link.prev
+            link_next = link.next
+            link_prev.next = link_next
+            link_next.prev = link_prev
+            link.prev = None
+            link.next = None
+            return result
+        if default is marker:
+            raise KeyError(key)
+        return default
+
+    def setdefault(self, key, default=None):
+        '''Insert key with a value of default if key is not in the dictionary.
+
+        Return the value for key if key is in the dictionary, else default.
+        '''
+        if key in self:
+            return self[key]
+        self[key] = default
+        return default
+
+    @_recursive_repr()
+    def __repr__(self):
+        'od.__repr__() <==> repr(od)'
+        if not self:
+            return '%s()' % (self.__class__.__name__,)
+        return '%s(%r)' % (self.__class__.__name__, dict(self.items()))
+
+    def __reduce__(self):
+        'Return state information for pickling'
+        state = self.__getstate__()
+        if state:
+            if isinstance(state, tuple):
+                state, slots = state
+            else:
+                slots = {}
+            state = state.copy()
+            slots = slots.copy()
+            for k in vars(OrderedDict()):
+                state.pop(k, None)
+                slots.pop(k, None)
+            if slots:
+                state = state, slots
+            else:
+                state = state or None
+        return self.__class__, (), state, None, iter(self.items())
+
+    def copy(self):
+        'od.copy() -> a shallow copy of od'
+        return self.__class__(self)
+
+    @classmethod
+    def fromkeys(cls, iterable, value=None):
+        '''Create a new ordered dictionary with keys from iterable and values set to value.
+        '''
+        self = cls()
+        for key in iterable:
+            self[key] = value
+        return self
+
+    def __eq__(self, other):
+        '''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
+        while comparison to a regular mapping is order-insensitive.
+
+        '''
+        if isinstance(other, OrderedDict):
+            return dict.__eq__(self, other) and all(map(_eq, self, other))
+        return dict.__eq__(self, other)
+
+    def __ior__(self, other):
+        self.update(other)
+        return self
+
+    def __or__(self, other):
+        if not isinstance(other, dict):
+            return NotImplemented
+        new = self.__class__(self)
+        new.update(other)
+        return new
+
+    def __ror__(self, other):
+        if not isinstance(other, dict):
+            return NotImplemented
+        new = self.__class__(other)
+        new.update(self)
+        return new
+
+
+try:
+    from _collections import OrderedDict
+except ImportError:
+    # Leave the pure Python version in place.
+    pass
+
+
+################################################################################
+### namedtuple
+################################################################################
+
+try:
+    from _collections import _tuplegetter
+except ImportError:
+    _tuplegetter = lambda index, doc: property(_itemgetter(index), doc=doc)
+
+def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None):
+    """Returns a new subclass of tuple with named fields.
+
+    >>> Point = namedtuple('Point', ['x', 'y'])
+    >>> Point.__doc__                   # docstring for the new class
+    'Point(x, y)'
+    >>> p = Point(11, y=22)             # instantiate with positional args or keywords
+    >>> p[0] + p[1]                     # indexable like a plain tuple
+    33
+    >>> x, y = p                        # unpack like a regular tuple
+    >>> x, y
+    (11, 22)
+    >>> p.x + p.y                       # fields also accessible by name
+    33
+    >>> d = p._asdict()                 # convert to a dictionary
+    >>> d['x']
+    11
+    >>> Point(**d)                      # convert from a dictionary
+    Point(x=11, y=22)
+    >>> p._replace(x=100)               # _replace() is like str.replace() but targets named fields
+    Point(x=100, y=22)
+
+    """
+
+    # Validate the field names.  At the user's option, either generate an error
+    # message or automatically replace the field name with a valid name.
+    if isinstance(field_names, str):
+        field_names = field_names.replace(',', ' ').split()
+    field_names = list(map(str, field_names))
+    typename = _sys.intern(str(typename))
+
+    if rename:
+        seen = set()
+        for index, name in enumerate(field_names):
+            if (not name.isidentifier()
+                or _iskeyword(name)
+                or name.startswith('_')
+                or name in seen):
+                field_names[index] = f'_{index}'
+            seen.add(name)
+
+    for name in [typename] + field_names:
+        if type(name) is not str:
+            raise TypeError('Type names and field names must be strings')
+        if not name.isidentifier():
+            raise ValueError('Type names and field names must be valid '
+                             f'identifiers: {name!r}')
+        if _iskeyword(name):
+            raise ValueError('Type names and field names cannot be a '
+                             f'keyword: {name!r}')
+
+    seen = set()
+    for name in field_names:
+        if name.startswith('_') and not rename:
+            raise ValueError('Field names cannot start with an underscore: '
+                             f'{name!r}')
+        if name in seen:
+            raise ValueError(f'Encountered duplicate field name: {name!r}')
+        seen.add(name)
+
+    field_defaults = {}
+    if defaults is not None:
+        defaults = tuple(defaults)
+        if len(defaults) > len(field_names):
+            raise TypeError('Got more default values than field names')
+        field_defaults = dict(reversed(list(zip(reversed(field_names),
+                                                reversed(defaults)))))
+
+    # Variables used in the methods and docstrings
+    field_names = tuple(map(_sys.intern, field_names))
+    num_fields = len(field_names)
+    arg_list = ', '.join(field_names)
+    if num_fields == 1:
+        arg_list += ','
+    repr_fmt = '(' + ', '.join(f'{name}=%r' for name in field_names) + ')'
+    tuple_new = tuple.__new__
+    _dict, _tuple, _len, _map, _zip = dict, tuple, len, map, zip
+
+    # Create all the named tuple methods to be added to the class namespace
+
+    namespace = {
+        '_tuple_new': tuple_new,
+        '__builtins__': {},
+        '__name__': f'namedtuple_{typename}',
+    }
+    code = f'lambda _cls, {arg_list}: _tuple_new(_cls, ({arg_list}))'
+    __new__ = eval(code, namespace)
+    __new__.__name__ = '__new__'
+    __new__.__doc__ = f'Create new instance of {typename}({arg_list})'
+    if defaults is not None:
+        __new__.__defaults__ = defaults
+
+    @classmethod
+    def _make(cls, iterable):
+        result = tuple_new(cls, iterable)
+        if _len(result) != num_fields:
+            raise TypeError(f'Expected {num_fields} arguments, got {len(result)}')
+        return result
+
+    _make.__func__.__doc__ = (f'Make a new {typename} object from a sequence '
+                              'or iterable')
+
+    def _replace(self, /, **kwds):
+        result = self._make(_map(kwds.pop, field_names, self))
+        if kwds:
+            raise ValueError(f'Got unexpected field names: {list(kwds)!r}')
+        return result
+
+    _replace.__doc__ = (f'Return a new {typename} object replacing specified '
+                        'fields with new values')
+
+    def __repr__(self):
+        'Return a nicely formatted representation string'
+        return self.__class__.__name__ + repr_fmt % self
+
+    def _asdict(self):
+        'Return a new dict which maps field names to their values.'
+        return _dict(_zip(self._fields, self))
+
+    def __getnewargs__(self):
+        'Return self as a plain tuple.  Used by copy and pickle.'
+        return _tuple(self)
+
+    # Modify function metadata to help with introspection and debugging
+    for method in (
+        __new__,
+        _make.__func__,
+        _replace,
+        __repr__,
+        _asdict,
+        __getnewargs__,
+    ):
+        method.__qualname__ = f'{typename}.{method.__name__}'
+
+    # Build-up the class namespace dictionary
+    # and use type() to build the result class
+    class_namespace = {
+        '__doc__': f'{typename}({arg_list})',
+        '__slots__': (),
+        '_fields': field_names,
+        '_field_defaults': field_defaults,
+        '__new__': __new__,
+        '_make': _make,
+        '_replace': _replace,
+        '__repr__': __repr__,
+        '_asdict': _asdict,
+        '__getnewargs__': __getnewargs__,
+        '__match_args__': field_names,
+    }
+    for index, name in enumerate(field_names):
+        doc = _sys.intern(f'Alias for field number {index}')
+        class_namespace[name] = _tuplegetter(index, doc)
+
+    result = type(typename, (tuple,), class_namespace)
+
+    # For pickling to work, the __module__ variable needs to be set to the frame
+    # where the named tuple is created.  Bypass this step in environments where
+    # sys._getframe is not defined (Jython for example) or sys._getframe is not
+    # defined for arguments greater than 0 (IronPython), or where the user has
+    # specified a particular module.
+    if module is None:
+        try:
+            module = _sys._getframemodulename(1) or '__main__'
+        except AttributeError:
+            try:
+                module = _sys._getframe(1).f_globals.get('__name__', '__main__')
+            except (AttributeError, ValueError):
+                pass
+    if module is not None:
+        result.__module__ = module
+
+    return result
+
+
+########################################################################
+###  Counter
+########################################################################
+
+def _count_elements(mapping, iterable):
+    'Tally elements from the iterable.'
+    mapping_get = mapping.get
+    for elem in iterable:
+        mapping[elem] = mapping_get(elem, 0) + 1
+
+try:                                    # Load C helper function if available
+    from _collections import _count_elements
+except ImportError:
+    pass
+
+class Counter(dict):
+    '''Dict subclass for counting hashable items.  Sometimes called a bag
+    or multiset.  Elements are stored as dictionary keys and their counts
+    are stored as dictionary values.
+
+    >>> c = Counter('abcdeabcdabcaba')  # count elements from a string
+
+    >>> c.most_common(3)                # three most common elements
+    [('a', 5), ('b', 4), ('c', 3)]
+    >>> sorted(c)                       # list all unique elements
+    ['a', 'b', 'c', 'd', 'e']
+    >>> ''.join(sorted(c.elements()))   # list elements with repetitions
+    'aaaaabbbbcccdde'
+    >>> sum(c.values())                 # total of all counts
+    15
+
+    >>> c['a']                          # count of letter 'a'
+    5
+    >>> for elem in 'shazam':           # update counts from an iterable
+    ...     c[elem] += 1                # by adding 1 to each element's count
+    >>> c['a']                          # now there are seven 'a'
+    7
+    >>> del c['b']                      # remove all 'b'
+    >>> c['b']                          # now there are zero 'b'
+    0
+
+    >>> d = Counter('simsalabim')       # make another counter
+    >>> c.update(d)                     # add in the second counter
+    >>> c['a']                          # now there are nine 'a'
+    9
+
+    >>> c.clear()                       # empty the counter
+    >>> c
+    Counter()
+
+    Note:  If a count is set to zero or reduced to zero, it will remain
+    in the counter until the entry is deleted or the counter is cleared:
+
+    >>> c = Counter('aaabbc')
+    >>> c['b'] -= 2                     # reduce the count of 'b' by two
+    >>> c.most_common()                 # 'b' is still in, but its count is zero
+    [('a', 3), ('c', 1), ('b', 0)]
+
+    '''
+    # References:
+    #   http://en.wikipedia.org/wiki/Multiset
+    #   http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
+    #   http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
+    #   http://code.activestate.com/recipes/259174/
+    #   Knuth, TAOCP Vol. II section 4.6.3
+
+    def __init__(self, iterable=None, /, **kwds):
+        '''Create a new, empty Counter object.  And if given, count elements
+        from an input iterable.  Or, initialize the count from another mapping
+        of elements to their counts.
+
+        >>> c = Counter()                           # a new, empty counter
+        >>> c = Counter('gallahad')                 # a new counter from an iterable
+        >>> c = Counter({'a': 4, 'b': 2})           # a new counter from a mapping
+        >>> c = Counter(a=4, b=2)                   # a new counter from keyword args
+
+        '''
+        super().__init__()
+        self.update(iterable, **kwds)
+
+    def __missing__(self, key):
+        'The count of elements not in the Counter is zero.'
+        # Needed so that self[missing_item] does not raise KeyError
+        return 0
+
+    def total(self):
+        'Sum of the counts'
+        return sum(self.values())
+
+    def most_common(self, n=None):
+        '''List the n most common elements and their counts from the most
+        common to the least.  If n is None, then list all element counts.
+
+        >>> Counter('abracadabra').most_common(3)
+        [('a', 5), ('b', 2), ('r', 2)]
+
+        '''
+        # Emulate Bag.sortedByCount from Smalltalk
+        if n is None:
+            return sorted(self.items(), key=_itemgetter(1), reverse=True)
+
+        # Lazy import to speedup Python startup time
+        import heapq
+        return heapq.nlargest(n, self.items(), key=_itemgetter(1))
+
+    def elements(self):
+        '''Iterator over elements repeating each as many times as its count.
+
+        >>> c = Counter('ABCABC')
+        >>> sorted(c.elements())
+        ['A', 'A', 'B', 'B', 'C', 'C']
+
+        Knuth's example for prime factors of 1836:  2**2 * 3**3 * 17**1
+
+        >>> import math
+        >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
+        >>> math.prod(prime_factors.elements())
+        1836
+
+        Note, if an element's count has been set to zero or is a negative
+        number, elements() will ignore it.
+
+        '''
+        # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
+        return _chain.from_iterable(_starmap(_repeat, self.items()))
+
+    # Override dict methods where necessary
+
+    @classmethod
+    def fromkeys(cls, iterable, v=None):
+        # There is no equivalent method for counters because the semantics
+        # would be ambiguous in cases such as Counter.fromkeys('aaabbc', v=2).
+        # Initializing counters to zero values isn't necessary because zero
+        # is already the default value for counter lookups.  Initializing
+        # to one is easily accomplished with Counter(set(iterable)).  For
+        # more exotic cases, create a dictionary first using a dictionary
+        # comprehension or dict.fromkeys().
+        raise NotImplementedError(
+            'Counter.fromkeys() is undefined.  Use Counter(iterable) instead.')
+
+    def update(self, iterable=None, /, **kwds):
+        '''Like dict.update() but add counts instead of replacing them.
+
+        Source can be an iterable, a dictionary, or another Counter instance.
+
+        >>> c = Counter('which')
+        >>> c.update('witch')           # add elements from another iterable
+        >>> d = Counter('watch')
+        >>> c.update(d)                 # add elements from another counter
+        >>> c['h']                      # four 'h' in which, witch, and watch
+        4
+
+        '''
+        # The regular dict.update() operation makes no sense here because the
+        # replace behavior results in some of the original untouched counts
+        # being mixed-in with all of the other counts for a mismash that
+        # doesn't have a straight-forward interpretation in most counting
+        # contexts.  Instead, we implement straight-addition.  Both the inputs
+        # and outputs are allowed to contain zero and negative counts.
+
+        if iterable is not None:
+            if isinstance(iterable, _collections_abc.Mapping):
+                if self:
+                    self_get = self.get
+                    for elem, count in iterable.items():
+                        self[elem] = count + self_get(elem, 0)
+                else:
+                    # fast path when counter is empty
+                    super().update(iterable)
+            else:
+                _count_elements(self, iterable)
+        if kwds:
+            self.update(kwds)
+
+    def subtract(self, iterable=None, /, **kwds):
+        '''Like dict.update() but subtracts counts instead of replacing them.
+        Counts can be reduced below zero.  Both the inputs and outputs are
+        allowed to contain zero and negative counts.
+
+        Source can be an iterable, a dictionary, or another Counter instance.
+
+        >>> c = Counter('which')
+        >>> c.subtract('witch')             # subtract elements from another iterable
+        >>> c.subtract(Counter('watch'))    # subtract elements from another counter
+        >>> c['h']                          # 2 in which, minus 1 in witch, minus 1 in watch
+        0
+        >>> c['w']                          # 1 in which, minus 1 in witch, minus 1 in watch
+        -1
+
+        '''
+        if iterable is not None:
+            self_get = self.get
+            if isinstance(iterable, _collections_abc.Mapping):
+                for elem, count in iterable.items():
+                    self[elem] = self_get(elem, 0) - count
+            else:
+                for elem in iterable:
+                    self[elem] = self_get(elem, 0) - 1
+        if kwds:
+            self.subtract(kwds)
+
+    def copy(self):
+        'Return a shallow copy.'
+        return self.__class__(self)
+
+    def __reduce__(self):
+        return self.__class__, (dict(self),)
+
+    def __delitem__(self, elem):
+        'Like dict.__delitem__() but does not raise KeyError for missing values.'
+        if elem in self:
+            super().__delitem__(elem)
+
+    def __repr__(self):
+        if not self:
+            return f'{self.__class__.__name__}()'
+        try:
+            # dict() preserves the ordering returned by most_common()
+            d = dict(self.most_common())
+        except TypeError:
+            # handle case where values are not orderable
+            d = dict(self)
+        return f'{self.__class__.__name__}({d!r})'
+
+    # Multiset-style mathematical operations discussed in:
+    #       Knuth TAOCP Volume II section 4.6.3 exercise 19
+    #       and at http://en.wikipedia.org/wiki/Multiset
+    #
+    # Outputs guaranteed to only include positive counts.
+    #
+    # To strip negative and zero counts, add-in an empty counter:
+    #       c += Counter()
+    #
+    # Results are ordered according to when an element is first
+    # encountered in the left operand and then by the order
+    # encountered in the right operand.
+    #
+    # When the multiplicities are all zero or one, multiset operations
+    # are guaranteed to be equivalent to the corresponding operations
+    # for regular sets.
+    #     Given counter multisets such as:
+    #         cp = Counter(a=1, b=0, c=1)
+    #         cq = Counter(c=1, d=0, e=1)
+    #     The corresponding regular sets would be:
+    #         sp = {'a', 'c'}
+    #         sq = {'c', 'e'}
+    #     All of the following relations would hold:
+    #         set(cp + cq) == sp | sq
+    #         set(cp - cq) == sp - sq
+    #         set(cp | cq) == sp | sq
+    #         set(cp & cq) == sp & sq
+    #         (cp == cq) == (sp == sq)
+    #         (cp != cq) == (sp != sq)
+    #         (cp <= cq) == (sp <= sq)
+    #         (cp < cq) == (sp < sq)
+    #         (cp >= cq) == (sp >= sq)
+    #         (cp > cq) == (sp > sq)
+
+    def __eq__(self, other):
+        'True if all counts agree. Missing counts are treated as zero.'
+        if not isinstance(other, Counter):
+            return NotImplemented
+        return all(self[e] == other[e] for c in (self, other) for e in c)
+
+    def __ne__(self, other):
+        'True if any counts disagree. Missing counts are treated as zero.'
+        if not isinstance(other, Counter):
+            return NotImplemented
+        return not self == other
+
+    def __le__(self, other):
+        'True if all counts in self are a subset of those in other.'
+        if not isinstance(other, Counter):
+            return NotImplemented
+        return all(self[e] <= other[e] for c in (self, other) for e in c)
+
+    def __lt__(self, other):
+        'True if all counts in self are a proper subset of those in other.'
+        if not isinstance(other, Counter):
+            return NotImplemented
+        return self <= other and self != other
+
+    def __ge__(self, other):
+        'True if all counts in self are a superset of those in other.'
+        if not isinstance(other, Counter):
+            return NotImplemented
+        return all(self[e] >= other[e] for c in (self, other) for e in c)
+
+    def __gt__(self, other):
+        'True if all counts in self are a proper superset of those in other.'
+        if not isinstance(other, Counter):
+            return NotImplemented
+        return self >= other and self != other
+
+    def __add__(self, other):
+        '''Add counts from two counters.
+
+        >>> Counter('abbb') + Counter('bcc')
+        Counter({'b': 4, 'c': 2, 'a': 1})
+
+        '''
+        if not isinstance(other, Counter):
+            return NotImplemented
+        result = Counter()
+        for elem, count in self.items():
+            newcount = count + other[elem]
+            if newcount > 0:
+                result[elem] = newcount
+        for elem, count in other.items():
+            if elem not in self and count > 0:
+                result[elem] = count
+        return result
+
+    def __sub__(self, other):
+        ''' Subtract count, but keep only results with positive counts.
+
+        >>> Counter('abbbc') - Counter('bccd')
+        Counter({'b': 2, 'a': 1})
+
+        '''
+        if not isinstance(other, Counter):
+            return NotImplemented
+        result = Counter()
+        for elem, count in self.items():
+            newcount = count - other[elem]
+            if newcount > 0:
+                result[elem] = newcount
+        for elem, count in other.items():
+            if elem not in self and count < 0:
+                result[elem] = 0 - count
+        return result
+
+    def __or__(self, other):
+        '''Union is the maximum of value in either of the input counters.
+
+        >>> Counter('abbb') | Counter('bcc')
+        Counter({'b': 3, 'c': 2, 'a': 1})
+
+        '''
+        if not isinstance(other, Counter):
+            return NotImplemented
+        result = Counter()
+        for elem, count in self.items():
+            other_count = other[elem]
+            newcount = other_count if count < other_count else count
+            if newcount > 0:
+                result[elem] = newcount
+        for elem, count in other.items():
+            if elem not in self and count > 0:
+                result[elem] = count
+        return result
+
+    def __and__(self, other):
+        ''' Intersection is the minimum of corresponding counts.
+
+        >>> Counter('abbb') & Counter('bcc')
+        Counter({'b': 1})
+
+        '''
+        if not isinstance(other, Counter):
+            return NotImplemented
+        result = Counter()
+        for elem, count in self.items():
+            other_count = other[elem]
+            newcount = count if count < other_count else other_count
+            if newcount > 0:
+                result[elem] = newcount
+        return result
+
+    def __pos__(self):
+        'Adds an empty counter, effectively stripping negative and zero counts'
+        result = Counter()
+        for elem, count in self.items():
+            if count > 0:
+                result[elem] = count
+        return result
+
+    def __neg__(self):
+        '''Subtracts from an empty counter.  Strips positive and zero counts,
+        and flips the sign on negative counts.
+
+        '''
+        result = Counter()
+        for elem, count in self.items():
+            if count < 0:
+                result[elem] = 0 - count
+        return result
+
+    def _keep_positive(self):
+        '''Internal method to strip elements with a negative or zero count'''
+        nonpositive = [elem for elem, count in self.items() if not count > 0]
+        for elem in nonpositive:
+            del self[elem]
+        return self
+
+    def __iadd__(self, other):
+        '''Inplace add from another counter, keeping only positive counts.
+
+        >>> c = Counter('abbb')
+        >>> c += Counter('bcc')
+        >>> c
+        Counter({'b': 4, 'c': 2, 'a': 1})
+
+        '''
+        for elem, count in other.items():
+            self[elem] += count
+        return self._keep_positive()
+
+    def __isub__(self, other):
+        '''Inplace subtract counter, but keep only results with positive counts.
+
+        >>> c = Counter('abbbc')
+        >>> c -= Counter('bccd')
+        >>> c
+        Counter({'b': 2, 'a': 1})
+
+        '''
+        for elem, count in other.items():
+            self[elem] -= count
+        return self._keep_positive()
+
+    def __ior__(self, other):
+        '''Inplace union is the maximum of value from either counter.
+
+        >>> c = Counter('abbb')
+        >>> c |= Counter('bcc')
+        >>> c
+        Counter({'b': 3, 'c': 2, 'a': 1})
+
+        '''
+        for elem, other_count in other.items():
+            count = self[elem]
+            if other_count > count:
+                self[elem] = other_count
+        return self._keep_positive()
+
+    def __iand__(self, other):
+        '''Inplace intersection is the minimum of corresponding counts.
+
+        >>> c = Counter('abbb')
+        >>> c &= Counter('bcc')
+        >>> c
+        Counter({'b': 1})
+
+        '''
+        for elem, count in self.items():
+            other_count = other[elem]
+            if other_count < count:
+                self[elem] = other_count
+        return self._keep_positive()
+
+
+########################################################################
+###  ChainMap
+########################################################################
+
+class ChainMap(_collections_abc.MutableMapping):
+    ''' A ChainMap groups multiple dicts (or other mappings) together
+    to create a single, updateable view.
+
+    The underlying mappings are stored in a list.  That list is public and can
+    be accessed or updated using the *maps* attribute.  There is no other
+    state.
+
+    Lookups search the underlying mappings successively until a key is found.
+    In contrast, writes, updates, and deletions only operate on the first
+    mapping.
+
+    '''
+
+    def __init__(self, *maps):
+        '''Initialize a ChainMap by setting *maps* to the given mappings.
+        If no mappings are provided, a single empty dictionary is used.
+
+        '''
+        self.maps = list(maps) or [{}]          # always at least one map
+
+    def __missing__(self, key):
+        raise KeyError(key)
+
+    def __getitem__(self, key):
+        for mapping in self.maps:
+            try:
+                return mapping[key]             # can't use 'key in mapping' with defaultdict
+            except KeyError:
+                pass
+        return self.__missing__(key)            # support subclasses that define __missing__
+
+    def get(self, key, default=None):
+        return self[key] if key in self else default
+
+    def __len__(self):
+        return len(set().union(*self.maps))     # reuses stored hash values if possible
+
+    def __iter__(self):
+        d = {}
+        for mapping in map(dict.fromkeys, reversed(self.maps)):
+            d |= mapping                        # reuses stored hash values if possible
+        return iter(d)
+
+    def __contains__(self, key):
+        return any(key in m for m in self.maps)
+
+    def __bool__(self):
+        return any(self.maps)
+
+    @_recursive_repr()
+    def __repr__(self):
+        return f'{self.__class__.__name__}({", ".join(map(repr, self.maps))})'
+
+    @classmethod
+    def fromkeys(cls, iterable, *args):
+        'Create a ChainMap with a single dict created from the iterable.'
+        return cls(dict.fromkeys(iterable, *args))
+
+    def copy(self):
+        'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
+        return self.__class__(self.maps[0].copy(), *self.maps[1:])
+
+    __copy__ = copy
+
+    def new_child(self, m=None, **kwargs):      # like Django's Context.push()
+        '''New ChainMap with a new map followed by all previous maps.
+        If no map is provided, an empty dict is used.
+        Keyword arguments update the map or new empty dict.
+        '''
+        if m is None:
+            m = kwargs
+        elif kwargs:
+            m.update(kwargs)
+        return self.__class__(m, *self.maps)
+
+    @property
+    def parents(self):                          # like Django's Context.pop()
+        'New ChainMap from maps[1:].'
+        return self.__class__(*self.maps[1:])
+
+    def __setitem__(self, key, value):
+        self.maps[0][key] = value
+
+    def __delitem__(self, key):
+        try:
+            del self.maps[0][key]
+        except KeyError:
+            raise KeyError(f'Key not found in the first mapping: {key!r}')
+
+    def popitem(self):
+        'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
+        try:
+            return self.maps[0].popitem()
+        except KeyError:
+            raise KeyError('No keys found in the first mapping.')
+
+    def pop(self, key, *args):
+        'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
+        try:
+            return self.maps[0].pop(key, *args)
+        except KeyError:
+            raise KeyError(f'Key not found in the first mapping: {key!r}')
+
+    def clear(self):
+        'Clear maps[0], leaving maps[1:] intact.'
+        self.maps[0].clear()
+
+    def __ior__(self, other):
+        self.maps[0].update(other)
+        return self
+
+    def __or__(self, other):
+        if not isinstance(other, _collections_abc.Mapping):
+            return NotImplemented
+        m = self.copy()
+        m.maps[0].update(other)
+        return m
+
+    def __ror__(self, other):
+        if not isinstance(other, _collections_abc.Mapping):
+            return NotImplemented
+        m = dict(other)
+        for child in reversed(self.maps):
+            m.update(child)
+        return self.__class__(m)
+
+
+################################################################################
+### UserDict
+################################################################################
+
+class UserDict(_collections_abc.MutableMapping):
+
+    # Start by filling-out the abstract methods
+    def __init__(self, dict=None, /, **kwargs):
+        self.data = {}
+        if dict is not None:
+            self.update(dict)
+        if kwargs:
+            self.update(kwargs)
+
+    def __len__(self):
+        return len(self.data)
+
+    def __getitem__(self, key):
+        if key in self.data:
+            return self.data[key]
+        if hasattr(self.__class__, "__missing__"):
+            return self.__class__.__missing__(self, key)
+        raise KeyError(key)
+
+    def __setitem__(self, key, item):
+        self.data[key] = item
+
+    def __delitem__(self, key):
+        del self.data[key]
+
+    def __iter__(self):
+        return iter(self.data)
+
+    # Modify __contains__ and get() to work like dict
+    # does when __missing__ is present.
+    def __contains__(self, key):
+        return key in self.data
+
+    def get(self, key, default=None):
+        if key in self:
+            return self[key]
+        return default
+
+
+    # Now, add the methods in dicts but not in MutableMapping
+    def __repr__(self):
+        return repr(self.data)
+
+    def __or__(self, other):
+        if isinstance(other, UserDict):
+            return self.__class__(self.data | other.data)
+        if isinstance(other, dict):
+            return self.__class__(self.data | other)
+        return NotImplemented
+
+    def __ror__(self, other):
+        if isinstance(other, UserDict):
+            return self.__class__(other.data | self.data)
+        if isinstance(other, dict):
+            return self.__class__(other | self.data)
+        return NotImplemented
+
+    def __ior__(self, other):
+        if isinstance(other, UserDict):
+            self.data |= other.data
+        else:
+            self.data |= other
+        return self
+
+    def __copy__(self):
+        inst = self.__class__.__new__(self.__class__)
+        inst.__dict__.update(self.__dict__)
+        # Create a copy and avoid triggering descriptors
+        inst.__dict__["data"] = self.__dict__["data"].copy()
+        return inst
+
+    def copy(self):
+        if self.__class__ is UserDict:
+            return UserDict(self.data.copy())
+        import copy
+        data = self.data
+        try:
+            self.data = {}
+            c = copy.copy(self)
+        finally:
+            self.data = data
+        c.update(self)
+        return c
+
+    @classmethod
+    def fromkeys(cls, iterable, value=None):
+        d = cls()
+        for key in iterable:
+            d[key] = value
+        return d
+
+
+################################################################################
+### UserList
+################################################################################
+
+class UserList(_collections_abc.MutableSequence):
+    """A more or less complete user-defined wrapper around list objects."""
+
+    def __init__(self, initlist=None):
+        self.data = []
+        if initlist is not None:
+            # XXX should this accept an arbitrary sequence?
+            if type(initlist) == type(self.data):
+                self.data[:] = initlist
+            elif isinstance(initlist, UserList):
+                self.data[:] = initlist.data[:]
+            else:
+                self.data = list(initlist)
+
+    def __repr__(self):
+        return repr(self.data)
+
+    def __lt__(self, other):
+        return self.data < self.__cast(other)
+
+    def __le__(self, other):
+        return self.data <= self.__cast(other)
+
+    def __eq__(self, other):
+        return self.data == self.__cast(other)
+
+    def __gt__(self, other):
+        return self.data > self.__cast(other)
+
+    def __ge__(self, other):
+        return self.data >= self.__cast(other)
+
+    def __cast(self, other):
+        return other.data if isinstance(other, UserList) else other
+
+    def __contains__(self, item):
+        return item in self.data
+
+    def __len__(self):
+        return len(self.data)
+
+    def __getitem__(self, i):
+        if isinstance(i, slice):
+            return self.__class__(self.data[i])
+        else:
+            return self.data[i]
+
+    def __setitem__(self, i, item):
+        self.data[i] = item
+
+    def __delitem__(self, i):
+        del self.data[i]
+
+    def __add__(self, other):
+        if isinstance(other, UserList):
+            return self.__class__(self.data + other.data)
+        elif isinstance(other, type(self.data)):
+            return self.__class__(self.data + other)
+        return self.__class__(self.data + list(other))
+
+    def __radd__(self, other):
+        if isinstance(other, UserList):
+            return self.__class__(other.data + self.data)
+        elif isinstance(other, type(self.data)):
+            return self.__class__(other + self.data)
+        return self.__class__(list(other) + self.data)
+
+    def __iadd__(self, other):
+        if isinstance(other, UserList):
+            self.data += other.data
+        elif isinstance(other, type(self.data)):
+            self.data += other
+        else:
+            self.data += list(other)
+        return self
+
+    def __mul__(self, n):
+        return self.__class__(self.data * n)
+
+    __rmul__ = __mul__
+
+    def __imul__(self, n):
+        self.data *= n
+        return self
+
+    def __copy__(self):
+        inst = self.__class__.__new__(self.__class__)
+        inst.__dict__.update(self.__dict__)
+        # Create a copy and avoid triggering descriptors
+        inst.__dict__["data"] = self.__dict__["data"][:]
+        return inst
+
+    def append(self, item):
+        self.data.append(item)
+
+    def insert(self, i, item):
+        self.data.insert(i, item)
+
+    def pop(self, i=-1):
+        return self.data.pop(i)
+
+    def remove(self, item):
+        self.data.remove(item)
+
+    def clear(self):
+        self.data.clear()
+
+    def copy(self):
+        return self.__class__(self)
+
+    def count(self, item):
+        return self.data.count(item)
+
+    def index(self, item, *args):
+        return self.data.index(item, *args)
+
+    def reverse(self):
+        self.data.reverse()
+
+    def sort(self, /, *args, **kwds):
+        self.data.sort(*args, **kwds)
+
+    def extend(self, other):
+        if isinstance(other, UserList):
+            self.data.extend(other.data)
+        else:
+            self.data.extend(other)
+
+
+################################################################################
+### UserString
+################################################################################
+
+class UserString(_collections_abc.Sequence):
+
+    def __init__(self, seq):
+        if isinstance(seq, str):
+            self.data = seq
+        elif isinstance(seq, UserString):
+            self.data = seq.data[:]
+        else:
+            self.data = str(seq)
+
+    def __str__(self):
+        return str(self.data)
+
+    def __repr__(self):
+        return repr(self.data)
+
+    def __int__(self):
+        return int(self.data)
+
+    def __float__(self):
+        return float(self.data)
+
+    def __complex__(self):
+        return complex(self.data)
+
+    def __hash__(self):
+        return hash(self.data)
+
+    def __getnewargs__(self):
+        return (self.data[:],)
+
+    def __eq__(self, string):
+        if isinstance(string, UserString):
+            return self.data == string.data
+        return self.data == string
+
+    def __lt__(self, string):
+        if isinstance(string, UserString):
+            return self.data < string.data
+        return self.data < string
+
+    def __le__(self, string):
+        if isinstance(string, UserString):
+            return self.data <= string.data
+        return self.data <= string
+
+    def __gt__(self, string):
+        if isinstance(string, UserString):
+            return self.data > string.data
+        return self.data > string
+
+    def __ge__(self, string):
+        if isinstance(string, UserString):
+            return self.data >= string.data
+        return self.data >= string
+
+    def __contains__(self, char):
+        if isinstance(char, UserString):
+            char = char.data
+        return char in self.data
+
+    def __len__(self):
+        return len(self.data)
+
+    def __getitem__(self, index):
+        return self.__class__(self.data[index])
+
+    def __add__(self, other):
+        if isinstance(other, UserString):
+            return self.__class__(self.data + other.data)
+        elif isinstance(other, str):
+            return self.__class__(self.data + other)
+        return self.__class__(self.data + str(other))
+
+    def __radd__(self, other):
+        if isinstance(other, str):
+            return self.__class__(other + self.data)
+        return self.__class__(str(other) + self.data)
+
+    def __mul__(self, n):
+        return self.__class__(self.data * n)
+
+    __rmul__ = __mul__
+
+    def __mod__(self, args):
+        return self.__class__(self.data % args)
+
+    def __rmod__(self, template):
+        return self.__class__(str(template) % self)
+
+    # the following methods are defined in alphabetical order:
+    def capitalize(self):
+        return self.__class__(self.data.capitalize())
+
+    def casefold(self):
+        return self.__class__(self.data.casefold())
+
+    def center(self, width, *args):
+        return self.__class__(self.data.center(width, *args))
+
+    def count(self, sub, start=0, end=_sys.maxsize):
+        if isinstance(sub, UserString):
+            sub = sub.data
+        return self.data.count(sub, start, end)
+
+    def removeprefix(self, prefix, /):
+        if isinstance(prefix, UserString):
+            prefix = prefix.data
+        return self.__class__(self.data.removeprefix(prefix))
+
+    def removesuffix(self, suffix, /):
+        if isinstance(suffix, UserString):
+            suffix = suffix.data
+        return self.__class__(self.data.removesuffix(suffix))
+
+    def encode(self, encoding='utf-8', errors='strict'):
+        encoding = 'utf-8' if encoding is None else encoding
+        errors = 'strict' if errors is None else errors
+        return self.data.encode(encoding, errors)
+
+    def endswith(self, suffix, start=0, end=_sys.maxsize):
+        return self.data.endswith(suffix, start, end)
+
+    def expandtabs(self, tabsize=8):
+        return self.__class__(self.data.expandtabs(tabsize))
+
+    def find(self, sub, start=0, end=_sys.maxsize):
+        if isinstance(sub, UserString):
+            sub = sub.data
+        return self.data.find(sub, start, end)
+
+    def format(self, /, *args, **kwds):
+        return self.data.format(*args, **kwds)
+
+    def format_map(self, mapping):
+        return self.data.format_map(mapping)
+
+    def index(self, sub, start=0, end=_sys.maxsize):
+        return self.data.index(sub, start, end)
+
+    def isalpha(self):
+        return self.data.isalpha()
+
+    def isalnum(self):
+        return self.data.isalnum()
+
+    def isascii(self):
+        return self.data.isascii()
+
+    def isdecimal(self):
+        return self.data.isdecimal()
+
+    def isdigit(self):
+        return self.data.isdigit()
+
+    def isidentifier(self):
+        return self.data.isidentifier()
+
+    def islower(self):
+        return self.data.islower()
+
+    def isnumeric(self):
+        return self.data.isnumeric()
+
+    def isprintable(self):
+        return self.data.isprintable()
+
+    def isspace(self):
+        return self.data.isspace()
+
+    def istitle(self):
+        return self.data.istitle()
+
+    def isupper(self):
+        return self.data.isupper()
+
+    def join(self, seq):
+        return self.data.join(seq)
+
+    def ljust(self, width, *args):
+        return self.__class__(self.data.ljust(width, *args))
+
+    def lower(self):
+        return self.__class__(self.data.lower())
+
+    def lstrip(self, chars=None):
+        return self.__class__(self.data.lstrip(chars))
+
+    maketrans = str.maketrans
+
+    def partition(self, sep):
+        return self.data.partition(sep)
+
+    def replace(self, old, new, maxsplit=-1):
+        if isinstance(old, UserString):
+            old = old.data
+        if isinstance(new, UserString):
+            new = new.data
+        return self.__class__(self.data.replace(old, new, maxsplit))
+
+    def rfind(self, sub, start=0, end=_sys.maxsize):
+        if isinstance(sub, UserString):
+            sub = sub.data
+        return self.data.rfind(sub, start, end)
+
+    def rindex(self, sub, start=0, end=_sys.maxsize):
+        return self.data.rindex(sub, start, end)
+
+    def rjust(self, width, *args):
+        return self.__class__(self.data.rjust(width, *args))
+
+    def rpartition(self, sep):
+        return self.data.rpartition(sep)
+
+    def rstrip(self, chars=None):
+        return self.__class__(self.data.rstrip(chars))
+
+    def split(self, sep=None, maxsplit=-1):
+        return self.data.split(sep, maxsplit)
+
+    def rsplit(self, sep=None, maxsplit=-1):
+        return self.data.rsplit(sep, maxsplit)
+
+    def splitlines(self, keepends=False):
+        return self.data.splitlines(keepends)
+
+    def startswith(self, prefix, start=0, end=_sys.maxsize):
+        return self.data.startswith(prefix, start, end)
+
+    def strip(self, chars=None):
+        return self.__class__(self.data.strip(chars))
+
+    def swapcase(self):
+        return self.__class__(self.data.swapcase())
+
+    def title(self):
+        return self.__class__(self.data.title())
+
+    def translate(self, *args):
+        return self.__class__(self.data.translate(*args))
+
+    def upper(self):
+        return self.__class__(self.data.upper())
+
+    def zfill(self, width):
+        return self.__class__(self.data.zfill(width))
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/index.html b/docs/sphinx/_modules/index.html new file mode 100644 index 0000000..25f1760 --- /dev/null +++ b/docs/sphinx/_modules/index.html @@ -0,0 +1,129 @@ + + + + + + + + Overview: module code — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila/utils/bitstrings.html b/docs/sphinx/_modules/tequila/utils/bitstrings.html new file mode 100644 index 0000000..8f790b8 --- /dev/null +++ b/docs/sphinx/_modules/tequila/utils/bitstrings.html @@ -0,0 +1,306 @@ + + + + + + + + tequila.utils.bitstrings — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila.utils.bitstrings

+from enum import Enum
+from typing import List
+from functools import total_ordering
+from math import ceil, log2
+
+
+class BitNumbering(Enum):
+    LSB = 0  # least signigicant bit ordering:  1 -> 0b01 -> [1,0] i.e bit0 is the least significant
+    MSB = 1  # Most  significant bit ordering:  1 -> 0b01 -> [0,1] i.e bit0 is the most significant
+    # MSB is the default
+
+
+@total_ordering
+class BitString:
+    """
+    Bitstring Class
+    All Bitstrings are stored as integers
+    return them as integers, binary strings or arrays of integers
+    """
+
+    @property
+    def numbering(self) -> BitNumbering:
+        return BitNumbering.MSB
+
+    @property
+    def nbits(self):
+        if self._nbits is None:
+            return 0
+        else:
+            return self._nbits
+
+    @nbits.setter
+    def nbits(self, value):
+        self._nbits = value
+        self.update_nbits()
+
+    def update_nbits(self):
+        current = self.nbits
+        min_needed = ceil(log2(self._value + 1))
+        self._nbits = max(current, min_needed)
+        return self
+
+    @property
+    def binary(self):
+        if self.numbering is BitNumbering.MSB:
+            return format(self._value, 'b').zfill(self.nbits)
+        else:
+            return format(self._value, 'b').zfill(self.nbits)[::-1]
+
+    @binary.setter
+    def binary(self, other: str):
+        assert (isinstance(other, str))
+        if other.startswith('0b'):
+            other = other[2:]
+        if self.numbering == BitNumbering.LSB:
+            self._value = int(other[::-1], 2)
+        else:
+            self._value = int(other, 2)
+        self.update_nbits()
+        return self
+
+    @property
+    def integer(self):
+        return self._value
+
+    @integer.setter
+    def integer(self, other: int):
+        self._value = other
+        self.update_nbits()
+        return self
+
+    @property
+    def array(self):
+        return [int(i) for i in self.binary]
+
+    @array.setter
+    def array(self, other):
+        if self.numbering == BitNumbering.MSB:
+            self.integer = int("".join(str(x) for x in other), 2)
+        else:
+            self.integer = int("".join(str(x) for x in reversed(other)), 2)
+        self.update_nbits()
+        return self
+
+    def __init__(self, nbits: int = None):
+        self._value = None
+        self._nbits = nbits
+
+    @classmethod
+    def from_array(cls, array: list, nbits: int = 0):
+        if isinstance(array, cls):
+            return cls.from_bitstring(other=array)
+        result = result = cls(nbits=max(nbits, len(array)))
+        result.array = array
+        return result
+
+    @classmethod
+    def from_int(cls, integer: int, nbits: int = None):
+        if isinstance(integer, cls):
+            return cls.from_bitstring(other=integer, nbits=nbits)
+        result = cls(nbits=nbits)
+        result.integer = integer
+        return result
+
+    @classmethod
+    def from_binary(cls, binary: str, nbits: int = None):
+        if isinstance(binary, cls):
+            return cls.from_bitstring(other=binary)
+        if nbits is None:
+            nbits = len(binary)
+        else:
+            nbits = max(nbits, len(binary))
+
+        result = result = cls(nbits=nbits)
+        result.binary = binary
+        return result
+
+    @classmethod
+    def from_bitstring(cls, other, nbits: int = None):
+        if nbits is None:
+            nbits = other.nbits
+        else:
+            nbits = max(nbits, other.nbits)
+        result = cls(nbits=nbits)
+        result.integer = other.integer
+        return result
+
+    def __add__(self, other):
+        nbits = max(self.nbits, other.nbits)
+        return BitString.from_int(integer=self.integer + other.integer, nbits=nbits)
+
+    def __iadd__(self, other):
+        self.integer = self.integer + other.integer
+        self.update_nbits()
+
+    def __mul__(self, other):
+        return BitString.from_int(integer=self.integer * other.integer, nbits=max(self.nbits, other.nbits))
+
+    def __imul__(self, other):
+        self.integer = self.integer * other.integer
+        self.update_nbits()
+
+    def __eq__(self, other) -> bool:
+        if isinstance(other, int):
+            return self.integer == other
+        if isinstance(other, str):
+            return self.binary == other
+        return self.numbering == other.numbering and self._value == other._value
+
+    def __repr__(self) -> str:
+        return str(self.integer)
+
+    def __hash__(self) -> int:
+        return hash(self._value)
+
+    def __getitem__(self, item: int) -> List[int]:
+        return self.array[item]
+
+    def __setitem__(self, key, value):
+        array = self.array
+        array[key] = value
+        self.array = array
+        return self
+
+    def __lt__(self, other) -> bool:
+        if isinstance(other, int):
+            return self.integer < other
+        return self.integer < other.integer
+
+    def __int__(self) -> int:
+        return self.integer
+
+
+class BitStringLSB(BitString):
+
+    @property
+    def numbering(self) -> BitNumbering:
+        return BitNumbering.LSB
+
+
+def reverse_int_bits(x: int, nbits: int) -> int:
+    if nbits is None:
+        nbits = x.bit_length()
+    assert nbits <= 32
+
+    x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1)
+    x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2)
+    x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4)
+    x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8)
+    x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16)
+    return x >> (32 - nbits)
+
+
+def initialize_bitstring(integer: int, nbits: int = None, numbering_in: BitNumbering = BitNumbering.MSB,
+                         numbering_out: BitNumbering = None):
+    if numbering_out is None:
+        numbering_out = numbering_in
+
+    if numbering_in != numbering_out:
+        integer = reverse_int_bits(integer, nbits)
+
+    if numbering_out == BitNumbering.MSB:
+        return BitString.from_int(integer=integer, nbits=nbits)
+    else:
+        return BitStringLSB.from_int(integer=integer, nbits=nbits)
+
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit.html b/docs/sphinx/_modules/tequila_code/circuit.html new file mode 100644 index 0000000..c7281af --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit.html @@ -0,0 +1,113 @@ + + + + + + + + tequila_code.circuit — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit

+from .circuit import QCircuit
+from .noise import NoiseModel
+from .qpic import export_to
+from .compiler import CircuitCompiler as CircuitCompiler
+
+
+[docs] +def compile_circuit(U, *args, **kwargs): + # see CircuitCompiler documentation + c = CircuitCompiler.standard_gate_set(*args, **kwargs) + return c(U)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit/circuit.html b/docs/sphinx/_modules/tequila_code/circuit/circuit.html new file mode 100644 index 0000000..cbe3ca9 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit/circuit.html @@ -0,0 +1,1191 @@ + + + + + + + + tequila_code.circuit.circuit — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit.circuit

+from __future__ import annotations
+from tequila.circuit._gates_impl import QGateImpl, assign_variable, list_assignment
+from tequila.utils.exceptions import TequilaException, TequilaWarning
+from tequila.utils.bitstrings import BitNumbering
+import typing
+import copy
+from collections import defaultdict
+import warnings
+
+from .qpic import export_to
+
+
+[docs] +class QCircuit(): + """ + Fundamental class representing an abstract circuit. + + Attributes + ---------- + canonical_depth: + the depth of the circuit, if converted to alternating parametrized and unparametrized layers. + canonical_moments: + returns the circuit as a list of Moment objects alternating between parametrized and unparametrized layers. + depth: + returns the gate depth of the circuit. + gates: + returns the gates in the circuit, as a list. + moments: + returns the circuit as a list of Moment objects. + n_qubits: + the number of qubits on which the circuit operates. + numbering: + returns the numbering convention use by tequila circuits. + qubits: + returns a list of qubits acted upon by the circuit. + + + Methods + ------- + make_parameter_map: + + + """ + +
+[docs] + def export_to(self, *args, **kwargs): + """ + Export to png, pdf, qpic, tex with qpic backend + Convenience: see src/tequila/circuit/qpic.py - export_to for more + Parameters + """ + return export_to(self, *args, **kwargs)
+ + + @property + def moments(self): + """ + Divide self into subcircuits representing layers of simultaneous gates. Attempts to minimize gate depth. + Returns + ------- + list: + list of Moment objects. + """ + table = {i: 0 for i in self.qubits} + moms = [] + moms.append(Moment()) + for g in self.gates: + qus = g.qubits + spots = [table[q] for q in qus] + + if max(spots) == len(moms): + + moms.append(Moment([g])) + else: + moms[max(spots)].add_gate(g) + for q in qus: + table[q] = max(spots) + 1 + for mom in moms: + mom.sort_gates() + return moms + + @property + def canonical_moments(self): + """ + Divide self into subcircuits of alternating unparametrized and parametrized layers. + Returns + ------- + list of Moment objects. + """ + table_u = {i: 0 for i in self.qubits} + table_p = {i: 0 for i in self.qubits} + moms = [] + moms.append((Moment(), Moment())) + + for g in self.gates: + p = 0 + qus = g.qubits + if g.is_parametrized(): + if hasattr(g.parameter, 'extract_variables'): + p = 1 + + if p == 0: + spots = [table_u[q] for q in qus] + [table_p[q] for q in qus] + if max(spots) == len(moms): + moms.append((Moment([g]), Moment())) + else: + moms[max(spots)][0].add_gate(g) + for q in qus: + table_u[q] = max(spots) + 1 + table_p[q] = max(spots) + + else: + spots = [max(table_p[q], table_u[q] - 1) for q in qus] + if max(spots) == len(moms): + moms.append((Moment(), Moment([g]))) + else: + moms[max(spots)][1].add_gate(g) + for q in qus: + table_u[q] = table_p[q] = max(spots) + 1 + noms = [] + for m in moms: + noms.extend([m[0], m[1]]) + + for nom in noms: + nom.sort_gates() + return noms + + @property + def depth(self): + """ + gate depth of the abstract circuit. + Returns + ------- + int: the depth. + + """ + return len(self.moments) + + @property + def canonical_depth(self): + """ + gate depth of the abstract circuit in alternating layer form. + Returns + ------- + int: depth of the alternating layer form. + """ + return len(self.canonical_moments) + + @property + def gates(self): + if self._gates is None: + return [] + else: + return self._gates + + @property + def numbering(self) -> BitNumbering: + return BitNumbering.LSB + + @property + def qubits(self): + accumulate = [] + for g in self.gates: + accumulate += list(g.qubits) + return sorted(list(set(accumulate))) + + @property + def n_qubits(self): + return max(self.max_qubit() + 1, self._min_n_qubits) + + @n_qubits.setter + def n_qubits(self, other): + self._min_n_qubits = other + if other < self.max_qubit() + 1: + raise TequilaException( + "You are trying to set n_qubits to " + str( + other) + " but your circuit needs at least: " + str( + self.max_qubit() + 1)) + return self + + def __init__(self, gates=None, parameter_map=None): + """ + init + Parameters + ---------- + gates: + (Default value = None) + the gates to include in the circuit. + parameter_map: + (Default value = None) + mapping to indicate where in the circuit certain parameters appear. + """ + self._n_qubits = None + self._min_n_qubits = 0 + if gates is None: + self._gates = [] + else: + self._gates = list(gates) + + if parameter_map is None: + self._parameter_map = self.make_parameter_map() + else: + self._parameter_map = parameter_map + +
+[docs] + def make_parameter_map(self) -> dict: + """ + Returns + ------- + ParameterMap of the circuit: A dictionary with + keys: variables in the circuit + values: list of all gates and their positions in the circuit + e.g. result[Variable("a")] = [(3, Rx), (5, Ry), ...] + """ + parameter_map = defaultdict(list) + for idx, gate in enumerate(self.gates): + if gate.is_parametrized(): + variables = gate.extract_variables() + for variable in variables: + parameter_map[variable] += [(idx, gate)] + + return parameter_map
+ + +
+[docs] + def is_primitive(self): + """ + Check if this is a single gate wrapped in this structure + :return: True if the circuit is just a single gate + """ + return len(self.gates) == 1
+ + +
+[docs] + def sort_gates(self): + """ + sort self into subcircuits corresponding to all simultaneous operations, greedily; then reinitialize gates. + Returns + ------- + None + """ + sl = [] + for m in self.moments: + sd = {} + for gate in m.gates: + q = min(gate.qubits) + sd[q] = gate + sl.extend([sd[k] for k in sorted(sd.keys())]) + self._gates = sl
+ + +
+[docs] + def replace_gates(self, positions: list, circuits: list, replace: list = None): + """ + Notes + ---------- + Replace or insert gates at specific positions into the circuit + at different positions (faster than multiple calls to replace_gate) + + Parameters + ---------- + positions: list of int: + the positions at which the gates should be added. Always refer to the positions in the original circuit + circuits: list or QCircuit: + the gates to add at the corresponding positions + replace: list of bool: (Default value: None) + Default is None which corresponds to all true + decide if gates shall be replaces or if the new parts shall be inserted without replacement + if replace[i] = true: gate at position [i] will be replaces by gates[i] + if replace[i] = false: gates[i] circuit will be inserted at position [i] (beaming before gate previously at position [i]) + Returns + ------- + new circuit with inserted gates + """ + + assert len(circuits) == len(positions) + if replace is None: + replace = [True] * len(circuits) + else: + assert len(circuits) == len(replace) + + dataset = zip(positions, circuits, replace) + dataset = sorted(dataset, key=lambda x: x[0]) + + offset = 0 + new_gatelist = self.gates + for idx, circuit, do_replace in dataset: + + # failsafe + if hasattr(circuit, "gates"): + gatelist = circuit.gates + elif isinstance(circuit, typing.Iterable): + gatelist = circuit + else: + gatelist = [circuit] + + pos = idx + offset + if do_replace: + new_gatelist = new_gatelist[:pos] + gatelist + new_gatelist[pos + 1:] + offset += len(gatelist) - 1 + else: + new_gatelist = new_gatelist[:pos] + gatelist + new_gatelist[pos:] + offset += len(gatelist) + + result = QCircuit(gates=new_gatelist) + result.n_qubits = max(result.n_qubits, self.n_qubits) + return result
+ + +
+[docs] + def insert_gates(self, positions, gates): + """ + See replace_gates + """ + return self.replace_gates(positions=positions, circuits=gates, replace=[False] * len(gates))
+ + +
+[docs] + def dagger(self): + """ + Returns + ------ + QCircuit: + The adjoint of the circuit + """ + result = QCircuit() + for g in reversed(self.gates): + result += g.dagger() + return result
+ + +
+[docs] + def extract_variables(self) -> list: + """ + return a list containing all the variable objects contained in any of the gates within the unitary + including those nested within gates themselves. + + Returns + ------- + list: + the variables of the circuit + """ + return list(self._parameter_map.keys())
+ + +
+[docs] + def max_qubit(self): + """ + Returns: + int: + Highest index of qubits in the circuit + """ + qmax = 0 + for g in self.gates: + qmax = max(qmax, g.max_qubit) + return qmax
+ + +
+[docs] + def is_fully_parametrized(self): + """ + Returns + ------- + bool: + whether or not all gates in the circuit are paremtrized + """ + for gate in self.gates: + if not gate.is_parametrized(): + return False + else: + if hasattr(gate, 'parameter'): + if not hasattr(gate.parameter, 'wrap'): + return False + else: + continue + else: + continue + return True
+ + +
+[docs] + def is_fully_unparametrized(self): + """ + Returns + ------- + bool: + whether or not all gates in the circuit are unparametrized + """ + for gate in self.gates: + if not gate.is_parametrized(): + continue + else: + if hasattr(gate, 'parameter'): + if not hasattr(gate.parameter, 'wrap'): + continue + else: + return False + else: + return False + return True
+ + +
+[docs] + def is_mixed(self): + return not (self.is_fully_parametrized() or self.is_fully_unparametrized())
+ + + def __iadd__(self, other): + other = self.wrap_gate(gate=other) + + offset = len(self.gates) + for k, v in other._parameter_map.items(): + self._parameter_map[k] += [(x[0] + offset, x[1]) for x in v] + + self._gates += copy.deepcopy(other.gates) + self._min_n_qubits = max(self._min_n_qubits, other._min_n_qubits) + + return self + + def __add__(self, other): + other = self.wrap_gate(other) + gates = [g.copy() for g in (self.gates + other.gates)] + result = QCircuit(gates=gates) + result._min_n_qubits = max(self._min_n_qubits, other._min_n_qubits) + return result + + def __str__(self): + result = "circuit: \n" + for g in self.gates: + result += str(g) + "\n" + return result + + def __eq__(self, other): + if len(self.gates) != len(other.gates): + return False + self.sort_gates() + other.sort_gates() + for i, g in enumerate(self.gates): + if g != other.gates[i]: + return False + return True + + def __repr__(self): + return self.__str__() + +
+[docs] + @staticmethod + def wrap_gate(gate: QGateImpl): + """ + take a gate and return a qcircuit containing only that gate. + Parameters + ---------- + gate: QGateImpl + the gate to wrap in a circuit. + + Returns + ------- + QCircuit: + a one gate circuit. + """ + if isinstance(gate, QCircuit): + return gate + if isinstance(gate, list): + return QCircuit(gates=gate) + else: + return QCircuit(gates=[gate])
+ + +
+[docs] + def to_networkx(self): + """ + Turn a given quantum circuit from tequila into graph form via NetworkX + :param self: tq.gates.QCircuit + :return: G, a graph in NetworkX with qubits as nodes and gate connections as edges + """ + # avoiding dependcies (only used here so far) + import networkx as nx + G = nx.Graph() + for q in self.qubits: + G.add_node(q) + Gdict = {s: [] for s in self.qubits} + for gate in self.gates: + if gate.control: + for s in gate.control: + for t in gate.target: + tstr = '' + tstr += str(t) + target = int(tstr) + Gdict[s].append(target) # add target to key of correlated controls + for p in gate.target: + for r in gate.control: + cstr = '' + cstr += str(r) + control = int(cstr) + Gdict[p].append(control) # add control to key of correlated targets + else: + for s in gate.target: + for t in gate.target: + tstr2 = '' + tstr2 += str(t) + target2 = int(tstr2) + Gdict[s].append(target2) + lConn = [] # List of connections between qubits + for a, b in Gdict.items(): + for q in b: + lConn.append((a, q)) + G.add_edges_from(lConn) + GPaths = list(nx.connected_components( + G)) # connections of various qubits, excluding repetitions (ex- (1,3) instead of (1,3) and (3,1)) + GIso = [g for g in GPaths if len(g) == 1] # list of Isolated qubits + return G
+ + +
+[docs] + @staticmethod + def from_moments(moments: typing.List): + """ + build a circuit from Moment objects. + + Parameters + ---------- + moments: list: + a list of Moment objects. + + Returns + ------- + """ + c = QCircuit() + for m in moments: + c += m.as_circuit() + return c
+ + +
+[docs] + def verify(self) -> bool: + """ + make sure self is built properly and of the correct types. + Returns + ------- + bool: + whether or not the circuit is properly constructed. + + """ + for k, v, in self._parameter_map.items(): + test = [self.gates[x[0]] == x[1] for x in v] + test += [k in self._gates[x[0]].extract_variables() for x in v] + return all(test)
+ + +
+[docs] + def map_qubits(self, qubit_map): + """ + + E.G. Rx(1)Ry(2) --> Rx(3)Ry(1) with qubit_map = {1:3, 2:1} + + Parameters + ---------- + qubit_map + a dictionary which maps old to new qubits + + Returns + ------- + A new circuit with mapped qubits + """ + + new_gates = [gate.map_qubits(qubit_map) for gate in self.gates] + # could speed up by applying qubit_map to parameter_map here + # currently its recreated in the init function + return QCircuit(gates=new_gates)
+ + +
+[docs] + def add_controls(self, control, inpl: typing.Optional[bool] = False) \ + -> typing.Optional[QCircuit]: + """Depending on the truth value of inpl: + - return controlled version of self with control as the control qubits if inpl; + - mutate self so that the qubits in control are added as the control qubits if not inpl. + + Raise ValueError if there any qubits in common between self and control. + """ + if inpl: + self._inpl_control_circ(control) + return self + else: + # return self._return_control_circ(control) + circ = copy.deepcopy(self) + return circ.add_controls(control, inpl=True)
+ + + def _return_control_circ(self, control) -> QCircuit: + """Return controlled version of self with control as the control qubits. + + This is not an in-place method, so it DOES NOT mutates self, and only returns a circuit. + + Raise TequilaWarning if there any qubits in common between self and control. + """ + control = list(set(list_assignment(control))) + + gates = self.gates + cgates = [] + + for gate in gates: + cgate = copy.deepcopy(gate) + + if cgate.is_controlled(): + control_lst = list(set(list(cgate.control) + list(control))) + + if len(control_lst) < len(gate.control) + len(control): + # warnings.warn("Some of the controls {} were already included in the control " + # "of a gate {}.".format(control, gate), TequilaWarning) + raise TequilaWarning(f'Some of the controls {control} were already included ' + f'in the control of a gate {gate}.') + else: + control_lst, not_control = list(control), list() + + # Raise TequilaWarning if target and control are the same qubit + if any(qubit in control for qubit in not_control): + # warnings.warn("The target and control {} were the same qubit for a gate {}." + # .format(control, gate), TequilaWarning) + raise TequilaWarning(f'The target for a gate {gate} ' + f'and the control list {control_lst} had a common qubit.') + + cgate._control = tuple(control_lst) + cgate.finalize() + cgates.append(cgate) + + return QCircuit(gates=cgates) + + def _inpl_control_circ(self, control) -> None: + """Mutate self such that the qubits in control are added as the control qubits + + This is an in-place method, so it mutates self and doesn't return any value. + + Raise TequilaWarning if there any qubits in common between self and control. + """ + gates = self.gates + control = list_assignment(control) + + for gate in gates: + if gate.is_controlled(): + control_lst = list(set(list(gate.control) + list(control))) + + # Need to check duplicates + not_control = list(set(qubit for qubit in list(gate.qubits) + if qubit not in list(gate.control))) + + # Raise TequilaWarning if control qubit is duplicated + if len(control_lst) < len(gate.control) + len(control): + # warnings.warn("Some of the controls {} were already included in the control " + # "of a gate {}.".format(control, gate), TequilaWarning) + raise TequilaWarning(f'Some of the controls {control} were already included ' + f'in the control of a gate {gate}.') + else: + control_lst, not_control = list(control), list() + + # Raise TequilaWarning if target and control are the same qubit + if any(qubit in control for qubit in not_control): + # warnings.warn("The target and control {} were the same qubit for a gate {}." + # .format(control, gate), TequilaWarning) + raise TequilaWarning(f'The target for a gate {gate} ' + f'and the control list {control} had a common qubit.') + + gate._control = tuple(control_lst) + gate.finalize() + +
+[docs] + def map_variables(self, variables: dict, *args, **kwargs): + """ + + Parameters + ---------- + variables + dictionary with old variable names as keys and new variable names or values as values + Returns + ------- + Circuit with changed variables + + """ + + variables = {assign_variable(k): assign_variable(v) for k, v in variables.items()} + + # failsafe + my_variables = self.extract_variables() + for k, v in variables.items(): + if k not in my_variables: + warnings.warn( + "map_variables: variable {} is not part of circuit with variables {}".format(k, + my_variables), + TequilaWarning) + + new_gates = [copy.deepcopy(gate).map_variables(variables) for gate in self.gates] + + return QCircuit(gates=new_gates)
+
+ + + +
+[docs] +class Moment(QCircuit): + """ + the class which represents a set of simultaneously applicable gates. + + Methods + ------- + with_gate: + attempt to add a gate to the moment, replacing any gate it may conflict with. + with_gates: + attempt to add multiple gates to the moment, replacing any gates they may conflict with. + + """ + + @property + def moments(self): + return [self] + + @property + def canonical_moments(self): + """ + Break self up into parametrized and unparametrized layers. + Returns + ------- + list: + list of 2 Moments, one of which may be empty. + """ + mu = [] + mp = [] + for gate in self.gates: + if not gate.is_parametrized(): + mu.append(gate) + else: + if hasattr(gate, 'parameter'): + if not hasattr(gate.parameter, 'wrap'): + mu.append(gate) + else: + mp.append(gate) + else: + mp.append(gate) + return [Moment(mu), Moment(mp)] + + @property + def depth(self): + return 1 + + @property + def canonical_depth(self): + return 2 + + def __init__(self, gates: typing.List[QGateImpl] = None, sort=False): + """ + initialize a moment from gates. + Parameters + ---------- + gates: list: + a list of gates. Can be None. + sort: + whether or not to sort the gates into order from lowest to highest qubit designate. + """ + super().__init__(gates=gates) + occ = [] + if gates is not None: + for g in list(gates): + for q in g.qubits: + if q in occ: + raise TequilaException( + 'cannot have doubly occupied qubits, which occurred at qubit {}'.format( + str(q))) + else: + occ.append(q) + if sort: + self.sort_gates() + +
+[docs] + def with_gate(self, gate: typing.Union[QCircuit, QGateImpl]): + """ + Add a gate, or else replace some gate with it. + + Parameters + ---------- + gate: + the gate to insert into the moment. + + Returns + ------- + Moment: + a New moment with the proper gates. + + """ + prev = self.qubits + newq = gate.qubits + overlap = [] + for n in newq: + if n in prev: + overlap.append(n) + + gates = copy.deepcopy(self.gates) + if len(overlap) == 0: + gates.append(gate) + else: + for i, g in enumerate(gates): + if any([q in overlap for q in g.qubits]): + del g + gates.append(gate) + + return Moment(gates=gates)
+ + +
+[docs] + def with_gates(self, gates): + """ + with gate, but on multiple gates. + + Parameters + ---------- + gates: + list of QGates + + Returns + ------- + Moment: + a new Moment, with the desired gates insert into self. + + """ + gl = list(gates) + first_overlap = [] + for g in gl: + for q in g.qubits: + if q not in first_overlap: + first_overlap.append(q) + else: + raise TequilaException( + 'cannot have a moment with multiple operations acting on the same qubit!') + + new = self.with_gate(gl[0]) + for g in gl[1:]: + new = new.with_gate(g) + new.sort_gates() + return new
+ + +
+[docs] + def add_gate(self, gate: typing.Union[QCircuit, QGateImpl]): + """ + add a gate to the moment. + + Parameters + ---------- + gate: + the desired gate. + + Returns + ------- + Moment + a new moment, of self + a new gate + """ + prev = self.qubits + newq = gate.qubits + for n in newq: + if n in prev: + raise TequilaException( + 'cannot add gate {} to moment; qubit {} already occupied.'.format(str(gate), + str(n))) + + self._gates.append(gate) + self.sort_gates() + return self
+ + +
+[docs] + def replace_gate(self, position, gates): + """ + substitute a gate at a given position with other gates. + Parameters + ---------- + position: + where in the list of gates the gate to be replaced occurs. + gates: + the gates to replace the unwanted gate with. + + Returns + ------- + QCircuit or Moment: + self, with unwanted gate removed and new gates inserted. May not be a moment. + """ + if hasattr(gates, '__iter__'): + gs = gates + else: + gs = [gates] + + new = self.gates[:position] + new.extend(gs) + new.extend(self.gates[(position + 1):]) + try: + return Moment(gates=new) + except: + return QCircuit(gates=new)
+ + +
+[docs] + def as_circuit(self): + """ + convert back into the unrestricted QCircuit. + Returns + ------- + QCircuit: + a circuit with the same gates as self. + """ + return QCircuit(gates=self.gates)
+ + +
+[docs] + def fully_parametrized(self): + """ + Todo: Why not just inherit from base? + Returns + ------- + bool: + whether or not EVERY gate in self.gates is parameterized. + """ + for gate in self.gates: + if not gate.is_parametrized(): + return False + else: + if hasattr(gate, 'parameter'): + if not hasattr(gate.parameter, 'wrap'): + return False + else: + continue + else: + continue + return True
+ + + def __str__(self): + result = "Moment: " + for g in self.gates: + result += str(g) + ", " + return result + + def __iadd__(self, other): + + new = self.as_circuit() + if isinstance(other, QGateImpl): + other = new.wrap_gate(other) + + if isinstance(other, list) and isinstance(other[0], QGateImpl): + new._gates += other + + if isinstance(other, list) and isinstance(other[0], QCircuit): + for o in other: + new._gates += o.gates + else: + new._gates += other.gates + new._min_n_qubits = max(self._min_n_qubits, other._min_n_qubits) + if new.depth == 1: + new = Moment(new.gates) + return new + + def __add__(self, other): + if isinstance(other, Moment): + gates = [g.copy() for g in (self.gates + other.gates)] + result = QCircuit(gates=gates) + result._min_n_qubits = max(self.as_circuit()._min_n_qubits, other._min_n_qubits) + if result.depth == 1: + result = Moment(gates=result.gates) + result._min_n_qubits = max(self.as_circuit()._min_n_qubits, other._min_n_qubits) + elif isinstance(other, QCircuit) and not isinstance(other, Moment): + if not other.is_primitive(): + gates = [g.copy() for g in (self.gates + other.gates)] + result = QCircuit(gates=gates) + result._min_n_qubits = max(self.as_circuit()._min_n_qubits, other._min_n_qubits) + else: + try: + result = self.add_gate(other.gates[0]) + result._min_n_qubits += len(other.qubits) + except: + result = self.as_circuit() + QCircuit.wrap_gate(other) + result._min_n_qubits = max(self.as_circuit()._min_n_qubits, + QCircuit.wrap_gate(other)._min_n_qubits) + + else: + if isinstance(other, QGateImpl): + try: + result = self.add_gate(other) + result._min_n_qubits += len(other.qubits) + except: + result = self.as_circuit() + QCircuit.wrap_gate(other) + result._min_n_qubits = max(self.as_circuit()._min_n_qubits, + QCircuit.wrap_gate(other)._min_n_qubits) + else: + raise TequilaException( + 'cannot add moments to types other than QCircuit,Moment,or Gate; recieved summand of type {}'.format( + str(type(other)))) + return result + +
+[docs] + @staticmethod + def wrap_gate(gate: QGateImpl): + """ + Parameters + ---------- + gate: QGateImpl: + the gate, to wrap as a moment + + Returns + ------- + Moment: + a moment with one gate in it. + """ + if isinstance(gate, QCircuit): + return gate + else: + return Moment(gates=[gate])
+ + +
+[docs] + @staticmethod + def from_moments(moments: typing.List): + """ + Raises + ------ + TequilaException + """ + raise TequilaException( + 'this method should never be called from Moment. Call from the QCircuit class itself instead.')
+
+ + + + +
+[docs] +def find_unused_qubit(U0: QCircuit = None, U1: QCircuit = None)->int: + ''' + Function that checks which are the active qubits of two circuits and + provides an unused qubit that is not among them. If all qubits are used + it adds a new one. + + Parameters + ---------- + U0 : QCircuit, corresponding to the first state. + + U1 : QCircuit, corresponding to the second state. + + Returns + ------- + control_qubit : int + + ''' + + active_qubits = list(set(U0.qubits+U1.qubits)) + # default + free_qubit = max(active_qubits) + 1 + # see if we can use another one + for n in range(max(active_qubits)+1): + if n not in active_qubits: + free_qubit = n + break + assert free_qubit not in active_qubits + + return free_qubit
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit/compiler.html b/docs/sphinx/_modules/tequila_code/circuit/compiler.html new file mode 100644 index 0000000..d050fa6 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit/compiler.html @@ -0,0 +1,1215 @@ + + + + + + + + tequila_code.circuit.compiler — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit.compiler

+from tequila import TequilaException
+from tequila.circuit.circuit import QCircuit
+from tequila.circuit.gates import Rx, Ry, H, X, Rz, ExpPauli, CNOT, Phase, T, Z
+from tequila.circuit._gates_impl import RotationGateImpl, PhaseGateImpl, QGateImpl, \
+    ExponentialPauliGateImpl, TrotterizedGateImpl, PowerGateImpl
+from tequila.utils import to_float
+from tequila.objective.objective import Variable, FixedVariable
+from tequila.objective.objective import Objective
+from tequila.objective.objective import ExpectationValueImpl
+import numpy
+from numpy import pi as pi
+
+import copy, typing
+
+
+
+[docs] +class TequilaCompilerException(TequilaException): + pass
+ + + +
+[docs] +class CircuitCompiler: + """ + an object that performs abstract compilation of QCircuits and Objectives. + + Note + ---- + see init for attributes, since all are specified there + + Methods + ------- + compile_objective + perform compilation on an entire objective + compile_objective_argument + perform compilation on a single arg of objective + compile_circuit: + perform compilation on a circuit. + """ + +
+[docs] + @classmethod + def all_flags_true(cls, *args, **kwargs): + # convenience: Initialize with all flags set to true + # set exceptions in kwargs + c = cls() + for k in c.__dict__.keys(): + try: + c.__dict__[k]=True + except: + pass + for k,v in kwargs.items(): + if k in c.__dict__: + c.__dict__[k]=v + c.gradient_mode=False + + if not c.multicontrol: + c.cc_max = False + return c
+ + +
+[docs] + @classmethod + def standard_gate_set(cls, *args, **kwargs): + # convenience: Initialize with all flags set to true + # but not for standard gates like ry + # set exceptions in kwargs + c = cls.all_flags_true() + c.gradient_mode=False + c.y_gate=False + c.ry_gate=False + + for k,v in kwargs.items(): + if k in c.__dict__: + c.__dict__[k]=v + + if not c.multicontrol: + c.cc_max = False + return c
+ + + def __init__(self, + multitarget=False, + multicontrol=False, + trotterized=False, + generalized_rotation=False, + exponential_pauli=False, + controlled_exponential_pauli=False, + hadamard_power=False, + controlled_power=False, + power=False, + toffoli=False, + controlled_phase=False, + phase=False, + phase_to_z=False, + controlled_rotation=False, + swap=False, + cc_max=False, + gradient_mode=False, + ry_gate=False, + y_gate=False, + ch_gate=False, + hadamard=False + ): + + """ + all parameters are booleans. + Parameters + ---------- + multitarget: + whether or not to split multitarget gates into single target (if gate isn't inherently multitarget) + multicontrol: + whether or not to split gates into single controlled gates. + trotterized: + whether or not to break down TrotterizedGateImpl into other types + generalized_rotation: + whether or not to break down GeneralizedRotationGateImpl into other types + exponential_pauli: + whether or not to break down ExponentialPauliGateImpl into other types + controlled_exponential_pauli + whether or not to break down controlled exponential pauli gates. + hadamard_power: + whether or not to break down Hadamard gates, raised to a power, into other rotation gates. + controlled_power: + whether or not to break down controlled power gates into CNOT and other gates. + power: + whether or not to break down parametrized power gates into rotation gates + toffoli: + whether or not to break down the toffoli gate into CNOTs and other single qubit gates. + controlled_phase: + whether or not to break down controlled phase gates into CNOTs and phase gates. + phase: + whether to replace phase gates + phase_to_z: + specifically, whether to replace phase gates with the z gate + controlled_rotation: + whether or not to break down controlled rotation gates into CNot and single qubit gates + swap: + whether or not to break down swap gates into CNOT gates. + cc_max: + whether or not to break down all controlled gates with 2 or more controls. + ry_gate: + whether or not to break down all rotational y gates + y_gate: + whether or not to break down all y gates + ch_gate: + whether or not to break down all controlled-H gates + """ + self.multitarget = multitarget + self.multicontrol = multicontrol + self.generalized_rotation = generalized_rotation + self.trotterized = trotterized + self.exponential_pauli = exponential_pauli + self.controlled_exponential_pauli = controlled_exponential_pauli + self.hadamard_power = hadamard_power + self.hadamard = hadamard + self.controlled_power = controlled_power + self.power = power + self.toffoli = toffoli + self.controlled_phase = controlled_phase + self.phase = phase + self.phase_to_z = phase_to_z + self.controlled_rotation = controlled_rotation + self.swap = swap + self.cc_max = cc_max + self.gradient_mode = gradient_mode + self.ry_gate = ry_gate + self.y_gate = y_gate + self.ch_gate = ch_gate + + def __call__(self, objective: typing.Union[Objective, QCircuit, ExpectationValueImpl], variables=None, *args, + **kwargs): + + """ + Perform compilation + Parameters + ---------- + objective: + the object (not necessarily an objective) to compile. + variables: optional: + Todo: Jakob, what is this for? + args + kwargs + + Returns + ------- + a compiled version of objective + """ + + if isinstance(objective, Objective) or hasattr(objective, "args"): + result = self.compile_objective(objective=objective, variables=variables, *args, **kwargs) + elif isinstance(objective, QCircuit) or hasattr(objective, "gates"): + result = self.compile_circuit(abstract_circuit=objective, variables=variables, *args, **kwargs) + elif isinstance(objective, ExpectationValueImpl) or hasattr(objective, "U"): + result = self.compile_objective_argument(arg=objective, variables=variables, *args, **kwargs) + else: + raise TequilaCompilerException("Tequila compiler can't process type {}".format(type(objective))) + + return result + +
+[docs] + def compile_objective(self, objective, *args, **kwargs): + """ + Compile an objective. + + Parameters + ---------- + objective: Objective: + the objective. + args + kwargs + Returns + ------- + the objective, compiled + """ + + argsets=objective.argsets + compiled_sets=[] + for argset in argsets: + compiled_args = [] + already_processed = {} + for arg in argset: + if isinstance(arg, ExpectationValueImpl) or (hasattr(arg, "U") and hasattr(arg, "H")): + if arg in already_processed: + compiled_args.append(already_processed[arg]) + else: + compiled = self.compile_objective_argument(arg, *args, **kwargs) + compiled_args.append(compiled) + already_processed[arg] = compiled + else: + # nothing to process for non-expectation-value types, but acts as sanity check + compiled_args.append(self.compile_objective_argument(arg, *args, **kwargs)) + compiled_sets.append(compiled_args) + if isinstance(objective,Objective): + return type(objective)(args=compiled_sets[0],transformation=objective.transformation)
+ + + +
+[docs] + def compile_objective_argument(self, arg, *args, **kwargs): + """ + Compile an argument of an objective. + + Parameters + ---------- + arg: + the term to compile + args + kwargs + + Returns + ------- + the arg, compiled + """ + + + if isinstance(arg, ExpectationValueImpl) or (hasattr(arg, "U") and hasattr(arg, "H")): + return ExpectationValueImpl(H=arg.H, + U=self.compile_circuit(abstract_circuit=arg.U, *args, + **kwargs)) + elif hasattr(arg, "abstract_expectationvalue"): + E = arg.abstract_expectationvalue + E._U = self.compile_circuit(abstract_circuit=E.U, *args, **kwargs) + return type(arg)(E, **arg._input_args) + elif isinstance(arg, Variable) or hasattr(arg, "name") or isinstance(arg, FixedVariable): + return arg + else: + raise TequilaCompilerException( + "Unknown argument type for objectives: {arg} or type {type}".format(arg=arg, type=type(arg)))
+ + +
+[docs] + def compile_circuit(self, abstract_circuit: QCircuit, variables=None, *args, **kwargs) -> QCircuit: + """ + compile a circuit. + Parameters + ---------- + abstract_circuit: QCircuit + the circuit to compile. + variables: + (Default value = None): + list of the variables whose gates, specifically, must compile. + Used to prevent excess compilation in gates whose parameters are fixed. + Default: compile every single gate. + args + kwargs + + Returns + ------- + QCircuit; a compiled circuit. + """ + + n_qubits = abstract_circuit.n_qubits + compiled = QCircuit(abstract_circuit.gates) + + if variables is None: + # check & compile all gates + gatelist = enumerate(abstract_circuit.gates) + else: + # check & compile only gates which depend on variables + gatelist = [] + for variable in variables: + gatelist += abstract_circuit._parameter_map[variable] + + compiled_gates = [] + + for idx, gate in gatelist: + + cg = gate + controlled = gate.is_controlled() + + if self.gradient_mode and (hasattr(cg, "eigenvalues_magnitude") or hasattr(cg, "shifted_gates")): + compiled_gates.append((idx, QCircuit.wrap_gate(cg))) + continue + else: + if hasattr(cg, "compile"): + cg = QCircuit.wrap_gate(cg.compile(**self.__dict__)) + for g in cg.gates: + if g.is_controlled(): + controlled = True + + + # order matters + # first the real multi-target gates + if controlled or self.trotterized: + cg = compile_trotterized_gate(gate=cg) + if controlled or self.generalized_rotation: + cg = compile_generalized_rotation_gate(gate=cg) + if controlled or self.exponential_pauli: + cg = compile_exponential_pauli_gate(gate=cg) + if self.swap: + cg = compile_swap(gate=cg) + if self.phase_to_z: + cg = compile_phase_to_z(gate=cg) + if self.power: + cg = compile_power_gate(gate=cg) + if self.phase: + cg = compile_phase(gate=cg) + if self.ch_gate: + cg = compile_ch(gate=cg) + if self.y_gate: + cg = compile_y(gate=cg) + if self.ry_gate: + cg = compile_ry(gate=cg, controlled_rotation=self.controlled_rotation) + if controlled: + if self.cc_max or self.multicontrol: + cg = compile_to_single_control(gate=cg) + if self.controlled_exponential_pauli: + cg = compile_exponential_pauli_gate(gate=cg) + if self.controlled_power: + cg = compile_controlled_power(gate=cg) + if self.controlled_phase: + cg = compile_controlled_phase(gate=cg) + if self.phase: + cg = compile_phase(gate=cg) + if self.toffoli: + cg = compile_toffoli(gate=cg) + if self.phase: + cg = compile_phase(gate=cg) + if self.controlled_rotation: + cg = compile_controlled_rotation(gate=cg) + + compiled_gates.append((idx, cg)) + + if len(compiled_gates) == 0: + return abstract_circuit + else: + pos, cgs = zip(*compiled_gates) + compiled = abstract_circuit.replace_gates(positions=pos, circuits=cgs) + + return compiled
+
+ + + +
+[docs] +def compiler(f): + """ + Decorator for compile functions. + + Make them applicable for single gates as well as for whole circuits + Note that all arguments need to be passed as keyword arguments + """ + + def wrapper(gate, **kwargs): + if hasattr(gate, "gates"): + result = QCircuit() + for g in gate.gates: + result += f(gate=g, **kwargs) + return result + + elif hasattr(gate, 'U'): + cU = QCircuit() + for g in gate.U.gates: + cU += f(gate=g, **kwargs) + return type(gate)(U=cU, H=gate.H) + elif hasattr(gate, 'transformations'): + outer=[] + for args in gate.argsets: + compiled = [] + for E in args: + if hasattr(E, 'name'): + compiled.append(E) + else: + cU = QCircuit() + for g in E.U.gates: + cU += f(gate=g, **kwargs) + compiled.append(type(E)(U=cU, H=E.H)) + outer.append(compiled) + if isinstance(gate, Objective): + return type(gate)(args=outer[0], transformation=gate._transformation) + else: + return f(gate=gate, **kwargs) + + return wrapper
+ + + +
+[docs] +def change_basis(target, axis=None, name=None, daggered=False): + """ + helper function; returns circuit that performs change of basis. + Parameters + ---------- + target: + the qubit having its basis changed + axis: + The axis of rotation to shift into. + daggered: bool: + adjusts the sign of the gate if axis = 1, I.E, change of basis about Y axis. + + Returns + ------- + QCircuit that performs change of basis on target qubit onto desired axis + + """ + if axis is None and name is None: + raise TequilaException('axis or name must be given.') + + if name: + name = name.lower() + if name in ['h', 'hadamard'] and daggered: + return Ry(angle=numpy.pi / 4, target=target) + elif name in ['h', 'hadamard']: + return Ry(angle=-numpy.pi / 4, target=target) + else: + name_to_axis = {'rx': 0, 'ry': 1, 'rz': 2} + axis = name_to_axis.get(name, name) + + if isinstance(axis, str): + axis = RotationGateImpl.string_to_axis[axis.lower()] + + if axis == 0 and daggered: + return Ry(angle=numpy.pi / 2, target=target) + elif axis == 0: + return Ry(angle=-numpy.pi / 2, target=target) + elif axis == 1 and daggered: + return Rx(angle=-numpy.pi / 2, target=target) + elif axis == 1: + return Rx(angle=numpy.pi / 2, target=target) + else: + return QCircuit()
+ + +
+[docs] +@compiler +def compile_multitarget(gate, *args, **kwargs) -> QCircuit: + """ + If a gate is 'trivially' multitarget, split it into single target gates. + Parameters + ---------- + gate: + the gate in question + + Returns + ------- + QCircuit, the result of compilation. + """ + targets = gate.target + + # don't compile real multitarget gates + if hasattr(gate, "generator") or hasattr(gate, "generators") or hasattr(gate, "paulistring"): + return QCircuit.wrap_gate(gate) + + if isinstance(gate, ExponentialPauliGateImpl) or isinstance(gate, TrotterizedGateImpl): + return QCircuit.wrap_gate(gate) + + if len(targets) == 1: + return QCircuit.wrap_gate(gate) + + if gate.name.lower() in ["swap", "iswap"]: + return QCircuit.wrap_gate(gate) + + result = QCircuit() + for t in targets: + gx = copy.deepcopy(gate) + gx._target = (t,) + result += gx + + return result
+ + + +# return index of control qubits in Gray Code order. +def _pattern(n): + if n == 1: + return [0] + pn = _pattern(n - 1) + + return pn + [n - 1] + pn + + +
+[docs] +@compiler +def compile_controlled_rotation(gate: RotationGateImpl) -> QCircuit: + """ + Recompilation of a controlled-rotation gate + Basis change into Rz then recompilation of controled Rz, then change basis back + :param gate: The rotational gate + :return: set of gates wrapped in QCircuit class + """ + + if not gate.is_controlled(): + return QCircuit.wrap_gate(gate) + + if not isinstance(gate, RotationGateImpl): + return QCircuit.wrap_gate(gate) + + if len(gate.target) > 1: + return compile_controlled_rotation(gate=compile_multitarget(gate=gate)) + + target = gate.target + control = gate.control + k = len(control) + cind = _pattern(k) + [k - 1] + + result = QCircuit() + result += change_basis(target=target, axis=gate._axis) + coeff = - 1 / pow(2, k) + for i, ci in enumerate(cind): + coeff *= -1 + + result += Rz(target=target, angle=coeff * gate.parameter) + result += CNOT(control[ci], target) + result += change_basis(target=target, axis=gate._axis, daggered=True) + + result.n_qubits = result.max_qubit() + 1 + return result
+ + + +
+[docs] +@compiler +def compile_to_single_control(gate) -> QCircuit: + """ + break down a gate into a sequence with no more than single-controlled gates. + Parameters + ---------- + gate: + the gate. + + Returns + ------- + A QCircuit; the result of compilation. + """ + if not gate.is_controlled: + return QCircuit.wrap_gate(gate) + cl = len(gate.control) + target = gate.target + control = gate.control + if cl <= 1: + return QCircuit.wrap_gate(gate) + name = gate.name + back = QCircuit() + if name in ['X', 'x', 'Y', 'y', 'Z', 'z', 'H', 'h']: + if isinstance(gate, PowerGateImpl): + power = gate.parameter + else: + power = 1.0 + new = PowerGateImpl(name=name, power=power, target=target, control=control, generator=gate.make_generator()) + partial = compile_power_gate(gate=new) + back += compile_to_single_control(gate=partial) + elif isinstance(gate, RotationGateImpl): + partial = compile_controlled_rotation(gate=gate) + back += compile_to_single_control(gate=partial) + elif isinstance(gate, PhaseGateImpl): + partial = compile_controlled_phase(gate=gate) + back += compile_to_single_control(gate=partial) + else: + print(gate) + raise TequilaException('frankly, what the fuck is this gate?') + return back
+ + + +
+[docs] +@compiler +def compile_toffoli(gate) -> QCircuit: + """ + break down a toffoli gate into a sequence of CNOT and single qubit gates. + Parameters + ---------- + gate: + the gate. + + Returns + ------- + A QCircuit; the result of compilation. + """ + + if gate.name.lower != 'x': + return QCircuit.wrap_gate(gate) + control = gate.control + c1 = control[1] + c0 = control[0] + target = gate.target + result = QCircuit() + result += H(target) + result += CNOT(c1, target) + result += T(target).dagger() + result += CNOT(c0, target) + result += T(target) + result += CNOT(c1, target) + result += T(target).dagger() + result += CNOT(c0, target) + result += T(c1) + result += T(target) + result += CNOT(c0, c1) + result += H(target) + result += T(c0) + result += T(c1).dagger() + result += CNOT(c0, c1) + + return (result)
+ + + +
+[docs] +@compiler +def compile_power_gate(gate) -> QCircuit: + """ + break down power gates into the rotation gates. + Parameters + ---------- + gate: + the gate. + + Returns + ------- + A QCircuit; the result of compilation. + """ + if not isinstance(gate, PowerGateImpl): + return QCircuit.wrap_gate(gate) + if not gate.is_controlled(): + return compile_power_base(gate=gate) + + return compile_controlled_power(gate=gate)
+ + + +
+[docs] +@compiler +def compile_power_base(gate): + """ + Base case of compile_power_gate: convert a 1-qubit parametrized power gate into rotation gates. + Parameters + ---------- + gate: + the gate. + + Returns + ------- + A QCircuit; the result of compilation. + """ + if not isinstance(gate, PowerGateImpl): + return QCircuit.wrap_gate(gate) + + if gate.is_controlled(): + return QCircuit.wrap_gate(gate) + + power = gate.power + if gate.name.lower() in ['h', 'hadamard']: + ### off by global phase of Exp[ pi power /2] + theta = power * numpy.pi + + result = QCircuit() + result += Ry(angle=-numpy.pi / 4, target=gate.target) + result += Rz(angle=theta, target=gate.target) + result += Ry(angle=numpy.pi / 4, target=gate.target) + elif gate.name == 'X': + ### off by global phase of Exp[ pi power /2] + ''' + if we wanted to do it formally we would use the following + a=-numpy.pi/2 + b=numpy.pi/2 + theta = power*numpy.pi + + result = QCircuit() + result+= Rz(angle=b,target=gate.target) + result+= Ry(angle=theta,target=gate.target) + result+= Rz(angle=a,target=gate.target) + ''' + result = Rx(angle=power * numpy.pi, target=gate.target) + elif gate.name == 'Y': + ### off by global phase of Exp[ pi power /2] + theta = power * numpy.pi + + result = QCircuit() + result += Ry(angle=theta, target=gate.target) + elif gate.name == 'Z': + ### off by global phase of Exp[ pi power /2] + a = 0 + b = power * numpy.pi + theta = 0 + result = QCircuit() + result += Rz(angle=b, target=gate.target) + else: + raise TequilaException('passed a gate with name ' + gate.name + ', which cannot be handled!') + return result
+ + + +
+[docs] +@compiler +def compile_controlled_power(gate: PowerGateImpl) -> QCircuit: + """ + Recompilation of a controlled-power gate + Basis change into Z then recompilation of controled Z, then change basis back + :param gate: The power gate + :return: set of gates wrapped in QCircuit class + """ + if not gate.is_controlled(): + return QCircuit.wrap_gate(gate) + + if not isinstance(gate, PowerGateImpl): + return QCircuit.wrap_gate(gate) + + if len(gate.target) > 1: + return compile_controlled_power(gate=compile_multitarget(gate=gate)) + + power = gate.power + target = gate.target + control = gate.control + + result = QCircuit() + result += Phase(target=control[0], control=control[1:], phi=power * pi / 2) + result += change_basis(target=target, name=gate.name) + result += Rz(target=target, control=control, angle=power * pi) + result += change_basis(target=target, name=gate.name, daggered=True) + + result.n_qubits = result.max_qubit() + 1 + return result
+ + + +
+[docs] +@compiler +def compile_phase(gate) -> QCircuit: + """ + Compile phase gates into Rz gates and cnots, if controlled + Parameters + ---------- + gate: + the gate + + Returns + ------- + QCircuit, the result of compilation. + """ + if not isinstance(gate, PhaseGateImpl): + return QCircuit.wrap_gate(gate) + phase = gate.parameter + result = QCircuit() + if len(gate.control) == 0: + return Rz(angle=phase, target=gate.target) + + result = compile_controlled_phase(gate) + result = compile_phase(result) + return result
+ + + +
+[docs] +@compiler +def compile_controlled_phase(gate) -> QCircuit: + """ + Compile multi-controlled phase gates to 1q - phase gate and multi-controlled Rz gates. + Parameters + ---------- + gate: + the gate. + + Returns + ------- + QCircuit, the result of compilation. + """ + if not isinstance(gate, PhaseGateImpl): + return QCircuit.wrap_gate(gate) + + if len(gate.control) == 0: + return QCircuit.wrap_gate(gate) + + phase = gate.parameter + + result = QCircuit() + result += Phase(target=gate.control[0], control=gate.control[1:], phi=phase / 2) + result += Rz(target=gate.target, control=gate.control, angle=phase) + return compile_controlled_phase(result)
+ + + +
+[docs] +@compiler +def compile_phase_to_z(gate) -> QCircuit: + """ + Compile phase gate to parametrized Z gate. + Parameters + ---------- + gate: + the gate. + + Returns + ------- + QCircuit, the result of compilation. + + """ + if not isinstance(gate, PhaseGateImpl): + return QCircuit.wrap_gate(gate) + phase = gate.parameter + return Z(power=phase / pi, target=gate.target, control=gate.control)
+ + + +
+[docs] +@compiler +def compile_swap(gate) -> QCircuit: + """ + Compile swap gates into CNOT. + Parameters + ---------- + gate: + the gate. + + Returns + ------- + QCircuit, the result of compilation. + """ + if gate.name.lower() == "swap": + if len(gate.target) != 2: + raise TequilaCompilerException("SWAP gates needs two targets") + power = 1 + if hasattr(gate, "power"): + if power is None or power in [1, 1.0]: + pass + else: + raise TequilaCompilerException("Parametrized SWAPs should be decomposed on top level! Something went wrong") + + c = [] + if gate.control is not None: + c = gate.control + return X(target=gate.target[0], control=[gate.target[1]]) \ + + X(target=gate.target[1], control=[gate.target[0]] + list(c), power=power) \ + + X(target=gate.target[0], control=[gate.target[1]]) + + else: + return QCircuit.wrap_gate(gate)
+ + + +
+[docs] +@compiler +def compile_exponential_pauli_gate(gate) -> QCircuit: + """ + Returns the circuit: exp(i*angle*paulistring) + primitively compiled into X,Y Basis Changes and CNOTs and Z Rotations + :param paulistring: The paulistring in given as tuple of tuples (openfermion format) + like e.g ( (0, 'Y'), (1, 'X'), (5, 'Z') ) + :param angle: The angle which parametrizes the gate -> should be real + :returns: the above mentioned circuit as abstract structure + """ + + if hasattr(gate, "paulistring"): + + angle = gate.paulistring.coeff * gate.parameter + + circuit = QCircuit() + + # the general circuit will look like: + # series which changes the basis if necessary + # series of CNOTS associated with basis changes + # Rz gate parametrized on the angle + # series of CNOT (inverted direction compared to before) + # series which changes the basis back + ubasis = QCircuit() + ubasis_t = QCircuit() + cnot_cascade = QCircuit() + + last_qubit = None + previous_qubit = None + for k, v in gate.paulistring.items(): + pauli = v + qubit = [k] # wrap in list for targets= ... + + # see if we need to change the basis + axis = 2 + if pauli.upper() == "X": + axis = 0 + elif pauli.upper() == "Y": + axis = 1 + ubasis += change_basis(target=qubit, axis=axis) + ubasis_t += change_basis(target=qubit, axis=axis, daggered=True) + + if previous_qubit is not None: + cnot_cascade += X(target=qubit, control=previous_qubit) + previous_qubit = qubit + last_qubit = qubit + + reversed_cnot = cnot_cascade.dagger() + + # assemble the circuit + circuit += ubasis + circuit += cnot_cascade + circuit += Rz(target=last_qubit, angle=angle, control=gate.control) + circuit += reversed_cnot + circuit += ubasis_t + + return circuit + + else: + return QCircuit.wrap_gate(gate)
+ + + +
+[docs] +def do_compile_trotterized_gate(generator, steps, factor, randomize, control): + + assert (generator.is_hermitian()) + circuit = QCircuit() + factor = factor / steps + for index in range(steps): + paulistrings = generator.paulistrings + if randomize: + numpy.random.shuffle(paulistrings) + for ps in paulistrings: + coeff = to_float(ps.coeff) + if len(ps._data) == 0 and len(control) > 0: + circuit += Phase(target=control[0], control=control[1:], phi=-factor * coeff / 2) + elif len(ps._data) > 0: + circuit += ExpPauli(paulistring=ps.naked(), angle=factor * coeff, control=control) + else: + # ignore global phases + pass + return circuit
+ + + +
+[docs] +@compiler +def compile_generalized_rotation_gate(gate, compile_exponential_pauli: bool = False): + """ + Parameters + ---------- + gate + compile_exponential_pauli + + Returns + ------- + + """ + if gate.generator is None or gate.name.lower() in ['phase', 'rx', 'ry', 'rz']: + return QCircuit.wrap_gate(gate) + if not hasattr(gate, "eigenvalues_magnitude"): + return QCircuit.wrap_gate(gate) + + steps = 1 if not hasattr(gate, "steps") else gate.steps + + return do_compile_trotterized_gate(generator=gate.generator, steps=steps, randomize=False, + factor=gate.parameter, control=gate.control)
+ + + +
+[docs] +@compiler +def compile_trotterized_gate(gate, compile_exponential_pauli: bool = False): + """ + Parameters + ---------- + gate + compile_exponential_pauli + + Returns + ------- + + """ + if not hasattr(gate, "steps") or hasattr(gate, "eigenvalues_magnitude"): + return QCircuit.wrap_gate(gate) + + randomize=False + if hasattr(gate, "randomize"): + randomize=gate.randomize + result = do_compile_trotterized_gate(generator=gate.generator, steps=gate.steps, factor=gate.parameter, randomize=randomize, control=gate.control) + + if compile_exponential_pauli: + return compile_exponential_pauli_gate(result) + else: + return result
+ + + +
+[docs] +@compiler +def compile_ry(gate: RotationGateImpl, controlled_rotation: bool = False) -> QCircuit: + """ + Compile Ry gates into Rx and Rz. + Parameters + ---------- + gate: + the gate. + controlled_rotation: + determines if the decomposition of the controlled-Ry gate will be performed in compile_controlled_rotation, + if not, decomposition will be performed here + + Returns + ------- + QCircuit, the result of compilation. + """ + if gate.name.lower() == "ry": + + if not (gate.is_controlled() and controlled_rotation): + + return Rz(target=gate.target, control=None, angle=-numpy.pi / 2) \ + + Rx(target=gate.target, control=gate.control, angle=gate.parameter) \ + + Rz(target=gate.target, control=None, angle=numpy.pi / 2) + + return QCircuit.wrap_gate(gate)
+ + + +
+[docs] +@compiler +def compile_y(gate) -> QCircuit: + """ + Compile Y gates into X and Rz. + Parameters + ---------- + gate: + the gate. + + Returns + ------- + QCircuit, the result of compilation. + """ + if gate.name.lower() == "y": + + return Rz(target=gate.target, control=None, angle=-numpy.pi / 2) \ + + X(target=gate.target, control=gate.control, power=gate.power if gate.is_parametrized() else None) \ + + Rz(target=gate.target, control=None, angle=numpy.pi / 2) + + else: + return QCircuit.wrap_gate(gate)
+ + + +
+[docs] +@compiler +def compile_ch(gate: QGateImpl) -> QCircuit: + """ + Compile CH gates into its equivalent: + CH = Ry(0.25pi) CZ Ry(-0.25pi) + Parameters + ---------- + gate: + the gate. + + Returns + ------- + QCircuit, the result of compilation. + """ + if gate.name.lower() == "h" and gate.is_controlled(): + + return Ry(target=gate.target, control=None, angle=-numpy.pi / 4) \ + + Z(target=gate.target, control=gate.control, power=gate.power if gate.is_parametrized() else None) \ + + Ry(target=gate.target, control=None, angle=numpy.pi / 4) + else: + return QCircuit.wrap_gate(gate)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit/gates.html b/docs/sphinx/_modules/tequila_code/circuit/gates.html new file mode 100644 index 0000000..d1a9ac8 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit/gates.html @@ -0,0 +1,1393 @@ + + + + + + + + tequila_code.circuit.gates — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit.gates

+from tequila.circuit.circuit import QCircuit
+from tequila.objective.objective import Variable, assign_variable
+from tequila.circuit import _gates_impl as impl
+import typing, numbers
+from tequila.hamiltonian import PauliString, QubitHamiltonian, paulis
+from tequila.tools import list_assignment
+import numpy as np
+import copy
+
+
+
+[docs] +def Phase(target: typing.Union[list, int], + control: typing.Union[list, int] = None, angle: typing.Union[typing.Hashable, numbers.Number] = None, *args, + **kwargs) -> QCircuit: + """ + Notes + ---------- + Initialize an abstract phase gate which acts as + + .. math:: + S(\\phi) = \\begin{pmatrix} 1 & 0 \\\\ 0 & e^{i\\phi} \\end{pmatrix} + + Parameters + ---------- + angle + defines the phase, can be numeric type (static gate) or hashable non-numeric type (parametrized gate) + target + int or list of int + control + int or list of int + + Returns + ------- + QCircuit object + + """ + + # ensure backward compatibility + if "phi" in kwargs: + if angle is None: + angle = kwargs["phi"] + else: + raise Exception( + "tq.gates.Phase initialization: You gave two angles angle={} and phi={}. Please only use angle".format( + angle, kwargs["phi"])) + + if angle is None: + angle = np.pi + + target = list_assignment(target) + gates = [impl.PhaseGateImpl(phase=angle, target=q, control=control) for q in target] + + return QCircuit.wrap_gate(gates)
+ + + +
+[docs] +def S(target: typing.Union[list, int], control: typing.Union[list, int] = None) -> QCircuit: + """ + Notes + ---------- + + .. math:: + S = \\begin{pmatrix} 1 & 0 \\\\ 0 & e^{i\\frac{\\pi}{2}} \\end{pmatrix} + + Parameters + ---------- + target + int or list of int + control + int or list of int + + Returns + ------- + QCircuit object + """ + return Phase(angle=np.pi / 2, target=target, control=control)
+ + + +
+[docs] +def T(target: typing.Union[list, int], control: typing.Union[list, int] = None): + """ + Notes + ---------- + Fixed phase gate + + .. math:: + T = \\begin{pmatrix} 1 & 0 \\\\ 0 & e^{i\\frac{\\pi}{4}} \\end{pmatrix} + + Parameters + ---------- + target + int or list of int + control + int or list of int + + Returns + ------- + QCircuit object + + """ + return Phase(angle=np.pi / 4, target=target, control=control)
+ + +
+[docs] +def Rx(angle, target: typing.Union[list, int], control: typing.Union[list, int] = None, assume_real=False) -> QCircuit: + """ + Notes + ---------- + Rx gate of the form + + .. math:: + R_{x}(\\text{angle}) = e^{-i\\frac{\\text{angle}}{2} \\sigma_{x}} + + + Parameters + ---------- + angle + Hashable type (will be treated as Variable) or Numeric type (static angle) + target + integer or list of integers + control + integer or list of integers + assume_real + enable improved gradient compilation for controlled gates + Returns + ------- + QCircuit object with this RotationGate + + """ + return RotationGate(axis=0, angle=angle, target=target, control=control, assume_real=assume_real)
+ + + +
+[docs] +def Ry(angle, target: typing.Union[list, int], control: typing.Union[list, int] = None, assume_real=False) -> QCircuit: + """ + Notes + ---------- + Ry gate of the form + + .. math:: + R_{y}(\\text{angle}) = e^{-i\\frac{\\text{angle}}{2} \\sigma_{y}} + + + Parameters + ---------- + angle + Hashable type (will be treated as Variable) or Numeric type (static angle) + target + integer or list of integers + control + integer or list of integers + + Returns + ------- + QCircuit object with this RotationGate + """ + return RotationGate(axis=1, angle=angle, target=target, control=control, assume_real=assume_real)
+ + + +
+[docs] +def Rz(angle, target: typing.Union[list, int], control: typing.Union[list, int] = None, assume_real=False) -> QCircuit: + """ + Notes + ---------- + Rz gate of the form + + .. math:: + R_{z}(\\text{angle}) = e^{-i\\frac{\\text{angle}}{2} \\sigma_{z}} + + + Parameters + ---------- + angle + Hashable type (will be treated as Variable) or Numeric type (static angle) + target + integer or list of integers + control + integer or list of integers + + Returns + QCircuit object with this RotationGate + ------- + """ + return RotationGate(axis=2, angle=angle, target=target, control=control, assume_real=assume_real)
+ + + +
+[docs] +def X(target: typing.Union[list, int], control: typing.Union[list, int] = None, power=None, angle=None, *args, **kwargs) -> QCircuit: + """ + Notes + ---------- + Pauli X Gate + + Parameters + ---------- + target + int or list of int + control + int or list of int + power + numeric type (fixed exponent) or hashable type (parametrized exponent) + angle + similar to power, but will be interpreted as + .. math:: + U(\\text{angle})=e^{-i\\frac{angle}{2} (1-X)} + the default is angle=pi + .. math:: + U(\\pi) = X + If angle and power are given both, tequila will combine them + + Returns + ------- + QCircuit object + """ + + generator = lambda q: paulis.X(q) - paulis.I(q) + return _initialize_power_gate(name="X", power=power, angle=angle, target=target, control=control, + generator=generator, *args, **kwargs)
+ + + +
+[docs] +def H(target: typing.Union[list, int], control: typing.Union[list, int] = None, power=None, angle=None, *args, **kwargs) -> QCircuit: + """ + Notes + ---------- + Hadamard gate + + Parameters + ---------- + target + int or list of int + control + int or list of int + power + numeric type (fixed exponent) or hashable type (parametrized exponent) + angle + similar to power, but will be interpreted as + .. math:: + U(\\text{angle})=e^{-i\\frac{angle}{2} generator} + the default is angle=pi + .. math:: + U(\\pi) = H + If angle and power are given both, tequila will combine them + + Returns + ------- + QCircuit object + + """ + coef = 1 / np.sqrt(2) + generator = lambda q: coef * (paulis.Z(q) + paulis.X(q)) - paulis.I(q) + return _initialize_power_gate(name="H", power=power, angle=angle, target=target, control=control, + generator=generator, *args, **kwargs)
+ + + +
+[docs] +def Y(target: typing.Union[list, int], control: typing.Union[list, int] = None, power=None, angle=None, *args, **kwargs) -> QCircuit: + """ + Notes + ---------- + Pauli Y Gate + + Parameters + ---------- + target: + int or list of int + control + int or list of int + power + numeric type (fixed exponent) or hashable type (parametrized exponent) + angle + similar to power, but will be interpreted as + .. math:: + U(\\text{angle})=e^{-i\\frac{angle}{2} (1-Y)} + the default is angle=pi + .. math:: + U(\\pi) = Y + If angle and power are given both, tequila will combine them + + Returns + ------- + QCircuit object + + """ + generator = lambda q: paulis.Y(q) - paulis.I(q) + return _initialize_power_gate(name="Y", power=power, angle=angle, target=target, control=control, + generator=generator)
+ + + +
+[docs] +def Z(target: typing.Union[list, int], control: typing.Union[list, int] = None, power=None, angle=None, *args, **kwargs) -> QCircuit: + """ + Notes + ---------- + Pauli Z Gate + + Parameters + ---------- + target + int or list of int + control + int or list of int + power + numeric type (fixed exponent) or hashable type (parametrized exponent) + angle + similar to power, but will be interpreted as + .. math:: + U(\\text{angle})=e^{-i\\frac{angle}{2} (1-Z)} + the default is angle=pi + .. math:: + U(\\pi) = Z + If angle and power are given both, tequila will combine them + + Returns + ------- + QCircuit object + + """ + generator = lambda q: paulis.Z(q) - paulis.I(q) + return _initialize_power_gate(name="Z", power=power, angle=angle, target=target, control=control, + generator=generator, *args, **kwargs)
+ + + +
+[docs] +def ExpPauli(paulistring: typing.Union[PauliString, str, dict], angle, control: typing.Union[list, int] = None, *args, **kwargs): + """Exponentiated Pauligate: + + ExpPauli(PauliString, angle) = exp(-i* angle/2* PauliString) + + Parameters + ---------- + paulistring : + given as PauliString structure or as string or dict or list + if given as string: Format should be like X(0)Y(3)Z(2) + if given as list: Format should be like [(0,'X'),(3,'Y'),(2,'Z')] + if given as dict: Format should be like { 0:'X', 3:'Y', 2:'Z' } + angle : + the angle (will be multiplied by paulistring coefficient if there is one) + control : + control qubits + paulistring: typing.Union[PauliString : + + str] : + + control: typing.Union[list : + + int] : + (Default value = None) + + Returns + ------- + type + Gate wrapped in circuit + + """ + + ps = _convert_Paulistring(paulistring) + + # Failsave: If the paulistring contains just one pauli matrix + # it is better to initialize a rotational gate due to strange conventions in some simulators + if len(ps.items()) == 1: + target, axis = tuple(ps.items())[0] + return QCircuit.wrap_gate( + impl.RotationGateImpl(axis=axis, target=target, angle=ps.coeff * assign_variable(angle), control=control, *args, **kwargs)) + else: + return QCircuit.wrap_gate(impl.ExponentialPauliGateImpl(paulistring=ps, angle=angle, control=control, *args, **kwargs))
+ + + +
+[docs] +def Rp(paulistring: typing.Union[PauliString, str], angle, control: typing.Union[list, int] = None, *args, **kwargs): + """ + Same as ExpPauli + """ + return ExpPauli(paulistring=paulistring, angle=angle, control=control, *args, **kwargs)
+ + + +
+[docs] +def GenRot(*args, **kwargs): + return GeneralizedRotation(*args, **kwargs)
+ + +
+[docs] +def GeneralizedRotation(angle: typing.Union[typing.List[typing.Hashable], typing.List[numbers.Real]], + generator: QubitHamiltonian, + control: typing.Union[list, int] = None, + eigenvalues_magnitude: float = 0.5, p0=None, + steps: int = 1, assume_real=False) -> QCircuit: + """ + + Notes + -------- + + A gates which is shift-rule differentiable + - its generator only has two distinguishable eigenvalues + - it is then differentiable by the shift rule + - eigenvalues_magnitude needs to be given upon initialization (this is "r" from Schuld et. al. and the default is r=1/2) + - the generator will not (!) be verified to fullfill the properties + Compiling will be done in analogy to a trotterized gate with steps=1 as default + + The gate will act in the same way as rotations and exppauli gates + + .. math:: + U_{G}(\\text{angle}) = e^{-i\\frac{\\text{angle}}{2} G} + + Parameters + ---------- + angle + numeric type or hashable symbol or tequila objective + generator + tequila QubitHamiltonian or any other structure with paulistrings + control + list of control qubits + eigenvalues_magnitude + magnitude of eigenvalues, in most papers referred to as "r" (default 0.5) + p0 + possible nullspace projector (if the rotation is happens in Q = 1-P0). See arxiv:2011.05938 + steps + possible Trotterization steps (default 1) + + Returns + ------- + The gate wrapped in a circuit + """ + + return QCircuit.wrap_gate( + impl.GeneralizedRotationImpl(angle=assign_variable(angle), generator=generator, control=control, + eigenvalues_magnitude=eigenvalues_magnitude, steps=steps, assume_real=assume_real, p0=p0))
+ + + + + +
+[docs] +def Trotterized(generator: QubitHamiltonian = None, + steps: int = 1, + angle: typing.Union[typing.Hashable, numbers.Real, Variable] = None, + control: typing.Union[list, int] = None, + randomize=False, + *args, **kwargs) -> QCircuit: + """ + + Parameters + ---------- + generator : + generator of the gate U = e^{-i\frac{angle}{2} G } + angles : + coefficients for each generator + steps : + trotter steps + control : + control qubits + generators: QubitHamiltonian : + The generator of the gate + steps: int : + Trotter Steps + angle: typing.Hashable : + A symbol that will be converted to a tq.Variable + numbers.Real : + A fixed real number + Variable : + A tequila Variable + control: control qubits + Returns + ------- + QCircuit + + """ + + # downward compatibility + if "generators" in kwargs: + if generator is None: + if len(kwargs["generators"]) > 1: + if "angles" not in kwargs: + angles = [angle]*len(kwargs["generators"]) + else: + angles = kwargs["angles"] + result = QCircuit() + for angle,g in zip(angles,kwargs["generators"]): + result += Trotterized(generator=g, angle=angle, steps=steps, control=control, randomize=randomize) + return result + else: + generator = kwargs["generators"][0] + else: + raise Exception("Trotterized: You gave generators={} and generator={}".format(generator, kwargs["generators"])) + + if "angles" in kwargs: + if angle is None: + if len(kwargs["angles"]) > 1: + raise Exception("multiple angles given, but only one generator") + angle = kwargs["angles"][0] + else: + raise Exception("Trotterized: You gave angles={} and angle={}".format(angle, kwargs["angles"])) + + angle = assign_variable(angle) + + return QCircuit.wrap_gate(impl.TrotterizedGateImpl(generator=generator, angle=angle, steps=steps, control=control, randomize=randomize, **kwargs))
+ + + +
+[docs] +def SWAP(first: int, second: int, angle: float = None, control: typing.Union[int, list] = None, power: float = None, *args, + **kwargs) -> QCircuit: + """ + Notes + ---------- + SWAP gate, order of targets does not matter + + Parameters + ---------- + first: int + target qubit + second: int + target qubit + angle: numeric type or hashable type + exponent in the for e^{-i a/2 G} + control + int or list of ints + power + numeric type (fixed exponent) or hashable type (parametrized exponent in the form (SWAP)^n + + Returns + ------- + QCircuit + + """ + + target = [first, second] + if angle is not None: + assert power is None + angle = assign_variable(angle) + elif power is not None: + angle = assign_variable(power)*np.pi + generator = 0.5 * (paulis.X(target) + paulis.Y(target) + paulis.Z(target) - paulis.I(target)) + if angle is None or power in [1, 1.0]: + return QGate(name="SWAP", target=target, control=control, generator=generator) + else: + return GeneralizedRotation(angle=angle, control=control, generator=generator, + eigenvalues_magnitude=0.25)
+ + + +
+[docs] +def iSWAP(first: int, second: int, control: typing.Union[int, list] = None, power: float = 1.0, *args, + **kwargs) -> QCircuit: + """ + Notes + ---------- + iSWAP gate + .. math:: + iSWAP = e^{i\\frac{\\pi}{4} (X \\otimes X + Y \\otimes Y )} + + Parameters + ---------- + first: int + target qubit + second: int + target qubit + control + int or list of ints + power + numeric type (fixed exponent) or hashable type (parametrized exponent) + + Returns + ------- + QCircuit + + """ + + generator = paulis.from_string(f"X({first})X({second}) + Y({first})Y({second})") + + p0 = paulis.Projector("|00>") + paulis.Projector("|11>") + p0 = p0.map_qubits({0:first, 1:second}) + + gate = QubitExcitationImpl(angle=power*(-np.pi/2), target=generator.qubits, generator=generator, p0=p0, control=control, compile_options="vanilla", *args, **kwargs) + + return QCircuit.wrap_gate(gate)
+ + + +
+[docs] +def Givens(first: int, second: int, control: typing.Union[int, list] = None, angle: float = None, *args, + **kwargs) -> QCircuit: + """ + Notes + ---------- + Givens gate G + .. math:: + G = e^{-i\\theta \\frac{(Y \\otimes X - X \\otimes Y )}{2}} + + Parameters + ---------- + first: int + target qubit + second: int + target qubit + control + int or list of ints + angle + numeric type (fixed exponent) or hashable type (parametrized exponent), theta in the above formula + + Returns + ------- + QCircuit + + """ + + return QubitExcitation(target=[second,first], angle=2*angle, control=control, *args, **kwargs) # twice the angle since theta is not divided by two in the matrix exponential
+ + + +""" +Convenience Initialization Routines for controlled gates following the patern: Gate(control_qubit, target_qubit, possible_parameter) +All can be initialized as well with the standard operations above +""" + + +
+[docs] +def CNOT(control: int, target: int) -> QCircuit: + """ + Convenience CNOT initialization + + Parameters + ---------- + control: int + control qubit + target: int + target qubit + + Returns + ------- + QCircuit object + """ + return X(target=target, control=control)
+ + + +
+[docs] +def Toffoli(first: int, second: int, target: int) -> QCircuit: + """ + Convenience Toffoli initialization + + Parameters + ---------- + first: int + first control qubit + second: int + second control qubit + target: int + target qubit + + Returns + ------- + QCircuit object + + """ + return X(target=target, control=[first, second])
+ + + +
+[docs] +def CX(control: int, target: int) -> QCircuit: + """ + Convenience initialization CX (CNOT) + + Parameters + ---------- + control: int + control qubit + target: int + target qubit + + Returns + ------- + QCircuit object + """ + return X(target=target, control=control)
+ + + +
+[docs] +def CY(control: int, target: int) -> QCircuit: + """ + Convenience initialization CY (controlled Pauli Y) + + Parameters + ---------- + control: int + control qubit + target: int + target qubit + + Returns + ------- + QCircuit object + """ + return Y(target=target, control=control)
+ + + +
+[docs] +def CZ(control: int, target: int) -> QCircuit: + """ + Convenience initialization CZ (controlled Pauli Z) + + Parameters + ---------- + control: int + control qubit + target: int + target qubit + + Returns + ------- + QCircuit object + """ + return Z(target=target, control=control)
+ + + +
+[docs] +def CRx(control: int, target: int, angle: float) -> QCircuit: + """ + Convenience initialization CRx (controlled Pauli X Rotation) + + Parameters + ---------- + control: int + control qubit + target: int + target qubit + angle: + Hashable type (will be treated as Variable) or Numeric type (static angle) + + Returns + ------- + QCircuit object + """ + return Rx(target=target, control=control, angle=angle)
+ + + +
+[docs] +def CRy(control: int, target: int, angle: float) -> QCircuit: + """ + Convenience initialization CRy (controlled Pauli Y Rotation) + + Parameters + ---------- + control: int + control qubit + target: int + target qubit + angle: + Hashable type (will be treated as Variable) or Numeric type (static angle) + + Returns + ------- + QCircuit object + """ + return Ry(target=target, control=control, angle=angle)
+ + + +
+[docs] +def CRz(control: int, target: int, angle: float) -> QCircuit: + """ + Convenience initialization CRz (controlled Pauli Z Rotation) + + Parameters + ---------- + control: int + control qubit + target: int + target qubit + angle: + Hashable type (will be treated as Variable) or Numeric type (static angle) + + Returns + ------- + QCircuit object + """ + return Rz(target=target, control=control, angle=angle)
+ + + +
+[docs] +def U(theta, phi, lambd, target: typing.Union[list, int], control: typing.Union[list, int] = None) -> QCircuit: + """ + Notes + ---------- + Convenient gate, one of the abstract gates defined by OpenQASM. + + .. math:: + U(\\theta, \\phi, \\lambda) = R_z(\\phi)R_x(-\\pi/2)R_z(\\theta)R_x(\\pi/2)R_z(\\lambda) + U(\\theta, \\phi, \\lambda) = \\begin{pmatrix} + e^{-i \\frac{\\phi}{2}} & 0 \\\\ + 0 & e^{i \\frac{\\phi}{2}} + \\end{pmatrix} + \\begin{pmatrix} + \\cos{-\\frac{\\pi}{4}} & -i \\sin{-\\frac{\\pi}{4}} \\\\ + -i \\sin{-\\frac{\\pi}{4}} & \\cos{-\\frac{\\pi}{4}} + \\end{pmatrix} + \\begin{pmatrix} + e^{-i \\frac{\\theta}{2}} & 0 \\\\ + 0 & e^{i \\frac{\\theta}{2}} + \\end{pmatrix} + \\begin{pmatrix} + \\cos{\\frac{\\pi}{4}} & -i \\sin{\\frac{\\pi}{4}} \\\\ + -i \\sin{\\frac{\\pi}{4}} & \\cos{\\frac{\\pi}{4}} + \\end{pmatrix} + \\begin{pmatrix} + e^{-i \\frac{\\lambda}{2}} & 0 \\\\ + 0 & e^{i \\frac{\\lambda}{2}} + \\end{pmatrix} + + U(\\theta, \\phi, \\lambda) = \\begin{pmatrix} + \\cos{\\frac{\\theta}{2}} & + -e^{i \\lambda} \\sin{\\frac{\\theta}{2}} \\\\ + e^{i \\phi} \\sin{\\frac{\\theta}{2}} & + e^{i (\\phi+\\lambda)} \\cos{\\frac{\\theta}{2}} + \\end{pmatrix} + + Parameters + ---------- + theta + first parameter angle + phi + second parameter angle + lamnd + third parameter angle + target + int or list of int + control + int or list of int + + Returns + ------- + QCircuit object + """ + + theta = assign_variable(theta) + phi = assign_variable(phi) + lambd = assign_variable(lambd) + pi_half = assign_variable(np.pi / 2) + + return Rz(angle=lambd, target=target, control=control) + \ + Rx(angle=pi_half, target=target, control=control) + \ + Rz(angle=theta, target=target, control=control) + \ + Rx(angle=-pi_half, target=target, control=control) + \ + Rz(angle=phi, target=target, control=control)
+ + + +
+[docs] +def u1(lambd, target: typing.Union[list, int], control: typing.Union[list, int] = None) -> QCircuit: + """ + Notes + ---------- + Convenient gate, one of the abstract gates defined by Quantum Experience Standard Header. + Changes the phase of a carrier without applying any pulses. + + .. math:: + from OpenQASM 2.0 specification: + u1(\\lambda) \\sim U(0, 0, \\lambda) = R_z(\\lambda) = e^{-i\\frac{\\lambda}{2} \\sigma_{z}} + also is equal to: + u1(\\lambda) = \\begin{pmatrix} 1 & 0 \\\\ 0 & e^{i\\lambda} \\end{pmatrix} + which is the Tequila Phase gate: + u1(\\lambda) = Phase(\\lambda) + + Parameters + ---------- + lambd + parameter angle + target + int or list of int + control + int or list of int + + Returns + ------- + QCircuit object + """ + + return Phase(phi=lambd, target=target, control=control)
+ + + +
+[docs] +def u2(phi, lambd, target: typing.Union[list, int], control: typing.Union[list, int] = None) -> QCircuit: + """ + Notes + ---------- + Convenient gate, one of the abstract gates defined by Quantum Experience Standard Header. + Uses a single \\pi/2-pulse. + + .. math:: + u2(\\phi, \\lambda) = U(\\pi/2, \\phi, \\lambda) = R_z(\\phi + \\pi/2)R_x(\\pi/2)R_z(\\lambda - \\pi/2) + + u2(\\phi, \\lambda) = \\frac{1}{\\sqrt{2}} + \\begin{pmatrix} + 1 & -e^{i\\lambda} \\\\ + e^{i\\phi} & e^{i(\\phi+\\lambda)} + \\end{pmatrix} + + Parameters + ---------- + phi + first parameter angle + lambd + second parameter angle + target + int or list of int + control + int or list of int + + Returns + ------- + QCircuit object + """ + + return U(theta=np.pi / 2, phi=phi, lambd=lambd, target=target, control=control)
+ + + +
+[docs] +def u3(theta, phi, lambd, target: typing.Union[list, int], control: typing.Union[list, int] = None) -> QCircuit: + """ + Notes + ---------- + Convenient gate, one of the abstract gates defined by Quantum Experience Standard Header + The most general single-qubit gate. + Uses a pair of \\pi/2-pulses. + + .. math:: + u3(\\theta, \\phi, \\lambda) = U(\\theta, \\phi, \\lambda) + = \\begin{pmatrix} + \\cos{\\frac{\\5theta}{2}} & + -e^{i \\lambda} \\sin{\\frac{\\theta}{2}} \\\\ + e^{i \\phi} \\sin{\\frac{\\theta}{2}} & + e^{i (\\phi+\\lambda)} \\cos{\\frac{\\theta}{2}} + \\end{pmatrix} + + Parameters + ---------- + theta + first parameter angle + phi + second parameter angle + lambd + third parameter angle + target + int or list of int + control + int or list of int + + Returns + ------- + QCircuit object + """ + + return U(theta=theta, phi=phi, lambd=lambd, target=target, control=control)
+ + + +
+[docs] +def QubitExcitation(angle: typing.Union[numbers.Real, Variable, typing.Hashable], target: typing.List, control=None, + assume_real: bool = False, compile_options="optimize"): + """ + A Qubit Excitation, as described under "qubit perspective" in https://doi.org/10.1039/D0SC06627C + For the Fermionic operators under corresponding Qubit encodings: Use the chemistry interface + Parameters + ---------- + angle: + the angle of the excitation unitary + target: + even number of qubit indices interpreted as [0,1,2,3....] = [(0,1), (2,3), ...] + i.e. as qubit excitations from 0 to 1, 2 to 3, etc + control: + possible control qubits + assume_real: + assume the wavefunction on which this acts is always real (cheaper gradients: see https://doi.org/10.1039/D0SC06627C) + + Returns + ------- + QubitExcitation gate wrapped into a tequila circuit + + """ + try: + assert len(target) % 2 == 0 + except: + raise Exception("QubitExcitation: Needs an even number of targets") + + return QCircuit.wrap_gate(QubitExcitationImpl(angle=angle, target=target, assume_real=assume_real, compile_options=compile_options, control=control))
+ + + +""" +Helper Functions +""" + +def _initialize_power_gate(name: str, target: typing.Union[list, int], generator, + control: typing.Union[list, int] = None, power=None, angle=None, *args, **kwargs) -> QCircuit: + target = list_assignment(target) + + # allow angle instead of power in initialization for more consistency + # if angle is given we just convert it + if angle is not None: + angle = assign_variable(angle) + if power is not None: + power = power * angle / np.pi + else: + power = angle / np.pi + + if power is None or power in [1, 1.0]: + gates = [impl.QGateImpl(name=name, target=q, control=control, generator=generator(q)) for q in target] + else: + gates = [impl.PowerGateImpl(name=name, power=power, target=q, control=control, generator=generator(q), *args, **kwargs) for q in + target] + + return QCircuit.wrap_gate(gates) + + +
+[docs] +def RotationGate(axis: int, angle: typing.Union[typing.Hashable, numbers.Number], target: typing.Union[list, int], control: typing.Union[list, int] = None, assume_real=False): + """ + Notes + ---------- + Initialize an abstract rotation gate of the form + + .. math:: + R_{\\text{axis}}(\\text{angle}) = e^{-i\\frac{\\text{angle}}{2} \\sigma_{\\text{axis}}} + + + Parameters + ---------- + axis + integer 1 for x, 2 for y, 3 for z + angle + Hashable type (will be treated as Variable) or Numeric type (static angle) + target + integer or list of integers + control + integer or list of integers + assume_real + enable improved gradient compilation for controlled gates (wavefunction needs to be real) + + Returns + ------- + QCircuit object with this RotationGate + """ + target = list_assignment(target) + gates = [impl.RotationGateImpl(axis=axis, angle=angle, target=q, control=control, assume_real=assume_real) for q in target] + + return QCircuit.wrap_gate(gates)
+ + + +
+[docs] +def PowerGate(name: str, target: typing.Union[list, int], power: float = None, control: typing.Union[list, int] = None, generator: QubitHamiltonian = None, *args, **kwargs): + """ + Initialize a (potentially parametrized) gate which is supported on the backend + + Parameters + ---------- + name: str + name of the gate on the backend (usually, H, X, Y, Z) + target + int or list of int + power + numeric type (fixed exponent) or hashable type (parametrized exponent) + will be interpreted as + angle + similar to power, but will be interpreted as + .. math:: + U=e^{-i\\frac{angle}{2} generator} + control + int or list of int + + Returns + ------- + + """ + return QCircuit.wrap_gate( + impl.PowerGateImpl(name=name, power=power, target=target, control=control, generator=generator, *args, **kwargs))
+ + + +
+[docs] +def QGate(name, target: typing.Union[list, int], control: typing.Union[list, int] = None, + generator: QubitHamiltonian = None): + return QCircuit.wrap_gate(impl.QGateImpl(name=name, target=target, control=control, generator=generator))
+ + +""" +Implementation of specific gates +Not put into _gates_impl.py for convenience +Those gate types will not be recognized by the compiler +and should all implement a compile function that +returns a QCircuit of primitive tq gates +""" + +
+[docs] +class QubitExcitationImpl(impl.GeneralizedRotationImpl): + + def __init__(self, angle, target, generator=None, p0=None, assume_real=True, control=None, compile_options=None): + angle = assign_variable(angle) + + if generator is None: + assert target is not None + assert p0 is None + generator = paulis.I() + p0a = paulis.I() + p0b = paulis.I() + + for i in range(len(target) // 2): + generator *= paulis.Sp(target[2 * i]) * paulis.Sm(target[2 * i + 1]) + p0a *= paulis.Qp(target[2 * i]) * paulis.Qm(target[2 * i + 1]) + p0b *= paulis.Qm(target[2 * i]) * paulis.Qp(target[2 * i + 1]) + generator = (1.0j * (generator - generator.dagger())).simplify() + p0 = paulis.I() - p0a - p0b + else: + assert generator is not None + assert p0 is not None + + super().__init__(name="QubitExcitation", angle=angle, generator=generator, target=target, p0=p0, control=control, assume_real=assume_real, steps=1) + + if compile_options is None: + self.compile_options = "optimize" + elif hasattr(compile_options, "lower"): + self.compile_options = compile_options.lower() + else: + self.compile_options = compile_options + +
+[docs] + def map_qubits(self, qubit_map: dict): + mapped = super().map_qubits(qubit_map) + mapped.p0 = self.p0.map_qubits(qubit_map=qubit_map) + return mapped
+ + +
+[docs] + def compile(self, exponential_pauli=False, *args, **kwargs): + # optimized compiling for single and double qubit excitaitons following arxiv:2005.14475 + # Alternative representation in arxiv:2104.05695 (not implemented -> could be added and controlled with optional compile keywords) + if self.is_controlled(): + control = list(self.control) + else: + control = [] + if self.compile_options == "optimize" and len(self.target) == 2 and exponential_pauli: + p,q = self.target + U0 = X(target=p, control=q) + U1 = Ry(angle=self.parameter, target=q, control=[p]+control) + return U0 + U1 + U0 + elif self.compile_options == "optimize" and len(self.target) == 4 and exponential_pauli: + p,r,q,s = self.target + U0 = X(target=q, control=p) + U0 += X(target=s, control=r) + U0 += X(target=r, control=p) + U0 += X(target=q) + U0 += X(target=s) + U1 = Ry(angle=-self.parameter, target=p, control=[q,r,s]+control) + return U0 + U1 + U0.dagger() + else: + return Trotterized(angle=self.parameter, generator=self.generator, steps=1, control=self.control)
+
+ + + +def _convert_Paulistring(paulistring: typing.Union[PauliString, str, dict]) -> PauliString: + ''' + Function that given a paulistring as PauliString structure or + as string or dict or list, returns the corresponding PauliString + structure. + + + Parameters + ---------- + paulistring : typing.Union[PauliString , str, dict] + given as PauliString structure or as string or dict or list + if given as string: Format should be like X(0)Y(3)Z(2) + if given as list: Format should be like [(0,'X'),(3,'Y'),(2,'Z')] + if given as dict: Format should be like { 0:'X', 3:'Y', 2:'Z' } + + Returns + ------- + ps : PauliString + ''' + + if isinstance(paulistring, str): + ps = PauliString.from_string(string=paulistring) + elif isinstance(paulistring, list): + ps = PauliString.from_openfermion(key=paulistring) + elif isinstance(paulistring, dict): + ps = PauliString(data=paulistring) + else: + ps = paulistring + + return ps + +
+[docs] +def PauliGate(paulistring: typing.Union[PauliString, str, dict], control: typing.Union[list, int] = None, *args, **kwargs) -> QCircuit: + ''' + Functions that converts a Pauli string into the corresponding quantum + circuit. + + Parameters + ---------- + paulistring : typing.Union[PauliString , str, dict] + given as PauliString structure or as string or dict or list + if given as string: Format should be like X(0)Y(3)Z(2) + if given as list: Format should be like [(0,'X'),(3,'Y'),(2,'Z')] + if given as dict: Format should be like { 0:'X', 3:'Y', 2:'Z' } + + control: typing.Union[list, int] : (Default value = None) + control qubits + + Raises + ------ + Exception: Not a Pauli Operator. + + Returns + ------- + U : QCircuit object corresponding to the Pauli string. + + ''' + + ps = _convert_Paulistring(paulistring) + + U = QCircuit() + + for k,v in ps.items(): + if v.lower() == "x": + U += X(target=k, control=control, *args, **kwargs) + elif v.lower() == "y": + U += Y(target=k, control=control, *args, **kwargs) + elif v.lower() == "z": + U += Z(target=k, control=control, *args, **kwargs) + else: + raise Exception("{}???".format(v)) + + return U
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit/gradient.html b/docs/sphinx/_modules/tequila_code/circuit/gradient.html new file mode 100644 index 0000000..cc7ab35 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit/gradient.html @@ -0,0 +1,362 @@ + + + + + + + + tequila_code.circuit.gradient — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit.gradient

+from tequila.circuit.compiler import CircuitCompiler
+from tequila.objective.objective import Objective, ExpectationValueImpl, Variable, \
+    assign_variable, identity, FixedVariable
+from tequila import TequilaException
+from tequila.objective import QTensor
+from tequila.simulators.simulator_api import compile
+import typing
+from numpy import vectorize
+from tequila.autograd_imports import jax, __AUTOGRAD__BACKEND__
+
+
+
+[docs] +def grad(objective: typing.Union[Objective, QTensor], variable: Variable = None, no_compile=False, *args, **kwargs): + ''' + wrapper function for getting the gradients of Objectives,ExpectationValues, Unitaries (including single gates), and Transforms. + :param obj (QCircuit,ParametrizedGateImpl,Objective,ExpectationValue,Transform,Variable): structure to be differentiated + :param variables (list of Variable): parameter with respect to which obj should be differentiated. + default None: total gradient. + return: dictionary of Objectives, if called on gate, circuit, exp.value, or objective; if Variable or Transform, returns number. + ''' + + if variable is None: + # None means that all components are created + variables = objective.extract_variables() + result = {} + + if len(variables) == 0: + raise TequilaException("Error in gradient: Objective has no variables") + + for k in variables: + assert (k is not None) + result[k] = grad(objective, k, no_compile=no_compile) + return result + else: + variable = assign_variable(variable) + + + if isinstance(objective, QTensor): + f = lambda x: grad(objective=x, variable=variable, *args, **kwargs) + ff = vectorize(f) + return ff(objective) + + if variable not in objective.extract_variables(): + return Objective() + + # objective translation + # if the objective was already translated to a backend + # we need to reverse that here + if objective.is_translated(): + raise TequilaException("\n\ngradient of:{}\ncan not form gradient that was already compiled to a quantum backend\ntq.grad neds to be applied to the abstract - non compiled objective\nE.g. for the (compiled) objective E1 \n\tE1 = tq.compile(E0)\ninstead of doing\n\tdE = tq.grad(E1)\ndo\n\tdE = tq.grad(E0)\nand compile dE afterwards (if wanted) with\n\tdE = tq.compile(dE)\n".format(str(objective))) + + + # circuit compilation + if no_compile: + compiled = objective + else: + compiler = CircuitCompiler(multitarget=True, + trotterized=True, + hadamard_power=True, + power=True, + controlled_phase=True, + controlled_rotation=True, + gradient_mode=True) + + compiled = compiler(objective, variables=[variable]) + + if variable not in compiled.extract_variables(): + raise TequilaException("Error in taking gradient. Objective does not depend on variable {} ".format(variable)) + + if isinstance(objective, ExpectationValueImpl): + return __grad_expectationvalue(E=objective, variable=variable) + elif objective.is_expectationvalue(): + return __grad_expectationvalue(E=compiled.args[-1], variable=variable) + elif isinstance(compiled, Objective) or (hasattr(compiled, "args") and hasattr(compiled, "transformation")): + return __grad_objective(objective=compiled, variable=variable) + else: + raise TequilaException("Gradient not implemented for other types than ExpectationValue and Objective.")
+ + + +def __grad_objective(objective: Objective, variable: Variable): + args = objective.args + transformation = objective.transformation + dO = None + + processed_expectationvalues = {} + for i, arg in enumerate(args): + if __AUTOGRAD__BACKEND__ == "jax": + df = jax.grad(transformation, argnums=i) + elif __AUTOGRAD__BACKEND__ == "autograd": + df = jax.grad(transformation, argnum=i) + else: + raise TequilaException("Can't differentiate without autograd or jax") + + # We can detect one simple case where the outer derivative is const=1 + if transformation is None or transformation == identity: + outer = 1.0 + else: + outer = Objective(args=args, transformation=df) + + if hasattr(arg, "U"): + # save redundancies + if arg in processed_expectationvalues: + inner = processed_expectationvalues[arg] + else: + inner = __grad_inner(arg=arg, variable=variable) + processed_expectationvalues[arg] = inner + else: + # this means this inner derivative is purely variable dependent + inner = __grad_inner(arg=arg, variable=variable) + + if inner == 0.0: + # don't pile up zero expectationvalues + continue + + if dO is None: + dO = outer * inner + else: + dO = dO + outer * inner + + if dO is None: + raise TequilaException("caught None in __grad_objective") + return dO + + +# def __grad_vector_objective(objective: Objective, variable: Variable): +# argsets = objective.argsets +# transformations = objective._transformations +# outputs = [] +# for pos in range(len(objective)): +# args = argsets[pos] +# transformation = transformations[pos] +# dO = None +# +# processed_expectationvalues = {} +# for i, arg in enumerate(args): +# if __AUTOGRAD__BACKEND__ == "jax": +# df = jax.grad(transformation, argnums=i) +# elif __AUTOGRAD__BACKEND__ == "autograd": +# df = jax.grad(transformation, argnum=i) +# else: +# raise TequilaException("Can't differentiate without autograd or jax") +# +# # We can detect one simple case where the outer derivative is const=1 +# if transformation is None or transformation == identity: +# outer = 1.0 +# else: +# outer = Objective(args=args, transformation=df) +# +# if hasattr(arg, "U"): +# # save redundancies +# if arg in processed_expectationvalues: +# inner = processed_expectationvalues[arg] +# else: +# inner = __grad_inner(arg=arg, variable=variable) +# processed_expectationvalues[arg] = inner +# else: +# # this means this inner derivative is purely variable dependent +# inner = __grad_inner(arg=arg, variable=variable) +# +# if inner == 0.0: +# # don't pile up zero expectationvalues +# continue +# +# if dO is None: +# dO = outer * inner +# else: +# dO = dO + outer * inner +# +# if dO is None: +# dO = Objective() +# outputs.append(dO) +# if len(outputs) == 1: +# return outputs[0] +# return outputs + + +def __grad_inner(arg, variable): + ''' + a modified loop over __grad_objective, which gets derivatives + all the way down to variables, return 1 or 0 when a variable is (isnt) identical to var. + :param arg: a transform or variable object, to be differentiated + :param variable: the Variable with respect to which par should be differentiated. + :ivar var: the string representation of variable + ''' + + assert (isinstance(variable, Variable)) + if isinstance(arg, Variable): + if arg == variable: + return 1.0 + else: + return 0.0 + elif isinstance(arg, FixedVariable): + return 0.0 + elif isinstance(arg, ExpectationValueImpl): + return __grad_expectationvalue(arg, variable=variable) + elif hasattr(arg, "abstract_expectationvalue"): + E = arg.abstract_expectationvalue + dE = __grad_expectationvalue(E, variable=variable) + return compile(dE, **arg._input_args) + else: + return __grad_objective(objective=arg, variable=variable) + + +def __grad_expectationvalue(E: ExpectationValueImpl, variable: Variable): + ''' + implements the analytic partial derivative of a unitary as it would appear in an expectation value. See the paper. + :param unitary: the unitary whose gradient should be obtained + :param variables (list, dict, str): the variables with respect to which differentiation should be performed. + :return: vector (as dict) of dU/dpi as Objective (without hamiltonian) + ''' + + hamiltonian = E.H + unitary = E.U + if not (unitary.verify()): + raise TequilaException("error in grad_expectationvalue unitary is {}".format(unitary)) + + # fast return if possible + if variable not in unitary.extract_variables(): + return 0.0 + + param_gates = unitary._parameter_map[variable] + + dO = Objective() + for idx_g in param_gates: + idx, g = idx_g + dOinc = __grad_shift_rule(unitary, g, idx, variable, hamiltonian) + dO += dOinc + + assert dO is not None + return dO + + +def __grad_shift_rule(unitary, g, i, variable, hamiltonian): + ''' + function for getting the gradients of directly differentiable gates. Expects precompiled circuits. + :param unitary: QCircuit: the QCircuit object containing the gate to be differentiated + :param g: a parametrized: the gate being differentiated + :param i: Int: the position in unitary at which g appears + :param variable: Variable or String: the variable with respect to which gate g is being differentiated + :param hamiltonian: the hamiltonian with respect to which unitary is to be measured, in the case that unitary + is contained within an ExpectationValue + :return: an Objective, whose calculation yields the gradient of g w.r.t variable + ''' + + # possibility for overwride in custom gate construction + if hasattr(g, "shifted_gates"): + inner_grad = __grad_inner(g.parameter, variable) + shifted = g.shifted_gates() + dOinc = Objective() + for x in shifted: + w, g = x + Ux = unitary.replace_gates(positions=[i], circuits=[g]) + wx = w * inner_grad + Ex = Objective.ExpectationValue(U=Ux, H=hamiltonian) + dOinc += wx * Ex + return dOinc + else: + raise TequilaException('No shift found for gate {}\nWas the compiler called?'.format(g)) +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit/noise.html b/docs/sphinx/_modules/tequila_code/circuit/noise.html new file mode 100644 index 0000000..6f99a09 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit/noise.html @@ -0,0 +1,443 @@ + + + + + + + + tequila_code.circuit.noise — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit.noise

+import typing
+from tequila.tools import list_assignment
+from tequila.utils import TequilaException
+import copy
+
+names_dict = {
+    'x': 'x',
+    'y': 'y',
+    'z': 'z',
+    'h': 'h',
+    'rx': 'r',
+    'ry': 'r',
+    'rz': 'r',
+    'r': 'r',
+    'phase': 'r',
+    'single': 'single',
+    'swap': 'control',
+    'cx': 'control',
+    'cy': 'control',
+    'cz': 'control',
+    'crx': 'control',
+    'cry': 'control',
+    'crz': 'control',
+    'control': 'control',
+    'cnot': 'control',
+    'ccnot': 'multicontrol',
+    'multicontrol': 'multicontrol'
+}
+
+noises_available=['bit flip','phase flip','phase damp','amplitude damp','phase-amplitude damp','depolarizing']
+krausses=['bit flip','phase flip','phase damp','amplitude damp','phase-amplitude damp','depolarizing']
+
+
+[docs] +class QuantumNoise: + """ + class representing a specific quantum noise operation on gates of a certain number of qubits. + + Attributes + ---------- + name: + what noise to apply + probs: + the probabilities with which to apply the noise + level: + the number of qubits in the gates this noise acts upon + + Methods + ------- + from_dict: + initialize from a dictionary. + """ + prob_length={ + 'bit flip':1, + 'phase flip':1, + 'phase damp':1, + 'amplitude damp':1, + 'phase-amplitude damp':2, + 'depolarizing':1 + } + + @property + def name(self): + return self._name + + @property + def level(self): + return self._level + + def __init__(self,name:str,probs:typing.List[float],level:int): + """ + + Parameters + ---------- + name: str + what the name of the noise is. Determines how many probabilites are needed additionally. + probs: list: + a list of probabilities with which to apply the requested noise + level: int: + the number of qubits in the gates this noise acts upon. + """ + probs=list_assignment(probs) + if name not in noises_available: + raise TequilaException('The name you asked for, {}, is not recognized'.format(name)) + self._name=name + self._level=int(level) + + if len(probs) != self.prob_length[name]: + raise TequilaException('{} noise requires {} probabilities; recieved {}'.format(name, self.prob_length[name], len(probs))) + if name in krausses: + assert sum(probs)<=1. + self.probs=list_assignment(probs) + + def __str__(self): + back=self.name + back+=' on ' + str(self._level) + ' qubit gates' + back+=', probs = ' +str(self.probs) + return back + +
+[docs] + @staticmethod + def from_dict(d): + if type(d) is dict: + return QuantumNoise(**d) + elif type(d) is QuantumNoise: + return d + else: + raise TequilaException('object provided is neither a dictionary nor a QuantumNoise.')
+
+ + + +
+[docs] +class NoiseModel(): + """ + class representing noises to apply to a quantum circuit during simulation. + + Attributes + ---------- + noises: + a list of all the noises to apply. + + Methods + ------- + without_noise_on_level: + remove all noise affecting operations with <level> qubits. + without_noise_op: + remove all noise of a given type, I.E get rid of all bit flips. + + """ + def __init__(self, noises: typing.List[typing.Union[dict, QuantumNoise]]=None): + if noises is None: + self.noises = [] + else: + self.noises=[QuantumNoise.from_dict(d) for d in list_assignment(noises)] + + def __str__(self): + back='NoiseModel with: \n' + for noise in self.noises: + back += str(noise) + back += ',\n' + return back + + def __add__(self, other): + new=NoiseModel() + new.noises+=self.noises + if type(other) is dict: + new.noises.append(QuantumNoise.from_dict(other)) + elif type(other) is QuantumNoise: + new.noises.append(other) + elif hasattr(other,'noises'): + new.noises.extend(copy.copy(other.noises)) + return new + + def __iadd__(self, other): + if type(other) is dict: + self.noises+=QuantumNoise.from_dict(other) + elif hasattr(other,'noises'): + self.noises.extend(copy.copy(other.noises)) + return self + +
+[docs] + def without_noise_on_level(self, level): + new = NoiseModel() + for noise in self.noises: + if noise.level == level: + pass + else: + new.noises.append(noise) + return new
+ + +
+[docs] + def without_noise_op(self, name): + new = NoiseModel() + for noise in self.noises: + if noise.name == name: + pass + else: + new.noises.append(noise) + return new
+ + +
+[docs] + @staticmethod + def wrap_noise(other): + return NoiseModel(noises=other)
+
+ + +
+[docs] +def BitFlip(p:float,level:int): + """ + Returns a NoiseModel with one QuantumNoise, having a kraus map corresponding to applying pauli X with likelihood p. + + Parameters + ---------- + p: float: + the probability with which the noise is applied. + level: int: + the # of qubits in operations to apply this noise to. + + Returns + ------- + NoiseModel + """ + + new=NoiseModel.wrap_noise(QuantumNoise(name='bit flip', probs=list_assignment(p), level=level)) + return new
+ + +
+[docs] +def PhaseFlip(p:float,level:int): + ''' + Returns a NoiseModel of one QuantumNoise, having a kraus map corresponding to applying pauli Z with likelihood p. + + Parameters + ---------- + p: float: + the probability with which the noise is applied. + level: int: + the # of qubits in operations to apply this noise to. + + Returns + ------- + NoiseModel + ''' + + new=NoiseModel.wrap_noise(QuantumNoise(name='phase flip', probs=list_assignment(p), level=level)) + return new
+ + + +
+[docs] +def PhaseDamp(p:float,level:int): + ''' + Returns a NoiseModel of one QuantumNoise, having a kraus map corresponding to phase damping; + Krauss map is defined following Nielsen and Chuang; + E_0= [[1,0], + [0,sqrt(1-p)]] + E_1= [[0,0], + [0,sqrt(p)]] + + Parameters + ---------- + p: float: + the probability with which the noise is applied. + level: int: + the # of qubits in operations to apply this noise to. + + Returns + ------- + NoiseModel + ''' + + new=NoiseModel.wrap_noise(QuantumNoise(name='phase damp', probs=list_assignment(p), level=level)) + return new
+ + + +
+[docs] +def AmplitudeDamp(p:float,level:int): + ''' + Returns a NoiseModel one QuantumNoise, corresponding to amplitude damping. + this channel takes 1 to 0, but leaves 0 unaffected. + kraus maps: + + E_0= [[1,0], + [0,sqrt(1-p)]] + E_1= [[0,sqrt(p)], + [0,0]] + + Parameters + ---------- + p: float: + the probability with which the noise is applied. + level: int: + the # of qubits in operations to apply this noise to. + + Returns + ------- + NoiseModel + ''' + + new=NoiseModel.wrap_noise(QuantumNoise(name='amplitude damp', probs=list_assignment(p), level=level)) + return new
+ + +
+[docs] +def PhaseAmplitudeDamp(p1:float,p2:float,level:int): + ''' + Returns a NoiseModel with one QuantumNoise, having a kraus map corresponding to phase and amplitude damping. + + Parameters + ---------- + p1: float: + the probability with which phase is damped + p2: float: + the probability with which amplitude is damped + level: int: + the # of qubits in operations to apply this noise to. + + Returns + ------- + NoiseModel + ''' + new=NoiseModel.wrap_noise(QuantumNoise(name='phase-amplitude damp', probs=list_assignment([p1, p2]), level=level)) + return new
+ + +
+[docs] +def DepolarizingError(p:float,level:int): + ''' + Returns a NoiseModel with one QuantumNoise, having a kraus map corresponding to equal + probabilities of each of the three pauli matrices being applied. + + Parameters + ---------- + p: float: + the probability with which the noise is applied. + level: int: + the # of qubits in operations to apply this noise to. + + Returns + ------- + NoiseModel + ''' + new = NoiseModel.wrap_noise(QuantumNoise(name='depolarizing', probs=list_assignment(p), level=level)) + return new
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit/pyzx.html b/docs/sphinx/_modules/tequila_code/circuit/pyzx.html new file mode 100644 index 0000000..f2c11d4 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit/pyzx.html @@ -0,0 +1,160 @@ + + + + + + + + tequila_code.circuit.pyzx — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit.pyzx

+"""
+Add to tequila the ability to make ZX-Calculus
+
+Using the pyzx library: https://github.com/Quantomatic/pyzx
+"""
+
+HAS_PYZX = True
+try:
+    import pyzx
+    HAS_PYZX = True
+except ImportError:
+    HAS_PYZX = False
+
+from tequila import TequilaException
+from tequila import export_open_qasm, import_open_qasm
+from tequila.circuit import QCircuit
+
+
+
+[docs] +def convert_to_pyzx(circuit: QCircuit, variables=None): + """ + Allow convert from Tequila circuit to pyzx circuit + + Args: + circuit: in Tequila format to be exported to pyzx + variables: optional dictionary with values for variables + + Returns: + pyzx.circuit.Circuit: pyzx circuit + """ + if HAS_PYZX: + return pyzx.circuit.Circuit.from_qasm(export_open_qasm(circuit=circuit, variables=variables, version="2.0", zx_calculus=True)) + else: + raise TequilaException("Pyzx package not installed.")
+ + + +
+[docs] +def convert_from_pyzx(circuit) -> QCircuit: + """ + Allow convert from pyzx circuit to Tequila circuit + + Args: + circuit: in pyzx format (pyzx.circuit.Circuit) to be exported to Tequila circuit + + Returns: + QCircuit: Tequila circuit + """ + if HAS_PYZX: + if isinstance(circuit, pyzx.circuit.Circuit): + return import_open_qasm(circuit.to_qasm(), version="2.0") + else: + raise TequilaException("Circuit provided must be of type pyzx.circuit.Circuit") + else: + raise TequilaException("Pyzx package not installed.")
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit/qasm.html b/docs/sphinx/_modules/tequila_code/circuit/qasm.html new file mode 100644 index 0000000..fe25e33 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit/qasm.html @@ -0,0 +1,573 @@ + + + + + + + + tequila_code.circuit.qasm — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit.qasm

+"""
+Export QCircuits as qasm code
+
+OPENQASM version 2.0 specification from:
+A. W. Cross, L. S. Bishop, J. A. Smolin, and J. M. Gambetta, e-print arXiv:1707.03429v2 [quant-ph] (2017).
+https://arxiv.org/pdf/1707.03429v2.pdf
+"""
+from tequila import TequilaException
+from tequila.circuit import QCircuit
+from tequila.circuit.compiler import CircuitCompiler
+import tequila.circuit.gates as gates
+from numpy import pi
+from typing import Dict
+import typing
+
+
+
+[docs] +def export_open_qasm(circuit: QCircuit, variables=None, version: str = "2.0", filename: str = None, zx_calculus: bool = False) -> str: + """ + Allow export to different versions of OpenQASM + + Args: + circuit: to be exported to OpenQASM + variables: optional dictionary with values for variables + version: of the OpenQASM specification, optional + filename: optional file name to save the generated OpenQASM code + zx_calculus: indicate if y-gates must be transformed to xz equivalents + + Returns: + str: OpenQASM string + """ + + if version == "2.0": + result = convert_to_open_qasm_2(circuit=circuit, variables=variables, zx_calculus=zx_calculus) + else: + return "Unsupported OpenQASM version : " + version + # TODO: export to version 3 + + if filename is not None: + with open(filename, "w") as file: + file.write(result) + file.close() + + return result
+ + + +
+[docs] +def import_open_qasm(qasm_code: str, version: str = "2.0", rigorous: bool = True) -> QCircuit: + """ + Allow import from different versions of OpenQASM + + Args: + qasm_code: string with the OpenQASM code + version: of the OpenQASM specification, optional + rigorous: indicates whether the QASM code should be read rigorously + + Returns: + QCircuit: equivalent to the OpenQASM code received + """ + + if version == "2.0": + result = parse_from_open_qasm_2(qasm_code=qasm_code, rigorous=rigorous) + else: + return "Unsupported OpenQASM version : " + version + # TODO: export to version 3 + + return result
+ + + +
+[docs] +def import_open_qasm_from_file(filename: str, version: str = "2.0", rigorous: bool = True) -> QCircuit: + """ + Allow import from different versions of OpenQASM from a file + + Args: + filename: string with the file name with the OpenQASM code + variables: optional dictionary with values for variables + version: of the OpenQASM specification, optional + rigorous: indicates whether the QASM code should be read rigorously + + Returns: + QCircuit: equivalent to the OpenQASM code received + """ + + with open(filename, "r") as file: + qasm_code = file.read() + file.close() + + return import_open_qasm(qasm_code, version=version, rigorous=rigorous)
+ + + +
+[docs] +def convert_to_open_qasm_2(circuit: QCircuit, variables=None, zx_calculus: bool = False) -> str: + """ + Allow export to OpenQASM version 2.0 + + Args: + circuit: to be exported to OpenQASM + variables: optional dictionary with values for variables + zx_calculus: indicate if y-gates must be transformed to xz equivalents + + Returns: + str: OpenQASM string + """ + + if variables is None and not (len(circuit.extract_variables()) == 0): + raise TequilaException( + "You called export_open_qasm for a parametrized type but forgot to pass down the variables: {}".format( + circuit.extract_variables())) + + compiler = CircuitCompiler(multitarget=True, + multicontrol=False, + trotterized=True, + generalized_rotation=True, + exponential_pauli=True, + controlled_exponential_pauli=True, + hadamard_power=True, + controlled_power=True, + power=True, + toffoli=True, + controlled_phase=True, + phase=True, + phase_to_z=True, + controlled_rotation=True, + swap=True, + cc_max=True, + gradient_mode=False, + ry_gate=zx_calculus, + y_gate=zx_calculus, + ch_gate=zx_calculus) + + compiled = compiler(circuit, variables=None) + + result = "OPENQASM 2.0;\ninclude \"qelib1.inc\";\n" + + qubits_names: Dict[int, str] = {} + for q in compiled.qubits: + name = "q[" + str(q) + "]" + qubits_names[q] = name + + result += "qreg q[" + str(compiled.n_qubits) + "];\n" + result += "creg c[" + str(compiled.n_qubits) + "];\n" + + for g in compiled.gates: + + control_str = '' + if g.is_controlled(): + + if len(g.control) > 2: + raise TequilaException( + "Multi-controls beyond 2 not yet supported for OpenQASM 2.0. Gate was:\n{}".format(g)) + + controls = list(map(lambda c: qubits_names[c], g.control)) + control_str = ','.join(controls) + ',' + + gate_name = name_and_params(g, variables) + for t in g.target: + result += gate_name + result += control_str + result += qubits_names[t] + result += ";\n" + + return result
+ + + +
+[docs] +def name_and_params(g, variables): + """ + Determines the quantum gate name and its parameters if applicable + + Args: + g: gate to get its name + variables: dictionary with values for variables + + Returns: + str: name (and parameter) to the gate specified + """ + + res = "" + + for c in range(len(g.control)): + res += "c" + + res += g.name.lower() + + if hasattr(g, "parameter") and g.parameter is not None: + res += "(" + str(g.parameter(variables)) + ")" + + res += " " + + return res
+ + + +
+[docs] +def parse_from_open_qasm_2(qasm_code: str, rigorous: bool = True) -> QCircuit: + + lines = qasm_code.splitlines() + clean_code = [] + # ignore comments + for line in lines: + if line.find("//") != -1: + clean_line = line[0:line.find("//")].strip() + else: + clean_line = line.strip() + if clean_line: + clean_code.append(clean_line) + + if clean_code[0].startswith("OPENQASM"): + clean_code.pop(0) + elif rigorous: + raise TequilaException("File must start with the 'OPENQASM' directive") + + if clean_code[0].startswith('include "qelib1.inc";'): + clean_code.pop(0) + elif rigorous: + raise TequilaException("File must import standard library (qelib1.inc)") + + code_circuit = "\n".join(clean_code) + # separate the custom command definitions from the normal commands + custom_gates_map: Dict[str, QCircuit] = {} + while True: + i = code_circuit.find("gate ") + if i == -1: + break + j = code_circuit.find("}", i) + custom_name, custom_circuit = parse_custom_gate(code_circuit[i:j + 1], custom_gates_map=custom_gates_map) + custom_gates_map[custom_name] = custom_circuit + code_circuit = code_circuit[:i] + code_circuit[j + 1:] + + # parse regular commands + commands = [s.strip() for s in code_circuit.split(";") if s.strip()] + qregisters: Dict[str, int] = {} + + circuit = QCircuit() + for c in commands: + partial_circuit = parse_command(command=c, custom_gates_map=custom_gates_map, qregisters=qregisters) + if partial_circuit is not None: + circuit += partial_circuit + + return circuit
+ + + +
+[docs] +def parse_custom_gate(gate_custom: str, custom_gates_map: Dict[str, QCircuit]) -> (str, QCircuit): + """ + Parse custom gates code + + Args: + gate_custom: code with custom gates + """ + gate_custom = gate_custom[5:] + spec, body = gate_custom.split("{", 1) + + if "(" in spec: + i = spec.find("(") + j = spec.find(")") + if spec[i + 1:j].strip(): + raise TequilaException("Parameters for custom gates not supported: {}".format(spec)) + spec = spec[:i] + spec[j + 1:] + + spec = spec.strip() + + if " " in spec: + name, qargs = spec.split(" ", 1) + name = name.strip() + qargs = qargs.strip() + else: + raise TequilaException("Custom gate specification doesn't have any arguments: {}".format(spec)) + + custom_qregisters: Dict[str, int] = {} + for qarg in qargs.split(','): + custom_qregisters[qarg] = len(custom_qregisters) + + body = body[:-1].strip() + commands = [s.strip() for s in body.split(";") if s.strip()] + + custom_circuit = QCircuit() + for c in commands: + partial_circuit = parse_command(command=c, custom_gates_map=custom_gates_map, qregisters=custom_qregisters) + if partial_circuit is not None: + custom_circuit += partial_circuit + + return name, custom_circuit
+ + + +
+[docs] +def parse_command(command: str, custom_gates_map: Dict[str, QCircuit], qregisters: Dict[str, int]) -> QCircuit: + """ + Parse qasm code command + + Args: + command: open qasm code to be parsed + custom_gates_map: map with custom gates + """ + + name, rest = command.split(" ", 1) + + if name in ("barrier", "creg", "measure", "id"): + return None + if name in ("opaque", "if"): + raise TequilaException("Unsupported operation {}".format(command)) + + args = [s.strip() for s in rest.split(",") if s.strip()] + + if name == "qreg": + regname, sizep = args[0].split("[", 1) + size = int(sizep[:-1]) + for i in range(size): + qregisters[regname + "[" + str(i) + "]"] = len(qregisters) + return None + + for arg in args: + if not (arg in qregisters or arg in [key.split("[",1)[0] for key in qregisters.keys()]): + raise TequilaException("Invalid register {}".format(arg)) + + if name in custom_gates_map: + custom_circuit = custom_gates_map[name] + qregisters_values = [] + for a in args: + qregisters_values.append(get_qregister(a, qregisters)) + return apply_custom_gate(custom_circuit=custom_circuit, qregisters_values=qregisters_values) + + if name in ("x", "y", "z", "h", "cx", "cy", "cz", "ch"): + target = get_qregister(args[0], qregisters) + control = None + if name[0].lower() == 'c': + control = get_qregister(args[0], qregisters) + target = get_qregister(args[1], qregisters) + name = name[1] + G = getattr(gates, name.upper()) + return G(control=control, target=target) + + if name in ("ccx", "ccy", "ccz"): + G = getattr(gates, name[2].upper()) + control = [get_qregister(args[0], qregisters), get_qregister(args[1], qregisters)] + target = get_qregister(args[2], qregisters) + return G(control=control, target=target) + + if name.startswith("rx(") or name.startswith("ry(") or name.startswith("rz(") or \ + name.startswith("crx(") or name.startswith("cry(") or name.startswith("crz("): + angle = get_angle(name)[0] + i = name.find('(') + name = name[0:i] + name = name.upper() + name = [x for x in name] + name[-1] = name[-1].lower() + name = "".join(name) + G = getattr(gates, name) + return G(angle=angle,control=get_qregister(args[0], qregisters) if name[0] == 'C' else None,target=get_qregister(args[1 if name[0] == 'C' else 0], qregisters)) + + if name.startswith("U("): + angles = get_angle(name) + return gates.U(theta=angles[0], phi=angles[1], lambd=angles[2], + control=None, + target=get_qregister(args[0], qregisters)) + if name.startswith("u1("): + angles = get_angle(name) + return gates.u1(lambd=angles[0], + control=None, + target=get_qregister(args[0], qregisters)) + if name.startswith("u2("): + angles = get_angle(name) + return gates.u2(phi=angles[0], lambd=angles[1], + control=None, + target=get_qregister(args[0], qregisters)) + if name.startswith("u3("): + angles = get_angle(name) + return gates.u3(theta=angles[0], phi=angles[1], lambd=angles[2], + control=None, + target=get_qregister(args[0], qregisters)) + if name.startswith("cu1("): + angles = get_angle(name) + return gates.u1(lambd=angles[0], + control=get_qregister(args[0], qregisters), + target=get_qregister(args[1], qregisters)) + if name.startswith("cu2("): + angles = get_angle(name) + return gates.u2(phi=angles[0], lambd=angles[1], + control=get_qregister(args[0], qregisters), + target=get_qregister(args[1], qregisters)) + if name.startswith("cu3("): + angles = get_angle(name) + return gates.u3(theta=angles[0], phi=angles[1], lambd=angles[2], + control=get_qregister(args[0], qregisters), + target=get_qregister(args[1], qregisters)) + if name in ("s", "t", "sdg", "tdg"): + g = gates.Phase(angle=pi / (2 if name.startswith("s") else 4), + control=None, + target=get_qregister(args[0], qregisters)) + if name.find("dg") != -1: + g = g.dagger() + return g
+ + + +
+[docs] +def apply_custom_gate(custom_circuit: QCircuit, qregisters_values: list) -> QCircuit: + applied_custom_circuit = QCircuit() + for gate in custom_circuit.gates: + g = gate.copy() + g._target = tuple([qregisters_values[i] for i in gate._target]) + g._control = tuple([qregisters_values[i] for i in gate._control]) if gate.is_controlled() else gate._control + applied_custom_circuit += g + return applied_custom_circuit
+ + + +
+[docs] +def get_qregister(qreg: str, qregisters: Dict[str, int]) -> typing.Union[list, int]: + if qreg == qreg.split("[", 1)[0]: + qreg_tequila = [qregisters[key] for key in qregisters.keys() if qreg == key.split("[", 1)[0]] + else: + qreg_tequila = qregisters[qreg] + return qreg_tequila
+ + +
+[docs] +def get_angle(name: str) -> list: + i = name.find('(') + j = name.find(')') + if j == -1: + raise TequilaException("Invalid specification {}".format(name)) + angles_str = name[i+1:j].split(',') + angles = [] + for angle in angles_str: + try: + phase = float(angle) + except ValueError: + if angle.find('pi') == -1: + raise TequilaException("Invalid specification {}".format(name)) + angle = angle.replace('pi', '') + try: + sign = 1 + div = 1 + if angle.find('-') != -1: + angle = angle.replace('-', '') + sign = -1 + if angle.find('/') != -1: + div = float(angle[angle.index('/')+1:]) + angle = angle[:angle.index('/')] + if angle.find('*') != -1: + angle = angle.replace('*', '') + phase = sign * float(angle) * pi / div + elif len(angle) == 0: + phase = sign * pi / div + else: + phase = sign * float(angle) / div + except ValueError: + raise TequilaException("Invalid specification {}".format(name)) + angles.append(phase) + return angles
+ + +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/circuit/qpic.html b/docs/sphinx/_modules/tequila_code/circuit/qpic.html new file mode 100644 index 0000000..e51a976 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/circuit/qpic.html @@ -0,0 +1,372 @@ + + + + + + + + tequila_code.circuit.qpic — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.circuit.qpic

+"""
+Export QCircuits as qpic files
+https://github.com/qpic/qpic/blob/master/doc/qpic_doc.pdf
+"""
+
+from tequila.objective.objective import FixedVariable
+
+import subprocess, numpy
+from shutil import which
+
+import numbers
+
+system_has_qpic = which("qpic") is not None
+system_has_pdflatex = which("pdflatex") is not None
+
+
+
+[docs] +def assign_name(parameter): + if isinstance(parameter, tuple): + return "\\theta" + if hasattr(parameter, "extract_variables"): + return repr(parameter.extract_variables()).lstrip('[').rstrip(']') + if isinstance(parameter, FixedVariable): + for i in [1, 2, 3, 4]: + if numpy.isclose(numpy.abs(float(parameter)), numpy.pi / i, atol=1.e-4): + if float(parameter) < 0.0: + return "-\\pi/{}".format(i) + else: + return "+\\pi/{}".format(i) + return "{:+2.4f}".format(float(parameter)) + + try: + return repr(parameter) + except: + return str(parameter)
+ + + +
+[docs] +def export_to_qpic(circuit, filename=None, filepath=None, always_use_generators=True, + decompose_control_generators=False, + group_together=False, qubit_names=None, mark_parametrized_gates=True, gatecolor1="tq", + textcolor1="white", gatecolor2="guo", textcolor2="black", *args, **kwargs) -> str: + result = "" + + colors = [{"name": "tq", "rgb": (0.03137254901960784, 0.1607843137254902, 0.23921568627450981)}] + colors += [{"name": "guo", "rgb": (0.988, 0.141, 0.757)}] + + # define colors as list of dictionaries with "name":str, "rgb":tuple entries + if "colors" in kwargs: + colors += kwargs["colors"] + + for color in colors: + result += "COLOR {} {} {} {}\n".format(color["name"], *tuple(color["rgb"])) + + if group_together is True: + group_together = "TOUCH" + # define wires + names = dict() + if qubit_names is None: + qubit_names = circuit.qubits + if isinstance(qubit_names, str): + qubit_names = [qubit_names for i in range(len(circuit.qubits))] + for i, q in enumerate(circuit.qubits): + name = "a" + str(q) + names[q] = name + result += name + " W " + str(qubit_names[i]) + "\n" + + for g in circuit.gates: + gcol = gatecolor1 + tcol = textcolor1 + param = None + if hasattr(g, "parameter"): + if not isinstance(g.parameter, numbers.Number) and mark_parametrized_gates: + tcol = textcolor2 + gcol = gatecolor2 + param = g.parameter + + if isinstance(param, numbers.Number): + param = "{:1.2f}".format(param) + + # special gates + # generator decomposition of H is misleading + if g.name in ["H", "h"]: + for target in g.target: + result += " a{qubit} G:fill={gcol} \\textcolor{tcol}{{{op}}} ".format(qubit=target, gcol=gcol, + tcol="{" + tcol + "}", op="H") + if g.is_controlled(): + for c in g.control: + result += names[c] + " " + elif always_use_generators and g.make_generator(include_controls=decompose_control_generators) is not None: + for ps in g.make_generator(include_controls=decompose_control_generators).paulistrings: + if len(ps) == 0: continue + + # if controls are not decomposed this will become a mess + # so we will represent NOT gates as + (and not as X) + # and will use standard notation for Y and H + if not decompose_control_generators and g.name.upper() in ["X", "Y", "Z", "H"]: + if g.name.upper() == "X": + result += " a{qubit} P:fill={gcol} \\textcolor{tcol}{{{op}}} ".format(qubit=g.target[0], + gcol=gcol, + tcol="{" + tcol + "}", + op="+") + else: + result += " a{qubit} G:fill={gcol} \\textcolor{tcol}{{{op}}} ".format(qubit=g.target[0], + gcol=gcol, + tcol="{" + tcol + "}", + op=g.name.upper()) + else: + for k, v in ps.items(): + result += " a{qubit} P:fill={gcol} \\textcolor{tcol}{{{op}}} ".format(qubit=k, gcol=gcol, + tcol="{" + tcol + "}", + op=v.upper()) + if g.is_controlled() and not decompose_control_generators: + for c in g.control: + result += names[c] + " " + result += "\n" + if hasattr(group_together, "upper"): + for t in circuit.qubits: + result += "a{} ".format(t) + result += "{}\n".format(group_together.upper()) + + else: + if g.name.upper() in ["Exp-Pauli".upper(), "GenRot".upper()]: + # represent ExpPaulis as generators + for ps in g.generator.paulistrings: + if len(ps) == 0: continue + for k, v in ps.items(): + result += " a{qubit} P:fill={gcol} \\textcolor{tcol}{{{op}}} ".format(qubit=k, gcol=gcol, + tcol="{" + tcol + "}", + op=v.upper()) + if g.is_controlled(): + for c in g.control: + result += names[c] + " " + result += "\n" + else: + for t in g.target: + result += names[t] + " G:fill={gcol} ".format(gcol=gcol) + gname=g.name + if "R" in gname.upper(): + gname=gname.replace("R", "R_") + + if param is not None: + gname="{{{x}}}({angle})".format(x=gname, angle=assign_name(g.parameter)) + + result += "\\textcolor{tcol}{{${op}$}} ".format(tcol="{" + tcol + "}", op=gname) + if hasattr(g, "parameter") and g.parameter is not None: + result += "width=" + str(25 + 5 * len(assign_name(g.parameter))) + " " + + if g.is_controlled(): + for c in g.control: + result += names[c] + " " + + result += "\n" + + if filename is not None: + filenamex = filename + if not filenamex.endswith(".qpic"): + filenamex = filename + ".qpic" + if filepath is not None: + filenamex = "{}/{}".format(filepath, filenamex) + with open(filenamex, "w") as file: + file.write(result) + return result
+ + + +
+[docs] +def export_to(circuit, + filename: str, + style="tequila", + qubit_names: list = None, *args, **kwargs): + """ + Parameters + ---------- + circuit: + the tequila circuit to export + filename: + filename.filetype, e.g. my_circuit.pdf, my_circuit.png (everything that qpic supports) + style: + string keyword (tequila, standard, generators) or dictionary containing the following keys: + always_use_generators: represent all gates with their generators + decompose_control_generators: Decompose the controls to generators. Effective only in combination with always_use_generators=True. + group_together: Keep PauliStrings from the same generator together. Effective only in combination with always_use_generators=True. + possible values: False, True, 'TOUCH' and 'BARRIER'. True is the same as TOUCH. + BARRIER will create a visible barrier in qpic + args + kwargs + + Returns + ------- + + """ + if not system_has_qpic: + raise Exception("You need qpic in order to export circuits to pictures ---\n pip install qpic") + if "." not in filename: + raise Exception("export_to: No filetype given {}, expected something like {}.pdf".format(filename, filename)) + + if style is None or style == "tequila": + style = { + 'decompose_control_generators': False, + 'always_use_generators': True, + 'group_together': False, + 'textcolor1': "white", + "textcolor2": "black", + "gatecolor1": "tq", + "gatecolor2": "guo" + } + elif style == "standard": + style = { + 'decompose_control_generators': False, + 'always_use_generators': False, + 'group_together': False + } + elif style == "plain": + # standard without colors + style = { + 'decompose_control_generators': False, + 'always_use_generators': False, + 'group_together': False, + 'textcolor1': "black", + "textcolor2": "black", + "gatecolor1": "white", + "gatecolor2": "white" + } + elif style == "generators": + style = { + 'decompose_control_generators': True, + 'always_use_generators': True, + 'group_together': "BARRIER" + } + elif not hasattr(style, "items"): + raise Exception( + "style needs to be `tequila`, or `standard` or `generators` or a dictionary, you gave: {}".format( + str(style))) + + pop = [] + for k,v in kwargs.items(): + if k in style: + style[k]=kwargs[k] + pop.append(k) + for k in pop: + kwargs.pop(k) + + filename_tmp = filename.split(".") + if len(filename_tmp) == 1: + ftype = ".pdf" + fname = filename + else: + ftype = filename_tmp[-1] + fname = "".join(filename_tmp[:-1]) + + fpath = None + tmp = fname.split("/") + fname = tmp[-1] + if len(tmp) > 1: + fpath = "".join([x + "/" for x in tmp[:-1]]) + if filename[0] == "/": + fpath = "/" + fpath + + export_to_qpic(circuit=circuit, + filename=fname, + filepath=fpath, + qubit_names=qubit_names, **style, **kwargs) + if ftype != "qpic": + subprocess.call(["qpic", "{}.qpic".format(fname), "-f", ftype], cwd=fpath)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/hamiltonian/paulis.html b/docs/sphinx/_modules/tequila_code/hamiltonian/paulis.html new file mode 100644 index 0000000..e5b9371 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/hamiltonian/paulis.html @@ -0,0 +1,524 @@ + + + + + + + + tequila_code.hamiltonian.paulis — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for tequila_code.hamiltonian.paulis

+"""
+Convenience initialization
+of Pauli Operators. Resulting structures can be added and multiplied together.
+Currently uses OpenFermion as backend (QubitOperators)
+"""
+import typing
+from tequila.hamiltonian import QubitHamiltonian
+from tequila import BitString, TequilaException
+from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
+from tequila.tools import list_assignment
+import numpy
+
+
+[docs] +def from_string(string, openfermion_format=False): + return QubitHamiltonian.from_string(string=string, openfermion_format=openfermion_format)
+ + +
+[docs] +def pauli(qubit, type) -> QubitHamiltonian: + """ + Parameters + ---------- + qubit: int or list of ints + + type: str or int or list of strquaing or int: + define if X, Y or Z (0,1,2) + + Returns + ------- + QubitHamiltonian + """ + + def assign_axis(axis): + if axis in QubitHamiltonian.axis_to_string: + return QubitHamiltonian.axis_to_string[axis] + elif hasattr(axis, "upper"): + return axis.upper() + else: + raise TequilaException("unknown initialization for pauli operator: {}".format(axis)) + + if not isinstance(qubit, typing.Iterable): + qubit = [qubit] + type = [type] + + type = [assign_axis(x) for x in type] + + init_string = "".join("{}{} ".format(t, q) for t, q in zip(type, qubit)) + + return QubitHamiltonian.from_string(string=init_string, openfermion_format=True)
+ + + +
+[docs] +def X(qubit) -> QubitHamiltonian: + """ + Initialize a single Pauli X Operator + + Parameters + ---------- + qubit: int or list of ints + qubit(s) on which the operator should act + + Returns + ------- + QubitHamiltonian + + """ + qubit = list_assignment(qubit) + return pauli(qubit=qubit, type=["X"] * len(qubit))
+ + + +
+[docs] +def Y(qubit) -> QubitHamiltonian: + """ + Initialize a single Pauli Y Operator + + Parameters + ---------- + qubit: int or list of ints + qubit(s) on which the operator should act + + Returns + ------- + QubitHamiltonian + + """ + qubit = list_assignment(qubit) + return pauli(qubit=qubit, type=["Y"] * len(qubit))
+ + + +
+[docs] +def Z(qubit) -> QubitHamiltonian: + """ + Initialize a single Pauli Z Operator + + Parameters + ---------- + qubit: int or list of ints + qubit(s) on which the operator should act + + Returns + ------- + QubitHamiltonian + + """ + qubit = list_assignment(qubit) + return pauli(qubit=qubit, type=["Z"] * len(qubit))
+ + + +
+[docs] +def I(*args, **kwargs) -> QubitHamiltonian: + """ + Initialize unit Operator + + Returns + ------- + QubitHamiltonian + + """ + return QubitHamiltonian.unit()
+ + + +
+[docs] +def Zero(*args, **kwargs) -> QubitHamiltonian: + """ + Initialize 0 Operator + + Returns + ------- + QubitHamiltonian + + """ + return QubitHamiltonian.zero()
+ + + +
+[docs] +def Qp(qubit) -> QubitHamiltonian: + """ + Notes + ---------- + Initialize + + .. math:: + \\frac{1}{2} \\left( 1 - \\sigma_z \\right) + + Parameters + ---------- + qubit: int or list of ints + qubit(s) on which the operator should act + + Returns + ------- + QubitHamiltonian + + """ + qubit = list_assignment(qubit) + result = I() + for q in qubit: + result *= 0.5 * (I(qubit=q) + Z(qubit=q)) + return result
+ + + +
+[docs] +def Qm(qubit) -> QubitHamiltonian: + """ + Notes + ---------- + Initialize + + .. math:: + \\frac{1}{2} \\left( 1 + \\sigma_z \\right) + + Parameters + ---------- + qubit: int or list of ints + qubit(s) on which the operator should act + + Returns + ------- + QubitHamiltonian + + """ + qubit = list_assignment(qubit) + result = I() + for q in qubit: + result *= 0.5 * (I(qubit=q) - Z(qubit=q)) + return result
+ + + +
+[docs] +def Sp(qubit) -> QubitHamiltonian: + """ + Notes + ---------- + Initialize + + .. math:: + \\frac{1}{2} \\left( \\sigma_x + i\\sigma_y \\right) + + Parameters + ---------- + qubit: int or list of ints + qubit(s) on which the operator should act + + Returns + ------- + QubitHamiltonian + + """ + qubit = list_assignment(qubit) + result = I() + for q in qubit: + result *= 0.5 * (X(qubit=q) + 1.j * Y(qubit=q)) + return result
+ + + +
+[docs] +def Sm(qubit) -> QubitHamiltonian: + """ + Notes + ---------- + Initialize + + .. math:: + \\frac{1}{2} \\left( \\sigma_x - i \\sigma_y \\right) + + Parameters + ---------- + qubit: int or list of ints + qubit(s) on which the operator should act + + Returns + ------- + QubitHamiltonian + + """ + qubit = list_assignment(qubit) + result = I() + for q in qubit: + result *= 0.5 * (X(qubit=q) - 1.j * Y(qubit=q)) + return result
+ + + +
+[docs] +def Projector(wfn, threshold=0.0, n_qubits=None) -> QubitHamiltonian: + """ + Notes + ---------- + Initialize a projector given by + + .. math:: + H = \\lvert \\Psi \\rangle \\langle \\Psi \\rvert + + Parameters + ---------- + wfn: QubitWaveFunction or int, or string, or array : + The wavefunction onto which the projector projects + Needs to be passed down as tequilas QubitWaveFunction type + See the documentation on how to initialize a QubitWaveFunction from + integer, string or array (can also be passed down diretly as one of those types) + + + threshold: float: (Default value = 0.0) + neglect small parts of the operator + + n_qubits: only needed when an integer is given as wavefunction + + Returns + ------- + + """ + + wfn = QubitWaveFunction(state=wfn, n_qubits=n_qubits) + + H = QubitHamiltonian.zero() + for k1, v1 in wfn.items(): + for k2, v2 in wfn.items(): + c = v1.conjugate() * v2 + if not numpy.isclose(c, 0.0, atol=threshold): + H += c * decompose_transfer_operator(bra=k1, ket=k2) + assert (H.is_hermitian()) + return H
+ + + +
+[docs] +def KetBra(ket: QubitWaveFunction, bra: QubitWaveFunction, hermitian: bool = False, threshold: float = 1.e-6, + n_qubits=None): + """ + Notes + ---------- + Initialize the general KetBra operator + .. math:: + H = \\lvert ket \\rangle \\langle bra \\rvert + + e.g. + wfn1 = tq.QubitWaveFunction.from_string("1.0*|00> + 1.0*|11>").normalize() + wfn2 = tq.QubitWaveFunction.from_string("1.0*|00>") + operator = tq.paulis.KetBra(ket=wfn1, bra=wfn1) + initializes the transfer operator from the all-zero state to a Bell state + + Parameters + ---------- + ket: QubitWaveFunction: + QubitWaveFunction which defines the ket element + can also be given as string or array or integer + bra: QubitWaveFunction: + QubitWaveFunction which defines the bra element + can also be given as string or array or integer + hermitian: bool: (Default False) + if True the hermitian version H + H^\dagger is returned + threshold: float: (Default 1.e-6) + elements smaller than the threshold will be ignored + n_qubits: only needed if ket and/or bra are passed down as integers + + Returns + ------- + QubitHamiltonian: + a tequila QubitHamiltonian (not necessarily hermitian) representing the KetBra operator desired. + + """ + H = QubitHamiltonian.zero() + ket = QubitWaveFunction(state=ket, n_qubits=n_qubits) + bra = QubitWaveFunction(state=bra, n_qubits=n_qubits) + + for k1, v1 in bra.items(): + for k2, v2 in ket.items(): + c = v1.conjugate() * v2 + if not numpy.isclose(c, 0.0, atol=threshold): + H += c * decompose_transfer_operator(bra=k1, ket=k2) + if hermitian: + return H.split()[0] + else: + return H.simplify(threshold=threshold)
+ + + +
+[docs] +def decompose_transfer_operator(ket: BitString, bra: BitString, qubits: typing.List[int] = None) -> QubitHamiltonian: + """ + Notes + ---------- + Create the operator + + Note that this is operator is not necessarily hermitian + So be careful when using it as a generator for gates + + e.g. + decompose_transfer_operator(ket="01", bra="10", qubits=[2,3]) + gives the operator + + .. math:: + \\lvert 01 \\rangle \\langle 10 \\rvert_{2,3} + + acting on qubits 2 and 3 + + Parameters + ---------- + ket: pass an integer, string, or tequila BitString + bra: pass an integer, string, or tequila BitString + qubits: pass the qubits onto which the operator acts + + Returns + ------- + + """ + + opmap = { + (0, 0): Qp, + (0, 1): Sp, + (1, 0): Sm, + (1, 1): Qm + } + + nbits = None + if qubits is not None: + nbits = len(qubits) + + if isinstance(bra, int): + bra = BitString.from_int(integer=bra, nbits=nbits) + if isinstance(ket, int): + ket = BitString.from_int(integer=ket, nbits=nbits) + + b_arr = bra.array + k_arr = ket.array + assert (len(b_arr) == len(k_arr)) + n_qubits = len(k_arr) + + if qubits is None: + qubits = range(n_qubits) + + assert (n_qubits <= len(qubits)) + + result = QubitHamiltonian.unit() + for q, b in enumerate(b_arr): + k = k_arr[q] + result *= opmap[(k, b)](qubit=qubits[q]) + + return result
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/optimizers.html b/docs/sphinx/_modules/tequila_code/optimizers.html new file mode 100644 index 0000000..0967e93 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/optimizers.html @@ -0,0 +1,241 @@ + + + + + + + + tequila_code.optimizers — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.optimizers

+from tequila.optimizers.optimizer_base import OptimizerHistory, Optimizer, TequilaOptimizerException, OptimizerResults
+from tequila.optimizers.optimizer_scipy import OptimizerSciPy
+from tequila.optimizers.optimizer_gd import OptimizerGD
+from tequila.optimizers.optimizer_scipy import minimize as minimize_scipy
+from tequila.optimizers.optimizer_gd import minimize as minimize_gd
+from tequila.simulators.simulator_api import simulate
+from dataclasses import dataclass
+
+import typing, numbers, numpy
+
+
+@dataclass
+class _Optimizers:
+    minimize: typing.Callable = None
+    cls: type = None
+    methods: list = None
+
+
+SUPPORTED_OPTIMIZERS = ['scipy', 'gpyopt', 'gd']
+INSTALLED_OPTIMIZERS = {}
+INSTALLED_OPTIMIZERS['scipy'] = _Optimizers(cls=OptimizerSciPy,
+                                            minimize=minimize_scipy,
+                                            methods=OptimizerSciPy.available_methods())
+INSTALLED_OPTIMIZERS['gd'] = _Optimizers(cls=OptimizerGD,
+                                         minimize=minimize_gd,
+                                         methods=OptimizerGD.available_methods())
+
+has_gpyopt = False
+try:
+    from tequila.optimizers.optimizer_gpyopt import OptimizerGPyOpt
+    from tequila.optimizers.optimizer_gpyopt import minimize as minimize_gpyopt
+
+    INSTALLED_OPTIMIZERS['gpyopt'] = _Optimizers(cls=OptimizerGPyOpt,
+                                                 minimize=minimize_gpyopt,
+                                                 methods=OptimizerGPyOpt.available_methods())
+    has_gpyopt = True
+except ImportError:
+    has_gpyopt = False
+
+
+[docs] +def show_available_optimizers(module=None): + """ + Returns + ------- + A list of available optimization methods + The list depends on optimization packages installed in your system + """ + if module is None: + print("available methods for optimizer modules found on your system:") + else: + print("available methods for optimizer module {}".format(module)) + if module not in INSTALLED_OPTIMIZERS: + print("module {} not found!".format(module)) + module = None + + print("{:20} | {}".format("method", "optimizer module")) + print("--------------------------") + for k, v in INSTALLED_OPTIMIZERS.items(): + if module is not None and module != k: + continue + for method in v.methods: + print("{:20} | {}".format(method, k)) + + if module is None: + print("Supported optimizer modules: ", SUPPORTED_OPTIMIZERS) + print("Installed optimizer modules: ", list(INSTALLED_OPTIMIZERS.keys()))
+ + + +
+[docs] +def minimize(objective, + method: str = "bfgs", + variables: list = None, + initial_values: typing.Union[dict, numbers.Number, typing.Callable] = 0.0, + maxiter: int = None, + *args, + **kwargs): + """ + + Parameters + ---------- + method: str: + The optimization method (e.g. bfgs, cobyla, nelder-mead, ...) + see 'tq.optimizers.show_available_methods()' for an overview + objective: tq.Objective: + The abstract tequila objective to be optimized + variables: list of names: + The variables which shall be optimized given as list + Can be passed as list of names or list of tq variables + initial_values: dict: + Initial values for the optimization, passed as dictionary + with the variable names as keys. + Alternatively `zero`, `random` or a single number are accepted + maxiter: + maximum number of iterations + kwargs: + further keyword arguments for the actual minimization functions + can also be called directly as tq.minimize_modulename + e.g. tq.minimize_scipy + See their documentation for more details + + example: gradient keyword: + gradient (Default Value: None): + instructions for gradient compilation + can be a dictionary of tequila objectives representing the gradients + or a string/dictionary giving instructions for numerical gradients + examples are + gradient = '2-point' + gradient = {'method':'2-point', 'stepsize': 1.e-4} + gradient = {'method':Callable, 'stepsize': 1.e-4} + see optimizer_base.py for method examples + + gradient = None: analytical gradients are compiled + + + Returns + ------- + + """ + + ovtmp=objective.extract_variables() + fast_return=False + if ovtmp is None or len(ovtmp) == 0: + return OptimizerResults(energy=float(simulate(objective, *args, **kwargs)), variables={}, history=OptimizerHistory()) + + for k, v in INSTALLED_OPTIMIZERS.items(): + if method.lower() in v.methods or method.upper() in v.methods: + return v.minimize( + objective=objective, + method=method, + variables=variables, + initial_values=initial_values, + maxiter=maxiter, + *args, **kwargs) + + raise TequilaOptimizerException( + "Could not find optimization method {} in tequila optimizers. You might miss dependencies")
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/optimizers/optimizer_base.html b/docs/sphinx/_modules/tequila_code/optimizers/optimizer_base.html new file mode 100644 index 0000000..a91dc7d --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/optimizers/optimizer_base.html @@ -0,0 +1,1063 @@ + + + + + + + + tequila_code.optimizers.optimizer_base — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.optimizers.optimizer_base

+"""
+Base class for Optimizers.
+"""
+import typing, numbers, copy, warnings
+
+from tequila.utils.exceptions import TequilaException, TequilaWarning
+from tequila.simulators.simulator_api import compile, pick_backend
+from tequila.objective import Objective
+from tequila.circuit.gradient import grad
+from dataclasses import dataclass, field
+from tequila.objective.objective import assign_variable, Variable, format_variable_dictionary, format_variable_list
+import numpy
+from random import choices
+
+
+
+[docs] +class TequilaOptimizerException(TequilaException): + pass
+ + + +
+[docs] +@dataclass +class OptimizerHistory: + """ + A class representing the history of optimizers over time. Has a variety of convenience functions attached to it. + """ + + @property + def iterations(self): + if self.energies is None: + return 0 + else: + return len(self.energies) + + # history of all true iterations (epochs) + energies: typing.List[numbers.Real] = field(default_factory=list) + gradients: typing.List[typing.Dict[str, numbers.Real]] = field(default_factory=list) + angles: typing.List[typing.Dict[str, numbers.Number]] = field(default_factory=list) + + # history of all function evaluations + energy_calls: typing.List[numbers.Real] = field(default_factory=list) + gradient_calls: typing.List[typing.Dict[str, numbers.Real]] = field(default_factory=list) + angles_calls: typing.List[typing.Dict[str, numbers.Number]] = field(default_factory=list) + + # backward comp. + @property + def energies_calls(self): + return self.energy_calls + @property + def energies_evaluations(self): + return self.energy_calls + + def __add__(self, other): + """ + magic method for convenient combination of history objects. + """ + result = OptimizerHistory() + result.energies = self.energies + other.energies + result.gradients = self.gradients + other.gradients + result.angles = self.angles + other.angles + return result + + def __iadd__(self, other): + """ + magic method for convenient in place combination of history objects. + """ + self.energies += other.energies + self.gradients += other.gradients + self.angles += other.angles + return self + +
+[docs] + def extract_energies(self, *args, **kwargs) -> typing.Dict[numbers.Integral, numbers.Real]: + """ + convenience function to get the energies back as a dictionary. + """ + return {i: e for i, e in enumerate(self.energies)}
+ + +
+[docs] + def extract_gradients(self, key: str) -> typing.Dict[numbers.Integral, numbers.Real]: + """ + convenience function to get the gradients of some variable out of the history. + Parameters + ---------- + key: str: + the name of the variable whose gradients are sought + + Returns + ------- + dict: + a dictionary, representing the gradient of variable 'key' over time. + """ + gradients = {} + for i, d in enumerate(self.gradients): + if key in d: + gradients[i] = d[assign_variable(key)] + return gradients
+ + +
+[docs] + def extract_angles(self, key: str) -> typing.Dict[numbers.Integral, numbers.Real]: + """ + convenience function to get the value of some variable out of the history. + + Parameters + ---------- + key: str: + name of the variable whose values are sought + + Returns + ------- + dict: + a dictionary, representing the value of variable 'key' over time. + """ + angles = {} + for i, d in enumerate(self.angles): + if key in d: + angles[i] = d[assign_variable(key)] + return angles
+ + +
+[docs] + def plot(self, + property: typing.Union[str, typing.List[str]] = 'energies', + key: str = None, + filename=None, + baselines: typing.Dict[str, float] = None, + *args, **kwargs): + + """ + Convenience function to plot the progress of the optimizer over time. + Parameters + ---------- + property: (list of) str: Default = 'energies' + which property (eg angles, energies, gradients) to plot. + Default: plot energies over time. + key: str, optional: + if property is 'angles' or 'gradients', key allows you to plot just an individual variables' property. + Default: plot everything + filename, optional: + if give, plot to this file; else, plot to terminal. + Default: plot to terminal. + baselines: dict, optional: + dictionary of plotting axis baseline information. + Default: use whatever matplotlib auto-generates. + + args: + args. + kwargs: + kwargs. + + Returns + ------- + None + """ + + from matplotlib import pyplot as plt + from matplotlib.ticker import MaxNLocator + fig = plt.figure() + fig.gca().xaxis.set_major_locator(MaxNLocator(integer=True)) + import pickle + + if baselines is not None: + for k, v in baselines.items(): + plt.axhline(y=v, label=k) + + if hasattr(property, "lower"): + properties = [property.lower()] + else: + properties = property + + labels = None + if 'labels' in kwargs: + labels = kwargs['labels'] + elif 'label' in kwargs: + labels = kwargs['label'] + + if hasattr(labels, "lower"): + labels = [labels] * len(properties) + + for k, v in kwargs.items(): + if hasattr(plt, k): + f = getattr(plt, k) + if callable(f): + f(v) + else: + f = v + + if key is None: + keys = [[k for k in self.angles[-1].keys()]] * len(properties) + elif isinstance(key, typing.Hashable): + keys = [[assign_variable(key)]] * len(properties) + else: + key = [assign_variable(k) for k in key] + keys = [key] * len(properties) + + for i, p in enumerate(properties): + try: + label = labels[i] + except: + label = p + + if p == "energies": + data = getattr(self, "extract_" + p)() + plt.plot(list(data.keys()), list(data.values()), label=str(label), marker='o', linestyle='--') + else: + for k in keys[i]: + data = getattr(self, "extract_" + p)(key=k) + plt.plot(list(data.keys()), list(data.values()), label=str(label) + " " + str(k), marker='o', + linestyle='--') + + loc = 'best' + if 'loc' in kwargs: + loc = kwargs['loc'] + plt.legend(loc=loc) + if filename is None: + plt.show() + else: + pickle.dump(fig, open(filename + ".pickle", "wb")) + plt.savefig(fname=filename + ".pdf", **kwargs)
+
+ + +
+[docs] +@dataclass +class OptimizerResults: + + energy: float = None + history: OptimizerHistory = None + variables: dict = None + + + @property + def angles(self): + # allow backwards compatibility + return self.variables
+ + + +
+[docs] +class Optimizer: + + """ + The base optimizer class, from which other optimizers inherit. + + + Attributes + ---------- + + backend: + The quantum backend to use (None means autopick) + maxiter: + Maximum number of iterations to perform. + silent: + whether or not to print during call or on init. + samples: + number of samples to call objectives with during call. + print_level: + Allow customization of printout in derived classes, is set to 0 if silent==True. + save_history: + whether or not to save history. + history: + a history object, saving information during optimization. + noise: + what noise (e.g, a NoiseModel) to apply to simulations during optimization. + device: + the device that sampling (real or emulated) should be performed on. + + + Methods + ------- + reset_history: + reset the optimizer history. + initialize_variables: + convenience: format variables of an objective and segregrate actives from passives. + compile_objective: + convenience: compile an objective. + compile_gradient: + convenience: build and compile (i.e render callable) the gradient of an objective. + compile_hessian: + convenience: build and compile (i.e render callable) the hessian of an objective. + + """ + def __init__(self, backend: str = None, + maxiter: int = None, + samples: int = None, + device: str= None, + noise=None, + save_history: bool = True, + silent: typing.Union[bool, int] = False, + print_level: int = 99, *args, **kwargs): + + """ + initialize an optimizer. + + Parameters + ---------- + backend: str, optional: + a quantum backend to use. None means autopick. + maxiter: int, optional: + maximum number of iterations to performed. + Note: overwrites attribute of same name to 100, not None, if default. + samples: int, optional: + number of samples to simulate measurement of objectives with. + Default: none, i.e full wavefunction simulation. + device: optional: + changeable type. The device on which to perform (or, simulate performing) actual quantum computation. + Default None will use the basic, un-restricted simulators of backend. + noise: optional: + NoiseModel object or str 'device', being either a custom noisemodel or the instruction to use that of + the emulated device. + Default value none means: simulate without any noise. + save_history: bool: Default = True: + whether or not to save history during optimization. Defaults to true. + silent: bool: Default = False: + whether or not to be verbose during iterations of optimization. + False indicates verbosity. + print_level: int: Default = 99: + The degree of verbosity during print. Meaningless on in base. + args + kwargs + """ + if backend is None: + self.backend = pick_backend(backend, samples=samples, noise=noise,device=device) + else: + self.backend = backend + + if maxiter is None: + self.maxiter = 100 + else: + self.maxiter = maxiter + + if silent is None: + self.silent = False + else: + self.silent = silent + + if print_level is None: + self.print_level = 99 + else: + self.print_level = print_level + + if silent: + self.print_level = 0 + + self.samples = samples + self.save_history = save_history + if save_history: + self.history = OptimizerHistory() + else: + self.history = None + + self.noise = noise + self.device = device + self.args = args + self.kwargs = kwargs + +
+[docs] + def reset_history(self): + """ + replace self.history with a blank history. + + Returns + ------- + None + """ + self.history = OptimizerHistory()
+ + + def __call__(self, objective: Objective, + variables: typing.List[Variable], + initial_values: typing.Dict[Variable, numbers.Real] = None, + *args, + **kwargs) -> OptimizerResults: + """ + Optimize some objective with the optimizer. + + Parameters + ---------- + objective: Objective: + The objective to optimize. + variables: list: + which variables to optimize over. + initial_values: dict, optional: + a starting point at which to begin optimization; a dict of variable, number pairs. + args + kwargs + + Returns + ------- + OptimizerResults instance with "energy" "history" and "variables" as attributes + see inheritors for more details. + """ + raise TequilaOptimizerException("Tried to call BaseClass of Optimizer") + +
+[docs] + def initialize_variables(self, objective, initial_values, variables): + """ + Convenience function to format the variables of some objective recieved in calls to optimzers. + + Parameters + ---------- + objective: Objective: + the objective being optimized. + initial_values: dict or string: + initial values for the variables of objective, as a dictionary. + if string: can be `zero` or `random` + if callable: custom function that initializes when keys are passed + if None: random initialization between 0 and 2pi (not recommended) + variables: list: + the variables being optimized over. + + Returns + ------- + tuple: + active_angles, a dict of those variables being optimized. + passive_angles, a dict of those variables NOT being optimized. + variables: formatted list of the variables being optimized. + """ + # bring into right format + variables = format_variable_list(variables) + all_variables = objective.extract_variables() + if variables is None: + variables = all_variables + if initial_values is None: + initial_values = {k: numpy.random.uniform(0, 2 * numpy.pi) for k in all_variables} + elif hasattr(initial_values, "lower"): + if initial_values.lower() == "zero": + initial_values = {k:0.0 for k in all_variables} + elif "zero" in initial_values.lower(): + scale=0.1 + if "scale" in initial_values.lower(): + # pass as: near_zero_scale=0.1_... + scale = float(initial_values.split("scale")[1].split("_")[0].split("=")[1]) + initial_values = {k: numpy.random.normal(loc=0.0, scale=scale) for k in all_variables} + elif initial_values.lower() == "random": + initial_values = {k: numpy.random.uniform(0.0, 4*numpy.pi) for k in all_variables} + elif "random" in initial_values.lower(): + scale=2*numpy.pi + loc=0.0 + if "scale" in initial_values.lower(): + scale = float(initial_values.split("scale")[1].split("_")[0].split("=")[1]) + if "loc" in initial_values.lower(): + loc = float(initial_values.split("loc")[1].split("_")[0].split("=")[1]) + initial_values = {k: numpy.random.normal(loc=loc, scale=scale) for k in all_variables} + else: + raise TequilaOptimizerException("unknown initialization instruction: {}".format(initial_values)) + elif callable(initial_values): + initial_values = {k: initial_values(k) for k in all_variables} + elif isinstance(initial_values, numbers.Number): + initial_values = {k: initial_values for k in all_variables} + else: + # autocomplete initial values, warn if you did + detected = False + for k in all_variables: + if k not in initial_values: + initial_values[k] = 0.0 + detected = True + if detected and not self.silent: + warnings.warn("initial_variables given but not complete: Autocompleted with zeroes", TequilaWarning) + initial_values = format_variable_dictionary(initial_values) + + active_angles = {} + for v in variables: + active_angles[v] = initial_values[v] + + passive_angles = {} + for k, v in initial_values.items(): + if k not in active_angles.keys(): + passive_angles[k] = v + return active_angles, passive_angles, variables
+ + +
+[docs] + def compile_objective(self, objective: Objective, *args, **kwargs): + """ + convenience function to wrap over compile; for use by inheritors. + Parameters + ---------- + objective: Objective: + an objective to compile. + args + kwargs + + Returns + ------- + Objective: + a compiled Objective. Types vary. + """ + return compile(objective=objective, + samples=self.samples, + backend=self.backend, + device=self.device, + noise=self.noise, + *args, **kwargs)
+ + +
+[docs] + def compile_gradient(self, objective: Objective, + variables: typing.List[Variable], + gradient=None, + *args, **kwargs) -> typing.Tuple[ + typing.Dict, typing.Dict]: + """ + convenience function to compile gradient objects and relavant types. For use by inheritors. + + Parameters + ---------- + objective: Objective: + the objective whose gradient is to be calculated. + variables: list: + the variables to take gradients with resepct to. + gradient, optional: + special argument to change what structure is used to calculate the gradient, like numerical, or QNG. + Default: use regular, analytic gradients. + args + kwargs + + Returns + ------- + tuple: + both the uncompiled and compiled gradients of objective, w.r.t variables. + """ + if gradient is None: + dO = {k: grad(objective=objective, variable=k, *args, **kwargs) for k in variables} + compiled_grad = {k: self.compile_objective(objective=dO[k], *args, **kwargs) for k in variables} + + elif isinstance(gradient, dict) or hasattr(gradient, "items"): + if all([isinstance(x, Objective) for x in gradient.values()]): + dO = gradient + compiled_grad = {k: self.compile_objective(objective=dO[k], *args, **kwargs) for k in variables} + elif 'method' in gradient and gradient['method'] == 'standard_spsa': + dO = None + compiled = self.compile_objective(objective=objective) + compiled_grad = _SPSAGrad(objective=compiled, variables=variables, **gradient) + else: + dO = None + compiled = self.compile_objective(objective=objective) + compiled_grad = {k: _NumGrad(objective=compiled, variable=k, **gradient) for k in variables} + else: + raise TequilaOptimizerException( + "unknown gradient instruction of type {} : {}".format(type(gradient), gradient)) + + return dO, compiled_grad
+ + +
+[docs] + def compile_hessian(self, + variables: typing.List[Variable], + grad_obj: typing.Dict[Variable, Objective], + comp_grad_obj: typing.Dict[Variable, Objective], + hessian: dict = None, + *args, + **kwargs) -> tuple: + """ + convenience function to compile hessians for optimizers which require it. + Parameters + ---------- + variables: + the variables of the hessian. + grad_obj: + the gradient object, to be differentiated once more + comp_grad_obj: + the compiled gradient object, used for further compilation of the hessian. + hessian: optional: + extra information to modulate compilation of the hessian. + args + kwargs + + Returns + ------- + tuple: + uncompiled and compiled hessian objects, in that order + """ + dO = grad_obj + cdO = comp_grad_obj + + if hessian is None: + if dO is None: + raise TequilaOptimizerException("Can not combine analytical Hessian with numerical Gradient\n" + "hessian instruction was: {}".format(hessian)) + + compiled_hessian = {} + ddO = {} + for k in variables: + dOk = dO[k] + for l in variables: + ddO[(k, l)] = grad(objective=dOk, variable=l) + compiled_hessian[(k, l)] = self.compile_objective(ddO[(k, l)]) + ddO[(l, k)] = ddO[(k, l)] + compiled_hessian[(l, k)] = compiled_hessian[(k, l)] + + elif isinstance(hessian, dict): + if all([isinstance(x, Objective) for x in hessian.values()]): + ddO = hessian + compiled_hessian = {k: self.compile_objective(objective=ddO[k], *args, **kwargs) for k in + hessian.keys()} + else: + ddO = None + compiled_hessian = {} + for k in variables: + for l in variables: + compiled_hessian[(k, l)] = _NumGrad(objective=cdO[k], variable=l, **hessian) + compiled_hessian[(l, k)] = _NumGrad(objective=cdO[l], variable=k, **hessian) + else: + raise TequilaOptimizerException("unknown hessian instruction: {}".format(hessian)) + + return ddO, compiled_hessian
+ + + def __repr__(self): + infostring = "Optimizer: {} \n".format(str(type(self))) + infostring += "{:15} : {}\n".format("backend", self.backend) + infostring += "{:15} : {}\n".format("device", self.device) + infostring += "{:15} : {}\n".format("samples", self.samples) + infostring += "{:15} : {}\n".format("save_history", self.save_history) + infostring += "{:15} : {}\n".format("noise", self.noise) + return infostring
+ + + +class _NumGrad: + """ Numerical Gradient object. + + Should not be used outside of optimizers. + Can't interact with other tequila structures. + + Attributes + ---------- + + objective: + the objective whose gradient is to be approximated. + variable: + the variable with respect to which the gradient is taken. + stepsize: + the size of the small constant for shifting. + method: how to approximate the gradient. + + + Methods + ------- + symmetric_two_point_stencil: + get gradient by point + shift, point - shift + forward_two_point_stencil: + get gradient by point + shift, point. + backward_two_point_stencil: + get gradient by point, point -shift + count_expectaionvalues: + convenience; call the count_expectationvalues method of objective + + """ + + def __init__(self, objective, variable, stepsize, method=None): + """ + + Parameters + ---------- + objective: Objective: + the objective whose gradient is to be approximated. + variable: + the variable the gradient of objective with respect to which is taken. + stepsize: + the small shift by which to displace variable around a point. + method: + the method by which to approximate the gradient. + """ + self.objective = objective + self.variable = variable + self.stepsize = stepsize + if method is None or method == "2-point": + self.method = self.symmetric_two_point_stencil + elif method is None or method == "2-point-forward": + self.method = self.forward_two_point_stencil + elif method is None or method == "2-point-backward": + self.method = self.backward_two_point_stencil + else: + self.method = method + + @staticmethod + def symmetric_two_point_stencil(obj, vars, key, step, *args, **kwargs): + """ + calculate objective gradient by symmetric shifts about a point. + Parameters + ---------- + obj: Objective: + objective to call. + vars: + variables to feed to the objective. + key: + which variable to shift, i.e, which variable's gradient is being called. + step: + the size of the shift; a small float. + args + kwargs + + Returns + ------- + float: + the approximated gradient of obj w.r.t var at point vars as a float. + + """ + left = copy.deepcopy(vars) + left[key] += step / 2 + right = copy.deepcopy(vars) + right[key] -= step / 2 + return 1.0 / step * (obj(left, *args, **kwargs) - obj(right, *args, **kwargs)) + + @staticmethod + def forward_two_point_stencil(obj, vars, key, step, *args, **kwargs): + """ + calculate objective gradient by asymmetric upward shfit relative to some point. + Parameters + ---------- + obj: Objective: + objective to call. + vars: + variables to feed to the objective. + key: + which variable to shift, i.e, which variable's gradient is being called. + step: + the size of the shift; a small float. + args + kwargs + + Returns + ------- + float: + the approximated gradient of obj w.r.t var at point vars as a float. + + """ + + left = copy.deepcopy(vars) + left[key] += step + right = copy.deepcopy(vars) + return 1.0 / step * (obj(left, *args, **kwargs) - obj(right, *args, **kwargs)) + + @staticmethod + def backward_two_point_stencil(obj, vars, key, step, *args, **kwargs): + """ + calculate objective gradient by asymmetric downward shfit relative to some point. + Parameters + ---------- + obj: Objective: + objective to call. + vars: + variables to feed to the objective. + key: + which variable to shift, i.e, which variable's gradient is being called. + step: + the size of the shift; a small float. + args + kwargs + + Returns + ------- + the approximated gradient of obj w.r.t var at point vars as a float. + + """ + + left = copy.deepcopy(vars) + right = copy.deepcopy(vars) + right[key] -= step + return 1.0 / step * (obj(left, *args, **kwargs) - obj(right, *args, **kwargs)) + + def __call__(self, variables, *args, **kwargs): + """ + convenience function to call self.method, e.g one of the staticmethods of this class. + + Parameters + ---------- + variables: + the variables constitutive of the point at which numerical gradients of self.objective are to be taken + args + kwargs + + Returns + ------- + type: + generally, float, the result of the numerical gradient. + """ + return self.method(self.objective, variables, self.variable, self.stepsize, *args, **kwargs) + + def count_expectationvalues(self, *args, **kwargs): + """ + how many expectationvalues are in self.objective? + Parameters + ---------- + args + kwargs + + Returns + ------- + int: + how many expectationvalues are in self.objective + """ + return self.objective.count_expectationvalues(*args, **kwargs) + +class _SPSAGrad(_NumGrad): + """ Simultaneous Perturbation Stochastic Approximation Gradient object. + + Should not be used outside of optimizers. + Can't interact with other tequila structures. + + Attributes + ---------- + + objective: + the objective whose gradient is to be approximated. + variables: + the variables with respect to which the gradient is taken. + stepsize: + the size of the small constant for shifting. + + """ + + def __init__(self, objective, variables, stepsize, gamma=None,method=None): + """ + + Parameters + ---------- + objective: Objective: + the objective whose gradient is to be approximated. + variables: + the variables the gradient of objective with respect to which is taken. + stepsize: + the small shift by which to displace variable around a point. + nextIndex: + Integer indicating the next index of the list stepsize to use + if(nextIndex == -1) stepsize is a float + """ + self.objective = objective + self.variables = variables + self.gamma = gamma + + if isinstance(stepsize, list): + self.nextIndex = 0 + elif gamma != None: + self.nextIndex = "adjust" + else: + self.nextIndex = -1 + self.stepsize = stepsize + if method is None or method == "standard_spsa": + self.method = self.standard_spsa + else: + self.method = method + + @staticmethod + def standard_spsa(obj, vars, keys, step, *args, **kwargs): + """ + calculate objective gradient using standar spsa. + Parameters + ---------- + obj: Objective: + objective to call. + vars: + variables to feed to the objective. + key: + which variables to shift, i.e, which variable's gradient is being called. + step: + the size of the shift; a small float. + args + kwargs + + Returns + ------- + the approximated gradient of obj w.r.t var at point vars as a float. + + """ + dim = len(keys) + perturbation_vector = choices([-1,1],k = dim) + left = copy.deepcopy(vars) + right = copy.deepcopy(vars) + for i, key in enumerate(keys): + left[key] += perturbation_vector[i] * step + right[key] -= perturbation_vector[i] * step + numerator = obj(left, *args, **kwargs) - obj(right, *args, **kwargs) + gradient = list() + for i in range(dim): + gradientComponent = numerator / (2 * step * perturbation_vector[i]) + gradient.append(gradientComponent) + return gradient + + def __call__(self, variables, iteration=1, *args, **kwargs): + """ + convenience function to call self.method, e.g one of the staticmethods of this class. + + Parameters + ---------- + variables: + the variables constitutive of the point at which numerical gradients of self.objective are to be taken + args + kwargs + + Returns + ------- + type: + generally, float, the result of the numerical gradient. + """ + if(self.nextIndex != -1 and self.nextIndex != "adjust"): + stepsize = self.stepsize[self.nextIndex] + if(self.nextIndex != len(self.stepsize) - 1): + self.nextIndex += 1 + elif(self.nextIndex == -1): + stepsize = self.stepsize + else: + stepsize = self.stepsize / (iteration ** self.gamma) + + return self.method(self.objective, variables, self.variables, stepsize, *args, **kwargs) + + def calibrated_lr(self, lr, initial_value, max_iter, *args, **kwargs): + """ + Calculates a calibrated learning rate for spsa + Parameters + ---------- + lr: + learning rate (a variable in spsa related papers) + initial_value: + the initial values of the variables used in the optimization + max_iter: + number of iteration used for the calibration + args + kwargs + + Returns + ------- + type: + float: the learning rate calibrated + """ + dim = len(initial_value) + delta = 0 + if(self.nextIndex != -1 and self.nextIndex != "adjust"): + stepsize = self.stepsize[0] + else: + stepsize = self.stepsize + + for i in range(max_iter): + perturbation_vector = choices([-1,1],k = dim) + left = copy.deepcopy(initial_value) + right = copy.deepcopy(initial_value) + for j, v in enumerate(initial_value): + left[v] += perturbation_vector[j] * stepsize + right[v] -= perturbation_vector[j] * stepsize + numeratorLeft = self.objective(left, *args, **kwargs) + numeratorRight = self.objective(right, *args, **kwargs) + delta += numpy.absolute(numeratorRight - numeratorLeft) / max_iter + return lr * 2 * stepsize / delta +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/optimizers/optimizer_gd.html b/docs/sphinx/_modules/tequila_code/optimizers/optimizer_gd.html new file mode 100644 index 0000000..c229dec --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/optimizers/optimizer_gd.html @@ -0,0 +1,1146 @@ + + + + + + + + tequila_code.optimizers.optimizer_gd — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.optimizers.optimizer_gd

+import numpy, typing, numbers
+from tequila.objective import Objective
+from tequila.objective.objective import Variable, format_variable_dictionary
+from .optimizer_base import Optimizer, OptimizerResults, dataclass
+from tequila.circuit.noise import NoiseModel
+from tequila.tools.qng import get_qng_combos, CallableVector, QNGVector
+from tequila.utils import TequilaException
+
+
+[docs] +@dataclass +class GDResults(OptimizerResults): + + moments: dict = None + num_iteration: int = 0
+ + +
+[docs] +class OptimizerGD(Optimizer): + """ + The gradient descent optimizer for tequila. + + OptimizerGD allows for two modalities: it can either function as a 'stepper', simply calculating updated + parameter values for a given object; or it can be called to perform an entire optimization. The former + is used to accomplish the latter, and can give users a more fine-grained control of the optimization. + See Optimizer for details on inherited attributes or methods; there are several. + + + Attributes + --------- + f: + function which performs an optimization step. + gradient_lookup: + dictionary mapping object ids as strings to said object's callable gradient + active_key_lookup: + dictionary mapping object ids as strings to said object's active keys, itself a dict, of variables to optimize. + moments_lookup: + dictionary mapping object ids as strings to said object's current stored moments; a pair of lists of floats, + namely running tallies of gradient momenta. said momenta are used to SCALE or REDIRECT gradient descent steps. + moments_trajectory: + dictionary mapping object ids as strings to said object's momenta at ALL steps; that is, a list of all + the moments of a given object, in order. + step_lookup: + dictionary mapping object ids as strings to an int; how many optimization steps have been performed for + a given object. Relevant only to the Adam optimizer. + diis: + Dictionary of parameters for the DIIS accelerator. + lr: + a float or list of floats. Hyperparameter: The learning rate (unscaled) to be used in each update; + in some literature, called a step size. + alpha: + a float. Hyperparameter: used to adjust the learning rate each iteration using the formula: lr := original_lr / (iteration ** alpha) + Default: None. If not specify alpha or lr given as a list: lr will not be adjusted + gamma: + a float. Hyperparameter: used to adjust the step of the gradient for spsa method in each iteration + following: c := original_c / (iteration ** gamma) + Default value: None. If not specify gamma or c given as a list: c will not be adjusted + beta: + a float. Hyperparameter: scales (perhaps nonlinearly) all first moment terms in any relavant method. + rho: + a float. Hyperparameter: scales (perhaps nonlinearly) all second moment terms in any relavant method. + in some literature, may be referred to as 'beta_2'. + c: + a float or list of floats. Hyperparameter: The step rate used in the spsa gradient. + If it is a list, the steprate will change each iteration until the last item of the list is reached. + epsilon: + a float. Hyperparameter: used to prevent division by zero in some methods. + tol: + a float. If specified, __call__ aborts when the difference in energies between two steps is smaller than tol. + calibrate_lr: + a boolean. It specifies to calibrate lr value for spsa method. + iteration: + a integer. It indicates the number of the iteration being runned. + + + Methods + ------- + prepare: + perform all necessary compilation and registration of a given objective. Must be called before step + is used on the given optimizer. + step: + perform a single optimization step on a compiled objective, starting from a given point. + reset_stepper: + wipe all stored information about all prepared objectives. + reset_momenta: + reset all moment information about all prepared objectives, but do not erase compiled gradients. + reset_momenta_for: + reset all moment information about a given objective, but do not erase compiled gradients. + + + """ +
+[docs] + @classmethod + def available_methods(cls): + """:return: All tested available methods""" + return ['adam', 'adagrad', 'adamax', 'nadam', 'sgd', 'momentum', 'nesterov', 'rmsprop', 'rmsprop-nesterov', 'spsa']
+ + + +
+[docs] + @classmethod + def available_diis(cls): + """:return: All tested methods that can be diis accelerated""" + return ['sgd']
+ + + def __init__(self, maxiter=100, + method='sgd', + tol: numbers.Real = None, + lr: typing.Union[numbers.Real, typing.List[numbers.Real]] = 0.1, + alpha: numbers.Real = None, + gamma: numbers.Real = None, + beta: numbers.Real = 0.9, + rho: numbers.Real = 0.999, + c: typing.Union[numbers.Real, typing.List[numbers.Real]] = 0.2, + epsilon: numbers.Real = 1.0 * 10 ** (-7), + diis: typing.Optional[dict] = None, + backend=None, + samples=None, + device=None, + noise=None, + silent=True, + calibrate_lr: bool = False, + **kwargs): + + """ + + Parameters + ---------- + maxiter: int: Default = 100: + maximum number of iterations to perform, if using __call__ method. + method: str: Default = 'sgd': + string specifying which of the available methods to use for optimization. if not specified, + then unmodified, stochastic gradient descent will be used. + tol: numbers.Real, optional: + if specified a tolerance that specifies when to deem that an optimization has converged. + If None: no convergence criterion specified; __call__ runs till maxiter is reached. Must be positive, >0. + lr: numbers.Real or list of numbers.Real: Default = 0.1: + the learning rate to use. Rescales all steps; used by every optimizer. + Default value is 0.1; chosen by fiat. + alpha: + a float. Hyperparameter: used to adjust the learning rate each iteration using the formula: lr := original_lr / (iteration ** alpha) + Default value: None. If not specify alpha or lr given as a list: lr will not be adjusted + gamma: + a float. Hyperparameter: used to adjust the step of the gradient for spsa method in each iteration + following: c := original_c / (iteration ** gamma) + Default value: None. If not specify gamma or c given as a list: c will not be adjusted + beta: numbers.Real: Default = 0.9 + rescaling parameter for first moments in a number of methods. Must obey 0<beta<1. + Default value suggested by original adam paper. + rho: numbers.Real: Default = 0.999 + rescaling parameter for second moments in a number of methods. Must obey 0<beta<1. + Default value suggested by original adam paper. + c: numbers.Real or list of numbers.Real: Default = 0.2 + stepsize for the gradient of the spsa method + epsilon: numbers.Real: Default = 10^-7: + a float for prevention of division by zero in methods like adam. Must be positive. + Default value suggested by original adam paper. + diis: dict, optional: + Dictionary of parameters for DIIS accelerator. + backend: str, optional: + a quantum backend to use. None means autopick. + samples: int, optional: + number of samples to simulate measurement of objectives with. + Default: none, i.e full wavefunction simulation. + device: optional: + changeable type. The device on which to perform (or, simulate performing) actual quantum computation. + Default None will use the basic, un-restricted simulators of backend. + noise: optional: + NoiseModel object or str 'device', being either a custom noisemodel or the instruction to use that of + the emulated device. + Default value none means: simulate without any noise. + silent: bool: Default = False: + suppresses printout during calls if True. + calibrate_lr: bool: Default = False + It specifies to calibrate lr value for spsa method. + kwargs + """ + + super().__init__(maxiter=maxiter, samples=samples,device=device, + backend=backend,silent=silent, + noise=noise, + **kwargs) + method_dict = { + 'adam': self._adam, + 'adagrad': self._adagrad, + 'adamax': self._adamax, + 'nadam': self._nadam, + 'sgd': self._sgd, + 'momentum': self._momentum, + 'nesterov': self._nesterov, + 'rmsprop': self._rms, + 'rmsprop-nesterov': self._rms_nesterov, + 'spsa': self._spsa + } + + self.f = method_dict[method.lower()] + self.gradient_lookup = {} + self.active_key_lookup = {} + self.moments_lookup = {} + self.moments_trajectory = {} + self.step_lookup = {} + ### scaling parameters. lr is learning rate. + ### beta rescales first moments. rho rescales second moments. epsilon is for division stability. + self.lr = lr + self.alpha = alpha + self.gamma = gamma + self.beta = beta + self.rho = rho + self.c = c + self.epsilon = epsilon + self.calibrate_lr = calibrate_lr + # DIIS quantities + if diis is True: + # Use default parameters + diis = {} + + if diis is None: + # DOn't do DIIS + self.__diis = None + elif type(diis) is dict: + # User parameters + if method.lower() in OptimizerGD.available_diis(): + self.__diis = DIIS(**diis) + else: + raise AttributeError("DIIS not compatible with method %s" % method) + else: + raise TypeError("Type of DIIS is not dict") + + if(isinstance(lr, list)): + self.nextLRIndex = 0 + for i in lr: + assert(i > .0) + else: + self.nextLRIndex = -1 + assert(lr > .0) + + assert all([k > .0 for k in [beta, rho, epsilon]]) + self.tol = tol + if self.tol is not None: + self.tol = abs(float(tol)) + + def __call__(self, objective: Objective, + maxiter: int = None, + initial_values: typing.Dict[Variable, numbers.Real] = None, + variables: typing.List[Variable] = None, + reset_history: bool = True, + method_options: dict = None, + gradient=None, + *args, **kwargs) -> GDResults: + + """ + perform a gradient descent optimization of an objective. + + Parameters + ---------- + objective: Objective: + the objective to optimize. + maxiter: int, optional: + Overrides the optimizer to specify maximum number of iterations to perform. + Default value: use the maxiter supplied to __init__. + initial_values: dict, optional: + initial point at which to begin optimization. + Default None: will be chosen randomly. + variables: list, optional: + which variables to optimize. Note that all variables not to be optimized must be specified in initial_values + Default: optimize all variables of objective. + reset_history: bool: Default = True: + whether or not to wipe the self.history object. + method_options: dict, optional: + dummy keyword to play well with tq.minimize. Does nothing. + gradient: optional: + how to calculate gradients. if str '2-point', will use 2-point numerical gradients; + if str 'qng' will use the default qng optimizer. Other more complex options possible. + args + kwargs + + Returns + ------- + GDResults + all the results of optimization. + """ + + + if self.save_history and reset_history: + self.reset_history() + + self.iteration = 1 + + active_angles, passive_angles, variables = self.initialize_variables(objective, initial_values, variables) + v = {**active_angles, **passive_angles} + + comp = self.prepare(objective=objective, initial_values=v, variables=variables, gradient=gradient) + ### prefactor. Early stopping, initialization, etc. handled here + + if maxiter is None: + maxiter = self.maxiter + + ### the actual algorithm acts here: + e = comp(v, samples=self.samples) + self.history.energies.append(e) + self.history.angles.append(v) + best = e + best_angles = v + v = self.step(comp, v) + last = e + + if not self.silent: + print("iter. <O> Δ<O> max(d<O>) rms(d<O>)") + + for step in range(1, maxiter): + comment = "" + e = comp(v, samples=self.samples) + self.history.energies.append(e) + self.history.angles.append(v) + ### saving best performance + if e < best: + best = e + best_angles = v + + if self.tol != None: + if numpy.abs(e - last) <= self.tol: + if not self.silent: + print('delta f smaller than tolerance {}. Stopping optimization.'.format(str(self.tol))) + break + + ### get new parameters with self.step! + vn = self.step(comp, v) + + # From http://vergil.chemistry.gatech.edu/notes/diis/node3.html + if self.__diis: + self.__diis.push( + numpy.array([vn[k] for k in active_angles]), + numpy.array([vn[k]-v[k] for k in active_angles])) + + new = self.__diis.update() + if new is not None: + self.reset_momenta() + comment = "DIIS" + for i,k in enumerate(active_angles): + vn[k] = new[i] + + + if not self.silent: + self.__dx = numpy.asarray(self.__dx) + print("%3i %+15.8f %+7.2e %7.3e %7.3e %s" + % (step, + e, + e-last, + numpy.max([abs(x) for x in self.__dx]), + numpy.sqrt(numpy.average(self.__dx**2)), + comment)) + + + last = e + v = vn + self.iteration += 1 + E_final, angles_final = best, best_angles + return GDResults(energy=E_final, variables=format_variable_dictionary(angles_final), history=self.history, + moments=self.moments_trajectory[id(comp)], num_iteration=self.iteration) + +
+[docs] + def prepare(self, objective: Objective, initial_values: dict = None, + variables: list = None, gradient=None): + """ + perform all initialization for an objective, register it with lookup tables, and return it compiled. + MUST be called before step is used. + + Parameters + ---------- + objective: Objective: + the objective to ready for optimization. + initial_values: dict, optional: + the initial values of to prepare the optimizer with. + Default: choose randomly. + variables: list, optional: + which variables to optimize over, and hence prepare gradients for. + Default value: optimize over all variables in objective. + gradient: optional: + extra keyword; information used to compile alternate gradients. + Default: prepare the standard, analytical gradient. + + Returns + ------- + Objective: + compiled version of objective. + """ + objective = objective.contract() + active_angles, passive_angles, variables = self.initialize_variables(objective, initial_values, variables) + comp = self.compile_objective(objective=objective) + for arg in comp.args: + if hasattr(arg,'U'): + if arg.U.device is not None: + # don't retrieve computer 100 times; pyquil errors out if this happens! + self.device = arg.U.device + break + + if(self.f == self._spsa): + gradient = {"method": "standard_spsa", "stepsize": self.c, "gamma": self.gamma} + + compile_gradient = True + dE = None + if isinstance(gradient, str): + if gradient.lower() == 'qng': + compile_gradient = False + + combos = get_qng_combos(objective, initial_values=initial_values, backend=self.backend, + device=self.device, + samples=self.samples, noise=self.noise, + ) + dE = QNGVector(combos) + else: + gradient = {"method": gradient, "stepsize": 1.e-4} + + elif isinstance(gradient,dict): + if gradient['method'] == 'qng': + func = gradient['function'] + compile_gradient = False + combos = get_qng_combos(objective, func=func, initial_values=initial_values, backend=self.backend, + device=self.device, + samples=self.samples, noise=self.noise) + dE = QNGVector(combos) + + if compile_gradient: + grad_obj, comp_grad_obj = self.compile_gradient(objective=objective, variables=variables, gradient=gradient) + spsa = isinstance(gradient, dict) and "method" in gradient and isinstance(gradient["method"], str) and "spsa" in gradient["method"].lower() + if spsa: + dE = comp_grad_obj + if(self.calibrate_lr): + self.lr = dE.calibrated_lr(self.lr,initial_values, 50, samples=self.samples) + else: + dE = CallableVector([comp_grad_obj[k] for k in comp_grad_obj.keys()]) + + ostring = id(comp) + if not self.silent: + print(self) + print("{:15} : {} expectationvalues".format("Objective", objective.count_expectationvalues())) + if compile_gradient: + if not spsa: + counts = [x.count_expectationvalues() for x in comp_grad_obj.values()] + print("{:15} : {} expectationvalues".format("Gradient", sum(counts))) + print("{:15} : {}".format("gradient instr", gradient)) + print("{:15} : {}".format("active variables", len(active_angles))) + + vec_len = len(active_angles) + first = numpy.zeros(vec_len) + second = numpy.zeros(vec_len) + + self.gradient_lookup[ostring] = dE + self.active_key_lookup[ostring] = active_angles.keys() + self.moments_lookup[ostring] = (first, second) + self.moments_trajectory[ostring] = [(first, second)] + self.step_lookup[ostring] = 0 + return comp
+ + +
+[docs] + def step(self, objective: Objective, parameters: typing.Dict[Variable, numbers.Real]) -> \ + typing.Dict[Variable, numbers.Real]: + """ + perform a single optimization step and return suggested parameters. + Parameters + ---------- + objective: Objective: + the compiled objective, to perform an optimization step for. MUST be one returned by prepare. + parameters: dict: + the parameters to use in performing the optimization step. + + Returns + ------- + dict + dict of new suggested parameters. + """ + s = id(objective) + try: + gradients = self.gradient_lookup[s] + active_keys = self.active_key_lookup[s] + last_moment = self.moments_lookup[s] + adam_step = self.step_lookup[s] + except: + raise TequilaException( + 'Could not retrieve necessary information. Please use the prepare function before optimizing!') + new, moments, grads = self.f(step=adam_step, + gradients=gradients, + active_keys=active_keys, + moments=last_moment, + v=parameters, + iteration=self.iteration) + back = {**parameters} + for k in new.keys(): + back[k] = new[k] + save_grad = {} + self.moments_lookup[s] = moments + self.moments_trajectory[s].append(moments) + if self.save_history: + for i, k in enumerate(active_keys): + save_grad[k] = grads[i] + self.history.gradients.append(save_grad) + self.step_lookup[s] += 1 + self.__dx = grads # most recent gradient + return back
+ + +
+[docs] + def reset_stepper(self): + """ + reset all information about all prepared objectives. + Returns + ------- + None + """ + self.moments_trajectory = {} + self.moments_lookup = {} + self.step_lookup = {} + self.gradient_lookup = {} + self.reset_history()
+ + +
+[docs] + def reset_momenta(self): + """ + reset moment information about all prepared objectives. + Returns + ------- + None + """ + for k in self.moments_lookup.keys(): + m = self.moments_lookup[k] + vlen = len(m[0]) + first = numpy.zeros(vlen) + second = numpy.zeros(vlen) + self.moments_lookup[k] = (first, second) + self.moments_trajectory[k] = [(first, second)] + self.step_lookup[k] = 0
+ + +
+[docs] + def reset_momenta_for(self, objective: Objective): + """ + reset moment information about a specific objective. + Parameters + ---------- + objective: Objective: + the objective whose information should be reset. + + Returns + ------- + None + """ + k = id(objective) + try: + m = self.moments_lookup[k] + vlen = len(m[0]) + first = numpy.zeros(vlen) + second = numpy.zeros(vlen) + self.moments_lookup[k] = (first, second) + self.moments_trajectory[k] = [(first, second)] + self.step_lookup[k] = 0 + except: + print('found no compiled objective with id {} in lookup. Did you pass the correct object?'.format(k))
+ + + def _adam(self, gradients, step, + v, moments, active_keys, + **kwargs): + + learningRate = self.nextLearningRate() + t = step + 1 + s = moments[0] + r = moments[1] + grads = gradients(v, samples=self.samples) + s = self.beta * s + (1 - self.beta) * grads + r = self.rho * r + (1 - self.rho) * numpy.square(grads) + s_hat = s / (1 - self.beta ** t) + r_hat = r / (1 - self.rho ** t) + updates = [] + for i in range(len(grads)): + rule = - learningRate * s_hat[i] / (numpy.sqrt(r_hat[i]) + self.epsilon) + updates.append(rule) + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] + updates[i] + back_moment = [s, r] + return new, back_moment, grads + + def _adagrad(self, gradients, + v, moments, active_keys, **kwargs): + + learningRate = self.nextLearningRate() + r = moments[1] + grads = gradients(v, self.samples) + + r += numpy.square(grads) + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] - learningRate * grads[i] / numpy.sqrt(r[i] + self.epsilon) + + back_moments = [moments[0], r] + return new, back_moments, grads + + def _adamax(self, gradients, + v, moments, active_keys, **kwargs): + + learningRate = self.nextLearningRate() + s = moments[0] + r = moments[1] + grads = gradients(v, samples=self.samples) + s = self.beta * s + (1 - self.beta) * grads + r = self.rho * r + (1 - self.rho) * numpy.linalg.norm(grads, numpy.inf) + updates = [] + for i in range(len(grads)): + rule = - learningRate * s[i] / r[i] + updates.append(rule) + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] + updates[i] + back_moment = [s, r] + return new, back_moment, grads + + def _nadam(self, step, gradients, + v, moments, active_keys, + **kwargs): + + learningRate = self.nextLearningRate() + s = moments[0] + r = moments[1] + t = step + 1 + grads = gradients(v, samples=self.samples) + s = self.beta * s + (1 - self.beta) * grads + r = self.rho * r + (1 - self.rho) * numpy.square(grads) + s_hat = s / (1 - self.beta ** t) + r_hat = r / (1 - self.rho ** t) + updates = [] + for i in range(len(grads)): + rule = - learningRate * (self.beta * s_hat[i] + (1 - self.beta) * grads[i] / (1 - self.beta ** t)) / ( + numpy.sqrt(r_hat[i]) + self.epsilon) + updates.append(rule) + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] + updates[i] + back_moment = [s, r] + return new, back_moment, grads + + def _sgd(self, gradients, + v, moments, active_keys, **kwargs): + + learningRate = self.nextLearningRate() + grads = gradients(v, samples=self.samples) + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] - learningRate * grads[i] + return new, moments, grads + + def _spsa(self, gradients, v, moments, active_keys, **kwargs): + + learningRate = self.nextLearningRate() + grads = gradients(v, samples=self.samples, iteration=self.iteration) + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] - learningRate * grads[i] + return new, moments, grads + + def _momentum(self, gradients, + v, moments, active_keys, **kwargs): + + learningRate = self.nextLearningRate() + m = moments[0] + grads = gradients(v, samples=self.samples) + + m = self.beta * m - learningRate * grads + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] + m[i] + + back_moments = [m, moments[1]] + return new, back_moments, grads + + def _nesterov(self, gradients, + v, moments, active_keys, **kwargs): + + learningRate = self.nextLearningRate() + m = moments[0] + + interim = {} + for i, k in enumerate(active_keys): + interim[k] = v[k] + self.beta * m[i] + active_keyset = set([k for k in active_keys]) + total_keyset = set([k for k in v.keys()]) + for k in total_keyset: + if k not in active_keyset: + interim[k] = v[k] + grads = gradients(interim, samples=self.samples) + + m = self.beta * m - learningRate * grads + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] + m[i] + + back_moments = [m, moments[1]] + return new, back_moments, grads + + def _rms(self, gradients, + v, moments, active_keys, + **kwargs): + + learningRate = self.nextLearningRate() + r = moments[1] + grads = gradients(v, samples=self.samples) + r = self.rho * r + (1 - self.rho) * numpy.square(grads) + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] - learningRate * grads[i] / numpy.sqrt(self.epsilon + r[i]) + + back_moments = [moments[0], r] + return new, back_moments, grads + + def _rms_nesterov(self, gradients, + v, moments, active_keys, + **kwargs): + + learningRate = self.nextLearningRate() + m = moments[0] + r = moments[1] + + interim = {} + for i, k in enumerate(active_keys): + interim[k] = v[k] + self.beta * m[i] + active_keyset = set([k for k in active_keys]) + total_keyset = set([k for k in v.keys()]) + for k in total_keyset: + if k not in active_keyset: + interim[k] = v[k] + grads = gradients(interim, samples=self.samples) + + r = self.rho * r + (1 - self.rho) * numpy.square(grads) + for i in range(len(m)): + m[i] = self.beta * m[i] - learningRate * grads[i] / numpy.sqrt(r[i]) + new = {} + for i, k in enumerate(active_keys): + new[k] = v[k] + m[i] + + back_moments = [m, r] + return new, back_moments, grads + +
+[docs] + def nextLearningRate(self): + """ Return the learning rate to use + + Returns + ------- + float representing the learning rate to use + """ + if(self.nextLRIndex == -1): + if(self.alpha != None): + return self.lr/(self.iteration ** self.alpha) + return self.lr + else: + if(self.nextLRIndex != len(self.lr) - 1): + self.nextLRIndex += 1 + return self.lr[self.nextLRIndex-1] + else: + return self.lr[self.nextLRIndex]
+
+ + +
+[docs] +class DIIS: + def __init__(self: 'DIIS', + ndiis: int =8, + min_vectors: int = 3, + tol: float = 5e-2, + drop: str='error', + ) -> None: + """DIIS accelerator for gradient descent methods. + + Setup a DIIS accelerator. Every gradient step, the optimizer should + call the push() method to update the DIIS internal list of error + vectors (i.e. gradients) and parameter vectors. A DIIS parameter + vector can be requested using the update() method. update() returns + None if DIIS is not yet active. + + DIIS activates when max(error) falls below tol and the number of + push() has been called more than min_vectors. When the number of DIIS + vectors exceed ndiis, older vectors are dropped according to, + - Age, if drop == 'first' + - Error magnitude if drop == 'error' (the default). + + Note: DIIS only works when the optimizer is fairly close to the sought + value. If initiated too far, the DIIS iteration will often start + oscillating wildly and generally not converge at all. However, if DIIS + is initiated close to the true solution, the acceleration can be + massive, and will often yields the last few sig figs way faster than + GD on its own. + + + Parameters + ---------- + ndiis: int: + Maximum number of vectors to use in DIIS calculations. + min_vectors: int: + Minimum number of vectors before DIIS iteration starts. + tol: float: + DIIS iteration activates when |d<O>| < tol. + drop: string: + Strategy for dropping old vectors. One of {'error', 'first'}. + + Returns + ------- + None + + """ + self.ndiis = ndiis + self.min_vectors = min_vectors + self.tol = tol + self.error = [] + self.P = [] + + if drop == 'error': + self.drop = self.drop_error + elif drop == 'first': + self.drop = self.drop_first + else: + raise NotImplementedError("Drop type %s not implemented" % drop) + +
+[docs] + def reset(self: 'DIIS') -> None: + """Reset containers.""" + self.P = [] + self.error = []
+ + +
+[docs] + def drop_first(self: 'DIIS', + p: typing.Sequence[numpy.ndarray], + e: typing.Sequence[numpy.ndarray] + ) -> typing.Tuple[typing.List[numpy.ndarray], typing.List[numpy.ndarray]]: + """Return P,E with the first element removed.""" + return p[1:], e[1:]
+ + +
+[docs] + def drop_error(self: 'DIIS', + p: typing.Sequence[numpy.ndarray], + e: typing.Sequence[numpy.ndarray] + ) -> typing.Tuple[typing.List[numpy.ndarray], typing.List[numpy.ndarray]]: + """Return P,E with the largest magnitude error vector removed.""" + i = numpy.argmax([v.dot(v) for v in e]) + return p[:i] + p[i+1:], e[:i] + e[i+1:]
+ + +
+[docs] + def push(self: 'DIIS', + param_vector: numpy.ndarray, + error_vector: numpy.ndarray + ) -> None: + """Update DIIS calculator with parameter and error vectors.""" + if len(self.error) == self.ndiis: + self.drop(self.P, self.error) + + self.error += [error_vector] + self.P += [param_vector]
+ + +
+[docs] + def do_diis(self: 'DIIS') -> bool: + """Return with DIIS should be performed.""" + if len(self.error) < self.min_vectors: + # No point in DIIS with less than 2 vectors! + return False + + if max(numpy.abs(self.error[-1])) > self.tol: + return False + + return True
+ + +
+[docs] + def update(self:'DIIS') -> typing.Optional[numpy.ndarray]: + """Get update parameter from DIIS iteration, or None if DIIS is not doable.""" + # Check if we should do DIIS + if not self.do_diis(): + return None + + # Making the B matrix + N = len(self.error) + B = numpy.zeros((N+1, N+1)) + for i in range(N): + for j in range(i,N): + B[i,j] = self.error[i].dot(self.error[j]) + B[j,i] = B[i,j] + + B[N,:] = -1 + B[:,N] = -1 + B[N,N] = 0 + + # Making the K vector + K = numpy.zeros((N+1,)) + K[-1] = -1.0 + + # Solve DIIS for great convergence! + try: + diis_v, res, rank, s = numpy.linalg.lstsq(B,K,rcond=None) + except numpy.linalg.LinAlgError: + self.reset() + return None + + new = diis_v[:-1].dot(self.P) + return new
+
+ + + +
+[docs] +def minimize(objective: Objective, + lr: typing.Union[float, typing.List[float]] = 0.1, + method='sgd', + initial_values: typing.Dict[typing.Hashable, numbers.Real] = None, + variables: typing.List[typing.Hashable] = None, + gradient: str = None, + samples: int = None, + maxiter: int = 100, + diis: int = None, + backend: str = None, + noise: NoiseModel = None, + device: str = None, + tol: float = None, + silent: bool = False, + save_history: bool = True, + alpha: float = None, + gamma: float = None, + beta: float = 0.9, + rho: float = 0.999, + c: typing.Union[float, typing.List[float]] = 0.2, + epsilon: float = 1. * 10 ** (-7), + calibrate_lr: bool = False, + *args, + **kwargs) -> GDResults: + + """ Initialize and call the GD optimizer. + Parameters + ---------- + objective: Objective : + The tequila objective to optimize + lr: float or list of floats >0: + the learning rate. Default 0.1. + alpha: float >0: + scaling factor to adjust learning rate each iteration. default None + gamma: float >0: + scaling facto to adjust step for gradient in spsa method. default None + beta: float >0: + scaling factor for first moments. default 0.9 + rho: float >0: + scaling factor for second moments. default 0.999 + c: float or list of floats: + stepsize for the gradient of the spsa method + epsilon: float>0: + small float for stability of division. default 10^-7 + method: string: Default = 'sgd' + which variation on Gradient Descent to use. Options include 'sgd','adam','nesterov','adagrad','rmsprop', etc. + initial_values: typing.Dict[typing.Hashable, numbers.Real], optional: + Initial values as dictionary of Hashable types (variable keys) and floating point numbers. If given None, + they will all be set to zero + variables: typing.List[typing.Hashable], optional: + List of Variables to optimize + gradient: optional: + the gradient to use. If None, calculated in the usual way. if str='qng', then the qng is calculated. + If a dictionary of objectives, those objectives are used. If another dictionary, + an attempt will be made to interpret that dictionary to get, say, numerical gradients. + samples: int, optional: + samples/shots to take in every run of the quantum circuits (None activates full wavefunction simulation) + maxiter: int : Default = 100: + the maximum number of iterations to run. + diis: int, optional: + Number of iteration before starting DIIS acceleration. + backend: str, optional: + Simulation backend which will be automatically chosen if set to None + noise: NoiseModel, optional: + a NoiseModel to apply to all expectation values in the objective. + device: optional: + the device from which to (potentially, simulatedly) sample all quantum circuits employed in optimization. + tol: float : Default = 10^-4 + Convergence tolerance for optimization; if abs(delta f) smaller than tol, stop. + silent: bool : Default = False: + No printout if True + save_history: bool: Default = True: + Save the history throughout the optimization + calibrate_lr: bool: Default = False: + Calibrates the value of the learning rate + + Note + ---- + + optional kwargs may include beta, beta2, and rho, parameters which affect + (but do not need to be altered) the various method algorithms. + + Returns + ------- + GDResults: + the results of an optimization. + + """ + if isinstance(gradient, dict) or hasattr(gradient, "items"): + if all([isinstance(x, Objective) for x in gradient.values()]): + gradient = format_variable_dictionary(gradient) + optimizer = OptimizerGD(save_history=save_history, + method=method, + lr=lr, + alpha=alpha, + gamma=gamma, + beta=beta, + rho=rho, + c=c, + tol=tol, + diis=diis, + epsilon=epsilon, + samples=samples, backend=backend, + device=device, + noise=noise, + maxiter=maxiter, + silent=silent, + calibrate_lr=calibrate_lr) + return optimizer(objective=objective, + maxiter=maxiter, + gradient=gradient, + initial_values=initial_values, + variables=variables, *args, **kwargs)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/optimizers/optimizer_scipy.html b/docs/sphinx/_modules/tequila_code/optimizers/optimizer_scipy.html new file mode 100644 index 0000000..0d17db4 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/optimizers/optimizer_scipy.html @@ -0,0 +1,548 @@ + + + + + + + + tequila_code.optimizers.optimizer_scipy — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.optimizers.optimizer_scipy

+import scipy, numpy, typing, numbers
+from tequila.objective import Objective
+from tequila.objective.objective import assign_variable, Variable, format_variable_dictionary, format_variable_list
+from .optimizer_base import Optimizer, OptimizerResults
+from ._containers import _EvalContainer, _GradContainer, _HessContainer, _QngContainer
+from tequila.utils.exceptions import TequilaException
+from tequila.circuit.noise import NoiseModel
+from tequila.tools.qng import get_qng_combos
+
+from dataclasses import dataclass
+
+
+[docs] +class TequilaScipyException(TequilaException): + """ """ + pass
+ + +
+[docs] +@dataclass +class SciPyResults(OptimizerResults): + + scipy_result: scipy.optimize.OptimizeResult = None
+ + + + +
+[docs] +class OptimizerSciPy(Optimizer): + """ + Class wrapping over the scipy optimizer for use by Tequila. + + Attributes + ---------- + method: + The scipy optimization method passed as string. + tol: + See scipy documentation for the method you picked + method_options: + See scipy documentation for the method you picked + method_bounds: + See scipy documentation for the method you picked + method_constraints: + See scipy documentation for the method you picked + silent: + if False, the optimizer prints out all evaluated energies + """ + gradient_free_methods = ['NELDER-MEAD', 'COBYLA', 'POWELL', 'SLSQP'] + gradient_based_methods = ['L-BFGS-B', 'BFGS', 'CG', 'TNC'] + hessian_based_methods = ["TRUST-KRYLOV", "NEWTON-CG", "DOGLEG", "TRUST-NCG", "TRUST-EXACT", "TRUST-CONSTR"] + +
+[docs] + @classmethod + def available_methods(cls): + """:return: All tested available methods""" + return cls.gradient_free_methods + cls.gradient_based_methods + cls.hessian_based_methods
+ + + def __init__(self, method: str = "L-BFGS-B", + tol: numbers.Real = None, + method_options=None, + method_bounds=None, + method_constraints=None, + **kwargs): + """ + Parameters + ---------- + method: str: Default = 'L-BFGS-B': + The scipy optimization method passed as string. + tol: float, optional: + See scipy documentation for the method you picked + method_options: optional: + See scipy documentation for the method you picked + method_bounds: optional: + See scipy documentation for the method you picked + method_constraints: optional: + See scipy documentation for the method you picked + silent: bool: + if False the optimizer prints out all evaluated energies + """ + super().__init__(**kwargs) + if hasattr(method, "upper"): + self.method = method.upper() + else: + self.method = method + self.tol = tol + self.method_options = method_options + + if method_bounds is not None: + method_bounds = {assign_variable(k): v for k, v in method_bounds.items()} + self.method_bounds = method_bounds + + if method_options is None: + self.method_options = {'maxiter': self.maxiter} + else: + self.method_options = method_options + if 'maxiter' not in method_options: + self.method_options['maxiter'] = self.maxiter + + self.method_options['disp'] = self.print_level > 0 + + if method_constraints is None: + self.method_constraints = () + else: + self.method_constraints = method_constraints + + def __call__(self, objective: Objective, + variables: typing.List[Variable] = None, + initial_values: typing.Dict[Variable, numbers.Real] = None, + gradient: typing.Dict[Variable, Objective] = None, + hessian: typing.Dict[typing.Tuple[Variable, Variable], Objective] = None, + reset_history: bool = True, + *args, + **kwargs) -> SciPyResults: + + """ + Perform optimization using scipy optimizers. + + Parameters + ---------- + objective: Objective: + the objective to optimize. + variables: list, optional: + the variables of objective to optimize. If None: optimize all. + initial_values: dict, optional: + a starting point from which to begin optimization. Will be generated if None. + gradient: optional: + Information or object used to calculate the gradient of objective. Defaults to None: get analytically. + hessian: optional: + Information or object used to calculate the hessian of objective. Defaults to None: get analytically. + reset_history: bool: Default = True: + whether or not to reset all history before optimizing. + args + kwargs + + Returns + ------- + ScipyReturnType: + the results of optimization. + """ + objective = objective.contract() + infostring = "{:15} : {}\n".format("Method", self.method) + infostring += "{:15} : {} expectationvalues\n".format("Objective", objective.count_expectationvalues()) + + if gradient is not None: + infostring += "{:15} : {}\n".format("grad instr", gradient) + if hessian is not None: + infostring += "{:15} : {}\n".format("hess_instr", hessian) + + if self.save_history and reset_history: + self.reset_history() + + active_angles, passive_angles, variables = self.initialize_variables(objective, initial_values, variables) + + # Transform the initial value directory into (ordered) arrays + param_keys, param_values = zip(*active_angles.items()) + param_values = numpy.array(param_values) + + # process and initialize scipy bounds + bounds = None + if self.method_bounds is not None: + bounds = {k: None for k in active_angles} + for k, v in self.method_bounds.items(): + if k in bounds: + bounds[k] = v + infostring += "{:15} : {}\n".format("bounds", self.method_bounds) + names, bounds = zip(*bounds.items()) + assert (names == param_keys) # make sure the bounds are not shuffled + + # do the compilation here to avoid costly recompilation during the optimization + compiled_objective = self.compile_objective(objective=objective, *args, **kwargs) + E = _EvalContainer(objective=compiled_objective, + param_keys=param_keys, + samples=self.samples, + passive_angles=passive_angles, + save_history=self.save_history, + print_level=self.print_level) + + compile_gradient = self.method in (self.gradient_based_methods + self.hessian_based_methods) + compile_hessian = self.method in self.hessian_based_methods + + dE = None + ddE = None + # detect if numerical gradients shall be used + # switch off compiling if so + if isinstance(gradient, str): + if gradient.lower() == 'qng': + compile_gradient = False + if compile_hessian: + raise TequilaException('Sorry, QNG and hessian not yet tested together.') + + combos = get_qng_combos(objective, initial_values=initial_values, backend=self.backend, + samples=self.samples, noise=self.noise) + dE = _QngContainer(combos=combos, param_keys=param_keys, passive_angles=passive_angles) + infostring += "{:15} : QNG {}\n".format("gradient", dE) + else: + dE = gradient + compile_gradient = False + if compile_hessian: + compile_hessian = False + if hessian is None: + hessian = gradient + infostring += "{:15} : scipy numerical {}\n".format("gradient", dE) + infostring += "{:15} : scipy numerical {}\n".format("hessian", ddE) + + if isinstance(gradient,dict) and "method" in gradient: + if gradient['method'] == 'qng': + func = gradient['function'] + compile_gradient = False + if compile_hessian: + raise TequilaException('Sorry, QNG and hessian not yet tested together.') + + combos = get_qng_combos(objective,func=func, initial_values=initial_values, backend=self.backend, + samples=self.samples, noise=self.noise) + dE = _QngContainer(combos=combos, param_keys=param_keys, passive_angles=passive_angles) + infostring += "{:15} : QNG {}\n".format("gradient", dE) + + if isinstance(hessian, str): + ddE = hessian + compile_hessian = False + + if compile_gradient: + grad_obj, comp_grad_obj = self.compile_gradient(objective=objective, variables=variables, gradient=gradient, *args, **kwargs) + expvals = sum([o.count_expectationvalues() for o in comp_grad_obj.values()]) + infostring += "{:15} : {} expectationvalues\n".format("gradient", expvals) + dE = _GradContainer(objective=comp_grad_obj, + param_keys=param_keys, + samples=self.samples, + passive_angles=passive_angles, + save_history=self.save_history, + print_level=self.print_level) + if compile_hessian: + hess_obj, comp_hess_obj = self.compile_hessian(variables=variables, + hessian=hessian, + grad_obj=grad_obj, + comp_grad_obj=comp_grad_obj, *args, **kwargs) + expvals = sum([o.count_expectationvalues() for o in comp_hess_obj.values()]) + infostring += "{:15} : {} expectationvalues\n".format("hessian", expvals) + ddE = _HessContainer(objective=comp_hess_obj, + param_keys=param_keys, + samples=self.samples, + passive_angles=passive_angles, + save_history=self.save_history, + print_level=self.print_level) + if self.print_level > 0: + print(self) + print(infostring) + print("{:15} : {}\n".format("active variables", len(active_angles))) + + Es = [] + + optimizer_instance = self + class SciPyCallback: + energies = [] + gradients = [] + hessians = [] + angles = [] + real_iterations = 0 + + def __call__(self, *args, **kwargs): + self.energies.append(E.history[-1]) + self.angles.append(E.history_angles[-1]) + if dE is not None and not isinstance(dE, str): + self.gradients.append(dE.history[-1]) + if ddE is not None and not isinstance(ddE, str): + self.hessians.append(ddE.history[-1]) + self.real_iterations += 1 + if 'callback' in optimizer_instance.kwargs: + optimizer_instance.kwargs['callback'](E.history_angles[-1]) + + callback = SciPyCallback() + res = scipy.optimize.minimize(E, x0=param_values, jac=dE, hess=ddE, + args=(Es,), + method=self.method, tol=self.tol, + bounds=bounds, + constraints=self.method_constraints, + options=self.method_options, + callback=callback) + + # failsafe since callback is not implemented everywhere + if callback.real_iterations == 0: + real_iterations = range(len(E.history)) + + if self.save_history: + self.history.energies = callback.energies + self.history.energy_calls = E.history + self.history.angles = callback.angles + self.history.angles_calls = E.history_angles + self.history.gradients = callback.gradients + self.history.hessians = callback.hessians + if dE is not None and not isinstance(dE, str): + self.history.gradient_calls = dE.history + if ddE is not None and not isinstance(ddE, str): + self.history.hessian_calls = ddE.history + + # some methods like "cobyla" do not support callback functions + if len(self.history.energies) == 0: + self.history.energies = E.history + self.history.angles = E.history_angles + + # some scipy methods always give back the last value and not the minimum (e.g. cobyla) + ea = sorted(zip(E.history, E.history_angles), key=lambda x: x[0]) + E_final = ea[0][0] + angles_final = ea[0][1] #dict((param_keys[i], res.x[i]) for i in range(len(param_keys))) + angles_final = {**angles_final, **passive_angles} + + return SciPyResults(energy=E_final, history=self.history, variables=format_variable_dictionary(angles_final), scipy_result=res)
+ + + +
+[docs] +def available_methods(energy=True, gradient=True, hessian=True) -> typing.List[str]: + """Convenience + Parameters + ---------- + energy : + (Default value = True) + gradient : + (Default value = True) + hessian : + (Default value = True) + + Returns + ------- + Available methods of the scipy optimizer, a list of strings. + + """ + methods = [] + if energy: + methods += OptimizerSciPy.gradient_free_methods + if gradient: + methods += OptimizerSciPy.gradient_based_methods + if hessian: + methods += OptimizerSciPy.hessian_based_methods + return methods
+ + + +
+[docs] +def minimize(objective: Objective, + gradient: typing.Union[str, typing.Dict[Variable, Objective]] = None, + hessian: typing.Union[str, typing.Dict[typing.Tuple[Variable, Variable], Objective]] = None, + initial_values: typing.Dict[typing.Hashable, numbers.Real] = None, + variables: typing.List[typing.Hashable] = None, + samples: int = None, + maxiter: int = 100, + backend: str = None, + backend_options: dict = None, + noise: NoiseModel = None, + device: str = None, + method: str = "BFGS", + tol: float = 1.e-3, + method_options: dict = None, + method_bounds: typing.Dict[typing.Hashable, numbers.Real] = None, + method_constraints=None, + silent: bool = False, + save_history: bool = True, + *args, + **kwargs) -> SciPyResults: + """ + + Parameters + ---------- + objective: Objective : + The tequila objective to optimize + gradient: typing.Union[str, typing.Dict[Variable, Objective], None] : Default value = None): + '2-point', 'cs' or '3-point' for numerical gradient evaluation (does not work in combination with all optimizers), + dictionary of variables and tequila objective to define own gradient, + None for automatic construction (default) + Other options include 'qng' to use the quantum natural gradient. + hessian: typing.Union[str, typing.Dict[Variable, Objective], None], optional: + '2-point', 'cs' or '3-point' for numerical gradient evaluation (does not work in combination with all optimizers), + dictionary (keys:tuple of variables, values:tequila objective) to define own gradient, + None for automatic construction (default) + initial_values: typing.Dict[typing.Hashable, numbers.Real], optional: + Initial values as dictionary of Hashable types (variable keys) and floating point numbers. If given None they will all be set to zero + variables: typing.List[typing.Hashable], optional: + List of Variables to optimize + samples: int, optional: + samples/shots to take in every run of the quantum circuits (None activates full wavefunction simulation) + maxiter: int : (Default value = 100): + max iters to use. + backend: str, optional: + Simulator backend, will be automatically chosen if set to None + backend_options: dict, optional: + Additional options for the backend + Will be unpacked and passed to the compiled objective in every call + noise: NoiseModel, optional: + a NoiseModel to apply to all expectation values in the objective. + method: str : (Default = "BFGS"): + Optimization method (see scipy documentation, or 'available methods') + tol: float : (Default = 1.e-3): + Convergence tolerance for optimization (see scipy documentation) + method_options: dict, optional: + Dictionary of options + (see scipy documentation) + method_bounds: typing.Dict[typing.Hashable, typing.Tuple[float, float]], optional: + bounds for the variables (see scipy documentation) + method_constraints: optional: + (see scipy documentation + silent: bool : + No printout if True + save_history: bool: + Save the history throughout the optimization + + Returns + ------- + SciPyReturnType: + the results of optimization + """ + if isinstance(gradient, dict) or hasattr(gradient, "items"): + if all([isinstance(x, Objective) for x in gradient.values()]): + gradient = format_variable_dictionary(gradient) + if isinstance(hessian, dict) or hasattr(hessian, "items"): + if all([isinstance(x, Objective) for x in hessian.values()]): + hessian = {(assign_variable(k[0]), assign_variable([k[1]])): v for k, v in hessian.items()} + method_bounds = format_variable_dictionary(method_bounds) + + # set defaults + + optimizer = OptimizerSciPy(save_history=save_history, + maxiter=maxiter, + method=method, + method_options=method_options, + method_bounds=method_bounds, + method_constraints=method_constraints, + silent=silent, + backend=backend, + backend_options=backend_options, + device=device, + samples=samples, + noise=noise, + tol=tol, + *args, + **kwargs) + return optimizer(objective=objective, + gradient=gradient, + hessian=hessian, + initial_values=initial_values, + variables=variables, *args, **kwargs)
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/quantumchemistry.html b/docs/sphinx/_modules/tequila_code/quantumchemistry.html new file mode 100644 index 0000000..b952cee --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/quantumchemistry.html @@ -0,0 +1,302 @@ + + + + + + + + tequila_code.quantumchemistry — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for tequila_code.quantumchemistry

+import typing
+import warnings
+
+from tequila import TequilaWarning
+from .qc_base import QuantumChemistryBase
+from .chemistry_tools import ParametersQC, NBodyTensor
+from .madness_interface import QuantumChemistryMadness
+
+
+SUPPORTED_QCHEMISTRY_BACKENDS = ["base", "psi4", "madness", "pyscf"]
+INSTALLED_QCHEMISTRY_BACKENDS = {"base": QuantumChemistryBase, "madness": QuantumChemistryMadness}
+
+try:
+    from .psi4_interface import QuantumChemistryPsi4
+
+    INSTALLED_QCHEMISTRY_BACKENDS["psi4"] = QuantumChemistryPsi4
+except ImportError:
+    pass
+
+try:
+    from .pyscf_interface import QuantumChemistryPySCF
+
+    INSTALLED_QCHEMISTRY_BACKENDS["pyscf"] = QuantumChemistryPySCF
+except ImportError:
+    pass
+
+
+
+[docs] +def show_available_modules(): + print("Available QuantumChemistry Modules:") + for k in INSTALLED_QCHEMISTRY_BACKENDS.keys(): + print(k)
+ + + +
+[docs] +def show_supported_modules(): + print(SUPPORTED_QCHEMISTRY_BACKENDS)
+ + + +
+[docs] +def Molecule(geometry: str = None, + basis_set: str = None, + transformation: typing.Union[str, typing.Callable] = None, + orbital_type: str = None, + backend: str = None, + guess_wfn=None, + name: str = None, + *args, + **kwargs) -> QuantumChemistryBase: + """ + + Parameters + ---------- + geometry + molecular geometry as string or as filename (needs to be in xyz format with .xyz ending) + basis_set + quantum chemistry basis set (sto-3g, cc-pvdz, etc) + transformation + The Fermion to Qubit Transformation (jordan-wigner, bravyi-kitaev, bravyi-kitaev-tree and whatever OpenFermion supports) + backend + quantum chemistry backend (psi4, pyscf) + guess_wfn + pass down a psi4 guess wavefunction to start the scf cycle from + can also be a filename leading to a stored wavefunction + name + name of the molecule, if not given it's auto-deduced from the geometry + can also be done vice versa (i.e. geometry is then auto-deduced to name.xyz) + args + kwargs + + Returns + ------- + The Fermion to Qubit Transformation (jordan-wigner, bravyi-kitaev, bravyi-kitaev-tree and whatever OpenFermion supports) + """ + + # failsafe for common mistake + if "basis" in kwargs: + warnings.warn("called molecule with keyword \"basis={0}\" converting it to \"basis_set={0}\"".format(kwargs["basis"]), TequilaWarning) + if basis_set is not None: + warnings.warn("did not convert as \"basis_set={}\" was already given".format(basis_set), TequilaWarning) + basis_set=kwargs["basis"] + + keyvals = {} + for k, v in kwargs.items(): + if k in ParametersQC.__dict__.keys(): + keyvals[k] = v + + if "parameters" in kwargs: + parameters = kwargs["parameters"] + kwargs.pop("parameters") + else: + parameters = ParametersQC(name=name, geometry=geometry, basis_set=basis_set, multiplicity=1, **keyvals) + + integrals_provided = all([key in kwargs for key in ["one_body_integrals", "two_body_integrals"]]) + if integrals_provided and backend is None: + backend = "base" + + if backend is None: + if basis_set is None or basis_set.lower() in ["madness", "mra", "pno"]: + backend = "madness" + basis_set = "mra" + parameters.basis_set = basis_set + if orbital_type is not None and orbital_type.lower() not in ["pno", "mra-pno"]: + warnings.warn("only PNOs supported as orbital_type without basis set. Setting to pno - You gave={}".format(orbital_type), TequilaWarning) + orbital_type = "pno" + else: + if orbital_type is not None and orbital_type.lower() not in ["hf", "native"]: + warnings.warn("only hf and native supported as orbital_type with basis-set. Setting to hf - You gave={}".format(orbital_type), TequilaWarning) + orbital_type = "hf" + if orbital_type is None: + orbital_type = "hf" + + if "psi4" in INSTALLED_QCHEMISTRY_BACKENDS: + backend = "psi4" + elif "pyscf" in INSTALLED_QCHEMISTRY_BACKENDS: + backend = "pyscf" + else: + raise Exception("No quantum chemistry backends installed on your system") + + elif backend == "base": + if not integrals_provided: + raise Exception("No quantum chemistry backends installed on your system\n" + "To use the base functionality you need to pass the following tensors via keyword\n" + "one_body_integrals, two_body_integrals\n") + else: + backend = "base" + + if backend not in SUPPORTED_QCHEMISTRY_BACKENDS: + raise Exception(str(backend) + " is not (yet) supported by tequila") + + if backend not in INSTALLED_QCHEMISTRY_BACKENDS: + raise Exception(str(backend) + " was not found on your system") + + if guess_wfn is not None and backend != 'psi4': + raise Exception("guess_wfn only works for psi4") + + if basis_set is None and backend.lower() not in ["base", "madness"] and not integrals_provided: + raise Exception("no basis_set or integrals provided for backend={}".format(backend)) + elif basis_set is None: + basis_set = "custom" + parameters.basis_set = basis_set + + return INSTALLED_QCHEMISTRY_BACKENDS[backend.lower()](parameters=parameters, transformation=transformation, orbital_type=orbital_type, + guess_wfn=guess_wfn, *args, **kwargs)
+ + + +
+[docs] +def MoleculeFromTequila(mol, transformation=None, backend=None, *args, **kwargs): + c, h, g = mol.get_integrals() + parameters = mol.parameters + if backend is None: + if "pyscf" in INSTALLED_QCHEMISTRY_BACKENDS: + backend = "pyscf" + else: + backend = "base" + if transformation is None: + transformation = mol.transformation + return INSTALLED_QCHEMISTRY_BACKENDS[backend.lower()](parameters=parameters, transformation=transformation, + n_electrons=mol.n_electrons, one_body_integrals=h, + two_body_integrals=g, nuclear_repulsion=c, *args, **kwargs)
+ + + +
+[docs] +def MoleculeFromOpenFermion(molecule, + transformation: typing.Union[str, typing.Callable] = None, + backend: str = None, + *args, + **kwargs) -> QuantumChemistryBase: + """ + Initialize a tequila Molecule directly from an openfermion molecule object + Parameters + ---------- + molecule + The openfermion molecule + transformation + The Fermion to Qubit Transformation (jordan-wigner, bravyi-kitaev, bravyi-kitaev-tree and whatever OpenFermion supports) + backend + The quantum chemistry backend, can be None in this case + Returns + ------- + The tequila molecule + """ + if backend is None: + return QuantumChemistryBase.from_openfermion(molecule=molecule, transformation=transformation, *args, **kwargs) + else: + INSTALLED_QCHEMISTRY_BACKENDS[backend].from_openfermion(molecule=molecule, transformation=transformation, *args, + **kwargs)
+ + + +# needs pyscf (handeled in call) +from .orbital_optimizer import optimize_orbitals +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/quantumchemistry/chemistry_tools.html b/docs/sphinx/_modules/tequila_code/quantumchemistry/chemistry_tools.html new file mode 100644 index 0000000..00e7e67 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/quantumchemistry/chemistry_tools.html @@ -0,0 +1,1450 @@ + + + + + + + + tequila_code.quantumchemistry.chemistry_tools — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.quantumchemistry.chemistry_tools

+import os
+import typing
+import warnings
+from dataclasses import dataclass
+from copy import deepcopy
+from numbers import Real
+import numpy
+
+from tequila import BitString, QCircuit, TequilaException,Variable,compile_circuit
+from tequila.circuit import gates
+try:
+    from openfermion.ops.representations import get_active_space_integrals  # needs openfermion 1.3
+except ImportError as E:
+    raise TequilaException("{}\nplease update openfermion to version 1.3 or higher".format(str(E)))
+
+
+[docs] +@dataclass +class ActiveSpaceData: + """ + Small dataclass to keep the overview in active spaces + Class is used internally + """ + active_orbitals: list = None # active orbitals (spatial, c1) + reference_orbitals: list = None # reference orbitals (spatial, c1) + + def __str__(self): + result = "Active Space Data:\n" + result += "{key:15} : {value:15} \n".format(key="active_orbitals", value=str(self.active_orbitals)) + result += "{key:15} : {value:15} \n".format(key="reference_orbitals", value=str(self.reference_orbitals)) + result += "{key:15} : {value:15} \n".format(key="active_reference_orbitals", + value=str(self.active_reference_orbitals)) + return result + + @property + def frozen_reference_orbitals(self): + return [i for i in self.reference_orbitals if i not in self.active_orbitals] + + @property + def active_reference_orbitals(self): + return [i for i in self.reference_orbitals if i in self.active_orbitals]
+ + + +
+[docs] +class FermionicGateImpl(gates.QubitExcitationImpl): + """ + Small helper class for Fermionic Excictation Gates + Mainly so that "FermionicGate is displayed when circuits are printed + """ + + def __init__(self, generator, p0, transformation, indices=None, *args, **kwargs): + super().__init__(generator=generator, target=generator.qubits, p0=p0, *args, **kwargs) + self._name = "FermionicExcitation" + self.transformation = transformation + self.indices = indices + if not hasattr(indices[0],"__len__"): + self.indices = [(indices[2 * i], indices[2 * i+1]) for i in range(len(indices) // 2)] + self.sign = self.format_excitation_variables(self.indices) + self.indices = self.format_excitation_indices(self.indices) +
+[docs] + def compile(self, *args, **kwargs): + if self.is_convertable_to_qubit_excitation(): + target = [] + for x in self.indices: + for y in x: + target.append(y) + return gates.QubitExcitation(target=target, angle=self.parameter, control=self.control) + else: + if self.transformation.lower().strip("_") == "jordanwigner": + return self.fermionic_excitation(angle=self.sign*self.parameter, indices=self.indices, control=self.control,opt=False) + else: + return gates.Trotterized(generator=self.generator, control=self.control, angle=self.parameter, steps=1)
+ +
+[docs] + def format_excitation_indices(self, idx): + """ + Consistent formatting of excitation indices + idx = [(p0,q0),(p1,q1),...,(pn,qn)] + sorted as: p0<p1<pn and pi<qi + :param idx: list of index tuples describing a single(!) fermionic excitation + :return: list of index tuples + """ + + idx = [tuple(sorted(x)) for x in idx] + idx = sorted(idx, key=lambda x: x[0]) + return list(idx)
+ +
+[docs] + def format_excitation_variables(self, idx): + """ + Consistent formatting of excitation variable + idx = [(p0,q0),(p1,q1),...,(pn,qn)] + sorted as: pi<qi and p0 < p1 < p2 + :param idx: list of index tuples describing a single(!) fermionic excitation + :return: sign of the variable with re-ordered indices + """ + sig = 1 + for pair in idx: + if pair[1]>pair[0]: + sig *= -1 + for pair in range(len(idx)-1): + if idx[pair+1][0]>idx[pair][0]: + sig *= -1 + return sig
+ +
+[docs] + def cCRy(self, target: int, dcontrol: typing.Union[list, int], control: typing.Union[list, int], + angle: typing.Union[Real, Variable, typing.Hashable], case: int = 1) -> QCircuit: + ''' + Compilation of CRy as on https://doi.org/10.1103/PhysRevA.102.062612 + If not control passed, Ry returned + Parameters + ---------- + case: if 1 employs eq. 12 from the paper, if 0 eq. 13 + ''' + if control is not None and not len(control): + control = None + if isinstance(dcontrol, int): + dcontrol = [dcontrol] + if not len(dcontrol): + return compile_circuit(gates.Ry(angle=angle, target=target, control=control)) + else: + if isinstance(angle, str): + angle = Variable(angle) + U = QCircuit() + aux = dcontrol[0] + ctr = deepcopy(dcontrol) + ctr.pop(0) + if case: + U += self.cCRy(target=target, dcontrol=ctr, angle=angle / 2, case=1, control=control) + gates.H( + aux) + gates.CNOT(target, aux) + U += self.cCRy(target=target, dcontrol=ctr, angle=-angle / 2, case=0, control=control) + gates.CNOT( + target, aux) + gates.H(aux) + else: + U += gates.H(aux) + gates.CNOT(target, aux) + self.cCRy(target=target, dcontrol=ctr, angle=-angle / 2, + case=0, control=control) + U += gates.CNOT(target, aux) + gates.H(aux) + self.cCRy(target=target, dcontrol=ctr, angle=angle / 2, + case=1, control=control) + return U
+ + +
+[docs] + def fermionic_excitation(self, angle: typing.Union[Real, Variable, typing.Hashable], indices: typing.List, + control: typing.Union[int, typing.List] = None, opt: bool = True) -> QCircuit: + ''' + Excitation [(i,j),(k,l)],... compiled following https://doi.org/10.1103/PhysRevA.102.062612 + opt: whether to optimized CNOT H CNOT --> Rz Rz CNOT Rz + ''' + lto = [] + lfrom = [] + if isinstance(indices,tuple) and not hasattr(indices[0],"__len__"): + indices = [(indices[2 * i], indices[2 * i + 1]) for i in range(len(indices) // 2)] + for pair in indices: + lfrom.append(pair[0]) + lto.append(pair[1]) + Upair = QCircuit() + if isinstance(angle, str) or isinstance(angle, tuple): + angle = Variable(angle) + for i in range(len(lfrom) - 1): + Upair += gates.CNOT(lfrom[i + 1], lfrom[i]) + Upair += gates.CNOT(lto[i + 1], lto[i]) + Upair += gates.X(lto[i]) + gates.X(lfrom[i]) + Upair += gates.CNOT(lto[-1], lfrom[-1]) + crt = lfrom[::-1] + lto + Uladder = QCircuit() + pairs = lfrom + lto + pairs.sort() + orbs = [] + for o in range(len(pairs) // 2): + orbs += [*range(pairs[2 * o] + 1, pairs[2 * o + 1])] + if len(orbs): + for o in range(len(orbs) - 1): + Uladder += gates.CNOT(orbs[o], orbs[o + 1]) + Uladder += compile_circuit(gates.CZ(orbs[-1], lto[-1])) + crt.pop(-1) + if control is not None and (isinstance(control, int) or len(control) == 1): + if isinstance(control, int): + crt.append(control) + else: + crt = crt + control + control = [] + Ur = self.cCRy(target=lto[-1], dcontrol=crt, angle=angle, control=control) + Upair2 = Upair.dagger() + if opt: + Ur.gates.pop(-1) + Ur.gates.pop(-1) + Upair2.gates.pop(0) + Ur += gates.Rz(numpy.pi / 2, target=lto[-1]) + gates.Rz(-numpy.pi / 2, target=lfrom[-1]) + Ur += gates.CNOT(lto[-1], lfrom[-1]) + gates.Rz(numpy.pi / 2, target=lfrom[-1]) + gates.H(lfrom[-1]) + return Upair + Uladder + Ur + Uladder.dagger() + Upair2
+ + + def __str(self): + if self.indices is not None: + return "FermionicExcitation({})".format(str(self.indices)) + return "FermionicExcitation" + + def __repr__(self): + return self.__str__() + +
+[docs] + def is_convertable_to_qubit_excitation(self): + """ + spin-paired double excitations (both electrons occupy the same spatial orbital and are excited to another spatial orbital) + in the jordan-wigner representation are identical to 4-qubit excitations which can be compiled more efficient + this function hels to automatically detect those cases + Returns + ------- + + """ + return False + if not self.transformation.lower().strip("_") == "jordanwigner": return False + if not len(self.indices) == 2: return False + if not self.indices[0][0] // 2 == self.indices[1][0] // 2: return False + if not self.indices[0][1] // 2 == self.indices[1][1] // 2: return False + return True
+
+ + + +
+[docs] +def prepare_product_state(state: BitString) -> QCircuit: + """Small convenience function + + Parameters + ---------- + state : + product state encoded into a bitstring + state: BitString : + + + Returns + ------- + type + unitary circuit which prepares the product state + + """ + result = QCircuit() + for i, v in enumerate(state.array): + if v == 1: + result += gates.X(target=i) + return result
+ + + +
+[docs] +@dataclass +class ParametersQC: + """Specialization of ParametersHamiltonian""" + basis_set: str = None # Quantum chemistry basis set + geometry: str = None # geometry of the underlying molecule (units: Angstrom!), + # this can be a filename leading to an .xyz file or the geometry given as a string + description: str = "" + multiplicity: int = 1 + charge: int = 0 + name: str = None + frozen_core: bool = True + +
+[docs] + def get_number_of_core_electrons(self): + result = 0 + for atom in self.get_atoms(): + n=self.get_atom_number(atom) + if n>2: + result += 2 + if n>10: + result += 8 + if n>18: + result += 18 + if n>36: + result += 36 + if n>45: + result += 54 + if n>86: + result += 86 + return result
+ + + @property + def n_electrons(self, *args, **kwargs): + return self.get_nuc_charge() - self.charge + +
+[docs] + def get_nuc_charge(self): + return sum(self.get_atom_number(name=atom) for atom in self.get_atoms())
+ + +
+[docs] + def get_atom_number(self, name): + atom_numbers = {"h": 1, "he": 2, "li": 3, "be": 4, "b": 5, "c": 6, "n": 7, "o": 8, "f": 9, "ne": 10, "na": 11, + "mg": 12, "al": 13, "si": 14, "ph": 15, "s": 16, "cl": 17, "ar": 18} + if name.lower() in atom_numbers: + return atom_numbers[name.lower()] + try: + import periodictable as pt + atom = list(name.lower()) + atom[0] = atom[0].upper() + atom = ''.join(atom) + element = pt.elements.symbol(atom) + return element.number + except: + raise TequilaException( + "can not assign atomic number to element {}\npip install periodictable will fix it".format(atom))
+ + +
+[docs] + def get_atoms(self): + return [x[0] for x in self.get_geometry()]
+ + + def __post_init__(self, *args, **kwargs): + + if self.name is None and self.geometry is None: + raise TequilaException( + "no geometry or name given to molecule\nprovide geometry=filename.xyz or geometry=`h 0.0 0.0 0.0\\n...`\nor name=whatever with file whatever.xyz being present") + # auto naming + if self.name is None: + if ".xyz" in self.geometry: + self.name = self.geometry.split(".xyz")[0] + if self.description is None: + coord, description = self.read_xyz_from_file() + self.description = description + else: + atoms = self.get_atoms() + atom_names = sorted(list(set(atoms)), key=lambda x: self.get_atom_number(x), reverse=True) + if self.name is None: + drop_ones = lambda x: "" if x == 1 else x + self.name = "".join(["{}{}".format(x, drop_ones(atoms.count(x))) for x in atom_names]) + self.name = self.name.lower() + + if self.geometry is None: + self.geometry = self.name + ".xyz" + + if ".xyz" in self.geometry and not os.path.isfile(self.geometry): + raise TequilaException("could not find file for molecular coordinates {}".format(self.geometry)) + + @property + def filename(self): + """ """ + return "{}_{}".format(self.name, self.basis_set) + + @property + def molecular_data_param(self) -> dict: + """:return: Give back all parameters for the MolecularData format from openfermion as dictionary""" + return {'basis': self.basis_set, 'geometry': self.get_geometry(), 'description': self.description, + 'charge': self.charge, 'multiplicity': self.multiplicity, 'filename': self.filename + } + +
+[docs] + @staticmethod + def format_element_name(string): + """OpenFermion uses case sensitive hash tables for chemical elements + I.e. you need to name Lithium: 'Li' and 'li' or 'LI' will not work + this convenience function does the naming + :return: first letter converted to upper rest to lower + + Parameters + ---------- + string : + + + Returns + ------- + + """ + assert (len(string) > 0) + assert (isinstance(string, str)) + fstring = string[0].upper() + string[1:].lower() + return fstring
+ + +
+[docs] + @staticmethod + def convert_to_list(geometry): + """Convert a molecular structure given as a string into a list suitable for openfermion + + Parameters + ---------- + geometry : + a string specifying a mol. structure. E.g. geometry="h 0.0 0.0 0.0\n h 0.0 0.0 1.0" + + Returns + ------- + type + A list with the correct format for openfermion E.g return [ ['h',[0.0,0.0,0.0], [..]] + + """ + result = [] + # Remove blank lines + lines = [l for l in geometry.split("\n") if l] + + for line in lines: + words = line.split() + + # Pad coordinates + if len(words) < 4: + words += [0.0] * (4 - len(words)) + + try: + tmp = (ParametersQC.format_element_name(words[0]), + (float(words[1]), float(words[2]), float(words[3]))) + result.append(tmp) + except ValueError: + print("get_geometry list unknown line:\n ", line, "\n proceed with caution!") + return result
+ + +
+[docs] + def get_geometry_string(self) -> str: + """returns the geometry as a string + :return: geometry string + + Parameters + ---------- + + Returns + ------- + + """ + if self.geometry.split('.')[-1] == 'xyz': + geomstring, comment = self.read_xyz_from_file(self.geometry) + if comment is not None: + self.description = comment + return geomstring + else: + return self.geometry
+ + +
+[docs] + def get_geometry(self): + """Returns the geometry + If a xyz filename was given the file is read out + otherwise it is assumed that the geometry was given as string + which is then reformatted as a list usable as input for openfermion + :return: geometry as list + e.g. [(h,(0.0,0.0,0.35)),(h,(0.0,0.0,-0.35))] + Units: Angstrom! + + Parameters + ---------- + + Returns + ------- + + """ + if self.geometry.split('.')[-1] == 'xyz': + geomstring, comment = self.read_xyz_from_file(self.geometry) + if self.description == '': + self.description = comment + return self.convert_to_list(geomstring) + elif self.geometry is not None: + return self.convert_to_list(self.geometry) + else: + raise Exception("Parameters.qc.geometry is None")
+ + +
+[docs] + @staticmethod + def read_xyz_from_file(filename): + """Read XYZ filetype for molecular structures + https://en.wikipedia.org/wiki/XYZ_file_format + Units: Angstrom! + + Parameters + ---------- + filename : + return: + + Returns + ------- + + """ + with open(filename, 'r') as file: + content = file.readlines() + natoms = int(content[0]) + comment = str(content[1]).strip('\n') + coord = '' + for i in range(natoms): + coord += content[2 + i] + return coord, comment
+
+ + + +
+[docs] +@dataclass +class ClosedShellAmplitudes: + """ + Helper Class for clasical amplitudes + used internally + """ + tIjAb: numpy.ndarray = None + tIA: numpy.ndarray = None + +
+[docs] + def make_parameter_dictionary(self, threshold=1.e-8, screening=True): + """ + + Parameters + ---------- + threshold : + (Default value = 1.e-8) + + Returns + ------- + + """ + variables = {} + if self.tIjAb is not None: + nvirt = self.tIjAb.shape[2] + nocc = self.tIjAb.shape[0] + assert (self.tIjAb.shape[1] == nocc and self.tIjAb.shape[3] == nvirt) + for (I, J, A, B), value in numpy.ndenumerate(self.tIjAb): + if not numpy.isclose(value, 0.0, atol=threshold) or not screening: + variables[(nocc + A, I, nocc + B, J)] = value + if self.tIA is not None: + nocc = self.tIA.shape[0] + for (I, A), value, in numpy.ndenumerate(self.tIA): + if not numpy.isclose(value, 0.0, atol=threshold) or not screening: + variables[(A + nocc, I)] = value + return dict(sorted(variables.items(), key=lambda x: numpy.abs(x[1]), reverse=True))
+
+ + + +
+[docs] +@dataclass +class Amplitudes: + """ + Helper class for classical Coupled-Cluster Amplitudes + We adopt the Psi4 notation for consistency + I,A for alpha + i,a for beta + + Parameters + ---------- + + Returns + ------- + + """ + +
+[docs] + @classmethod + def from_closed_shell(cls, cs: ClosedShellAmplitudes): + """ + Initialize from closed-shell Amplitude structure + + Parameters + ---------- + cs: ClosedShellAmplitudes : + + + Returns + ------- + + """ + tijab = cs.tIjAb - numpy.einsum("ijab -> ijba", cs.tIjAb, optimize='greedy') + return cls(tIjAb=cs.tIjAb, tIA=cs.tIA, tiJaB=cs.tIjAb, tia=cs.tIA, tijab=tijab, tIJAB=tijab)
+ + + tIjAb: numpy.ndarray = None + tIA: numpy.ndarray = None + tiJaB: numpy.ndarray = None + tijab: numpy.ndarray = None + tIJAB: numpy.ndarray = None + tia: numpy.ndarray = None + +
+[docs] + def make_parameter_dictionary(self, threshold=1.e-8): + """ + + Parameters + ---------- + threshold : + (Default value = 1.e-8) + Neglect amplitudes below the threshold + + Returns + ------- + Dictionary of tequila variables (hash is in the style of (a,i,b,j)) + + """ + variables = {} + if self.tIjAb is not None: + nvirt = self.tIjAb.shape[2] + nocc = self.tIjAb.shape[0] + assert (self.tIjAb.shape[1] == nocc and self.tIjAb.shape[3] == nvirt) + + for (I, j, A, b), value in numpy.ndenumerate(self.tIjAb): + if not numpy.isclose(value, 0.0, atol=threshold): + variables[(2 * (nocc + A), 2 * I, 2 * (nocc + b) + 1, j + 1)] = value + for (i, J, a, B), value in numpy.ndenumerate(self.tiJaB): + if not numpy.isclose(value, 0.0, atol=threshold): + variables[(2 * (nocc + a) + 1, 2 * i + 1, 2 * (nocc + B), J)] = value + for (i, j, a, b), value in numpy.ndenumerate(self.tijab): + if not numpy.isclose(value, 0.0, atol=threshold): + variables[(2 * (nocc + a) + 1, 2 * i + 1, 2 * (nocc + b) + 1, j + 1)] = value + for (I, J, A, B), value in numpy.ndenumerate(self.tijab): + if not numpy.isclose(value, 0.0, atol=threshold): + variables[(2 * (nocc + A), 2 * I, 2 * (nocc + B), J)] = value + + if self.tIA is not None: + nocc = self.tIjAb.shape[0] + assert (self.tia.shape[0] == nocc) + for (I, A), value, in numpy.ndenumerate(self.tIA): + if not numpy.isclose(value, 0.0, atol=threshold): + variables[(2 * (A + nocc), 2 * I)] = value + for (i, a), value, in numpy.ndenumerate(self.tIA): + if not numpy.isclose(value, 0.0, atol=threshold): + variables[(2 * (a + nocc) + 1, 2 * i + 1)] = value + + return variables
+
+ + + +
+[docs] +class NBodyTensor: + """ Convenience class for handling N-body tensors """ + +
+[docs] + class Ordering: + """ + Convenience to keep track of aliases in odering names for two body integrals + i.e. Mulliken/Chem/1122 + Dirac/Phys/1212 + openfermion/1221 + """ + + def __init__(self, scheme): + if hasattr(scheme, "_scheme"): + scheme = scheme._scheme + elif hasattr(scheme, "scheme"): + scheme = scheme.scheme + self._scheme = self.assign_scheme(scheme) + +
+[docs] + def assign_scheme(self, scheme): + if scheme is None: + return "chem" + else: + scheme = str(scheme) + + if scheme.lower() in ["mulliken", "chem", "c", "1122"]: + return "chem" + elif scheme.lower() in ["dirac", "phys", "p", "1212"]: + return "phys" + elif scheme.lower() in ["openfermion", "of", "o", "1221"]: + return "of" + else: + raise TequilaException( + "Unknown two-body tensor scheme {}. Supported are dirac, mulliken, and openfermion".format(scheme))
+ + +
+[docs] + def is_phys(self): + return self._scheme == "phys"
+ + +
+[docs] + def is_chem(self): + return self._scheme == "chem"
+ + +
+[docs] + def is_of(self): + return self._scheme == "of"
+ + + def __str__(self): + return self._scheme
+ + +
+[docs] + def identify_ordering(self, trials=25): + if len(self.shape) != 4: + return None + chem=False + phys=False + of=False + if self._verify_ordering_mulliken(trials=trials): + chem=self.Ordering(scheme="mulliken") + if self._verify_ordering_dirac(trials=trials): + phys=self.Ordering(scheme="dirac") + if self._verify_ordering_of(trials=trials): + of=self.Ordering(scheme="openfermion") + + uniqueness = (chem,phys,of) + if not uniqueness.count(False) == 2 and trials<100: + return self.identify_ordering(trials=trials*2) + if chem: return self.Ordering(scheme="chem") + elif phys: return self.Ordering(scheme="phys") + elif of: return self.Ordering(scheme="openfermion") + else: + raise Exception("NBTensor ordering could not be identified")
+ + + def _verify_ordering_dirac(self, trials=100): + if len(self.shape) != 4: + return False + # dirac ordering: ijkl = <ij|kl> i.e 1212 + # check for two_body symetries: <ij|kl> = <kj|il> , <il|kj> + elems = self.elems + n = self.shape[0] + for _ in range(trials): + idx = numpy.random.randint(0,n,4) + test1 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[2],idx[1],idx[0],idx[3]], atol=1.e-4) + test2 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[0],idx[3],idx[2],idx[1]], atol=1.e-4) + test3 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[2],idx[3],idx[0],idx[1]], atol=1.e-4) + if not (test1 and test2 and test3): + return False + + return True + + def _verify_ordering_mulliken(self, trials=100): + if len(self.shape) != 4: + return False + # mulliken ordering: ijkl = (ij|kl) i.e 1122 + elems = self.elems + n = self.shape[0] + for _ in range(trials): + idx = numpy.random.randint(0,n,4) + test1 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[1],idx[0],idx[2],idx[3]], atol=1.e-4) + test2 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[0],idx[1],idx[3],idx[2]], atol=1.e-4) + test3 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[1],idx[0],idx[3],idx[2]], atol=1.e-4) + if not (test1 and test2 and test3): + return False + + return True + + def _verify_ordering_of(self, trials=100): + if len(self.shape) != 4: + return False + # openfermion ordering: ijkl = [ij|kl] i.e 1221 + elems = self.elems + n = self.shape[0] + for _ in range(trials): + idx = numpy.random.randint(0,n,4) + test1 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[3],idx[1],idx[2],idx[0]], atol=1.e-4) + test2 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[0],idx[2],idx[1],idx[3]], atol=1.e-4) + test3 = numpy.isclose(elems[idx[0],idx[1],idx[2],idx[3]],elems[idx[3],idx[2],idx[1],idx[0]], atol=1.e-4) + if not (test1 and test2 and test3): + return False + + return True + + def __init__(self, elems: numpy.ndarray = None, active_indices: list = None, ordering: str = None, + size_full: int = None, verify=False): + """ + Parameters + ---------- + elems: Tensor data as numpy array + active_indices: List of active indices in total ordering + ordering: Ordering scheme for two body tensors + "dirac" or "phys": <12|g|12> + .. math:: + g_{pqrs} = \\int d1 d2 p(1)q(2) g(1,2) r(1)s(2) + "mulliken" or "chem": (11|g|22) + .. math:: + g_{pqrs} = \\int d1 d2 p(1)r(2) g(1,2) q(1)s(2) + "openfermion": + .. math:: [12|g|21] + g_{gqprs} = \\int d1 d2 p(1)q(2) g(1,2) s(1)r(2) + + size_full + """ + + # Set elements + self.elems = elems + # Active indices only as list of indices (e.g. spatial orbital indices), not as a dictionary of irreducible + # representations + if active_indices is not None: + self.active_indices = active_indices + self._passive_indices = None + self._full_indices = None + self._indices_set: bool = False + + # Determine order of tensor + # Assume, that tensor is entered in desired shape, not as flat array. + self.order = len(self.elems.shape) + # Can use size_full < self.elems.shape[0] -> 'full' space is to be considered a subspace as well + if size_full is None: + self._size_full = self.elems.shape[0] + else: + self._size_full = size_full + # 2-body tensors (<=> order 4) currently allow reordering + if self.order == 4: + if ordering is None: + ordering = self.identify_ordering() + elif verify: + try: # some RDMs are really sloppy (depends on backend) + auto_ordering=self.identify_ordering() + if auto_ordering is not ordering: + warnings.warn("Auto identified ordering of NBTensor does not match given ordering: {} vs {}".format(auto_ordering, ordering)) + except Exception as E: + warnings.warn("could not verify odering {}".format(ordering)) + self.ordering = self.Ordering(ordering) + else: + if ordering is not None: + raise Exception("Ordering only implemented for tensors of order 4 / 2-body tensors.") + self.ordering = None + + @property + def shape(self, *args, **kwargs): + return self.elems.shape + +
+[docs] + def sub_lists(self, idx_lists: list = None) -> numpy.ndarray: + """ + Get subspace of tensor by a set of index lists + according to hPQ.sub_lists(idx_lists=[p, q]) = [hPQ for P in p and Q in q] + + This essentially is an implementation of a non-contiguous slicing using numpy.take + + Parameters + ---------- + idx_lists : + List of lists, each defining the desired subspace per axis + Size needs to match order of tensor, and lists successively correspond to axis=0,1,2,...,N + + Returns + ------- + out : + Sliced tensor as numpy.ndarray + """ + # Check if index list has correct size + if len(idx_lists) != self.order: + raise Exception("Need to pass an index list for each dimension!" + + " Length of idx_lists needs to match order of tensor.") + + # Perform slicing via numpy.take + out = self.elems + for ax in range(self.order): + if idx_lists[ax] is not None: # None means, we want the full space in this direction + out = numpy.take(out, idx_lists[ax], axis=ax) + + return out
+ + +
+[docs] + def set_index_lists(self): + """ Set passive and full index lists based on class inputs """ + tmp_size = self._size_full + if self._size_full is None: + tmp_size = self.elems.shape[0] + + self._passive_indices = [i for i in range(tmp_size) + if i not in self.active_indices] + self._full_indices = [i for i in range(tmp_size)]
+ + +
+[docs] + def sub_str(self, name: str) -> numpy.ndarray: + """ + Get subspace of tensor by a string + Currently is able to resolve an active space, named 'a', full space 'f', and the complement 'p' = 'f' - 'a'. + Full space in this context may also be smaller than actual tensor dimension. + + The specification of active space in this context only allows to pick a set from a list of orbitals, and + is not able to resolve an active space from irreducible representations. + + Example for one-body tensor: + hPQ.sub_lists(name='ap') = [hPQ for P in active_indices and Q in _passive_indices] + + Parameters + ---------- + name : + String specifying the desired subspace, elements need to be a (active), f (full), p (full - active) + + Returns + ------- + out : + Sliced tensor as numpy.ndarray + """ + if not self._indices_set: + self.set_index_lists() + self._indices_set = True + + if name is None: + raise Exception("No name specified.") + if len(name) != self.order: + raise Exception("Name does not match order of the tensor.") + if self.active_indices is None: + raise Exception("Need to set an active space in order to call this function.") + + idx_lists = [] + # Parse name as string of space indices + for char in name: + if char.lower() == 'a': + idx_lists.append(self.active_indices) + elif char.lower() == 'p': + idx_lists.append(self._passive_indices) + elif char.lower() == 'f': + if self._size_full is None: + idx_lists.append(None) + else: + idx_lists.append(self._full_indices) + else: + raise Exception("Need to specify a valid letter (a,p,f).") + + out = self.sub_lists(idx_lists) + + return out
+ + +
+[docs] + def reorder(self, to: str = 'of'): + """ + Function to reorder tensors according to some convention. + + Parameters + ---------- + to : + Ordering scheme of choice. + 'openfermion', 'of' (default) : + openfermion - ordering, corresponds to integrals of the type + h^pq_rs = int p(1)* q(2)* O(1,2) r(2) s(1) (O(1,2) + with operators a^pq_rs = a^p a^q a_r a_s (a^p == a^dagger_p) + currently needed for dependencies on openfermion-library + 'chem', 'c' : + quantum chemistry ordering, collect particle terms, + more convenient for real-space methods + h^pq_rs = int p(1) q(1) O(1,2) r(2) s(2) + This is output by psi4 + 'phys', 'p' : + typical physics ordering, integrals of type + h^pq_rs = int p(1)* q(2)* O(1,2) r(1) s(2) + with operators a^pq_rs = a^p a^q a_s a_r + + Returns + ------- + """ + if self.order != 4: + warnings.warn('Reordering currently only implemented for two-body tensors.') + return self + + to = self.Ordering(scheme=to) + + if self.ordering == to: + return self + elif self.ordering.is_chem(): + if to.is_of(): + self.elems = numpy.einsum("psqr -> pqrs", self.elems, optimize='greedy') + elif to.is_phys(): + self.elems = numpy.einsum("prqs -> pqrs", self.elems, optimize='greedy') + elif self.ordering.is_of(): + if to.is_chem(): + self.elems = numpy.einsum("pqrs -> psqr", self.elems, optimize='greedy') + elif to.is_phys(): + self.elems = numpy.einsum("pqrs -> pqsr", self.elems, optimize='greedy') + elif self.ordering.is_phys(): + if to.is_chem(): + self.elems = numpy.einsum("pqrs -> prqs", self.elems, optimize='greedy') + elif to.is_of(): + self.elems = numpy.einsum("pqsr -> pqrs", self.elems, optimize='greedy') + + self.ordering=to + return self
+
+ + + +
+[docs] +@dataclass +class OrbitalData: + irrep: str = None # irrep of symmetry group (if assigned) + idx_irrep: int = None # index within the irrep + idx_total: int = None # index within the total set of orbitals + idx: int = None # index within the active space + energy: float = None # energy assigned to orbital + occ: float = None # occupation number assigned to orbital + pair: tuple = None # potential electron pair that the orbital is assigned to + + def __post_init__(self): + # backward compatibility + if self.pair is not None and len(self.pair) == 1: + self.pair = (self.pair[0], self.pair[0]) + self.occ = 2.0 # mark as reference + + def __str__(self): + return "{"+"{}".format("".join(["{}:{}, ".format(k,v) for k,v in self.__dict__.items() if v is not None])).rstrip().rstrip(",")+"}"
+ + +
+[docs] +class IntegralManager: + """ + Manage Basis Integrals of Quantum Chemistry + All integrals are held in their original basis, the corresponding mo-coefficients have to be passed down + and are usually held by the QuantumChemistryBaseClass + """ + _overlap_integrals: numpy.ndarray = None + _one_body_integrals: numpy.ndarray = None + _two_body_integrals: NBodyTensor = None + _constant_term: float = None + _basis_name: str = "unknown" + _orbital_type: str = "unknown" # e.g. "HF", "PNO", "native" + _orbital_coefficients: numpy.ndarray = None + _active_space: ActiveSpaceData = None + _orbitals: typing.List[OrbitalData] = None + + def __init__(self, one_body_integrals, two_body_integrals, + basis_name="unknown", orbital_type="unknown", + constant_term=0.0, orbital_coefficients=None, active_space=None, overlap_integrals=None, orbitals=None, *args, **kwargs): + self._one_body_integrals = one_body_integrals + self._two_body_integrals = two_body_integrals + self._constant_term = constant_term + self._basis_name = basis_name + self._orbital_type = orbital_type + + assert len(self._one_body_integrals.shape) == 2 + assert len(self._two_body_integrals.shape) == 4 + try: + two_body_integrals = two_body_integrals.reorder(to="chem") + except Exception as E: + raise TequilaException( + "{}\ntwo_body_integrals given in wrong format. Needs to be a tq.chemistry.NBodyTensor in chem ordering.\n{} with ordering={}".format( + str(E), str(type(two_body_integrals)), str(two_body_integrals.ordering))) + + for i in range(4): + assert self._one_body_integrals.shape[0] == self._two_body_integrals.elems.shape[i] + assert self._one_body_integrals.shape[0] == self._one_body_integrals.shape[1] + + if overlap_integrals is None: + overlap_integrals = numpy.eye(one_body_integrals.shape[0]) + self._overlap_integrals = overlap_integrals + assert self._overlap_integrals.shape == self._one_body_integrals.shape + + if orbital_coefficients is None: + # default are symmetrically orthogonalized orbitals in the given basis + orbital_coefficients = self.get_orthonormalized_orbital_coefficients() + self._orbital_coefficients = orbital_coefficients + + if orbitals is None: + orbitals = [OrbitalData(idx_total=i, idx=i) for i in range(one_body_integrals.shape[0])] + + self._orbitals = orbitals + self.active_space = active_space + +
+[docs] + def get_orthonormalized_orbital_coefficients(self): + """ + Computes orbitals in this basis that are orthonormal (through loewdin orthonormalization) + + Returns + ------- + coefficient matrix of orthonormalized orbitals + """ + if self.basis_is_orthogonal(): + return numpy.eye(self._one_body_integrals.shape[0]) + + S = self._overlap_integrals + sv, U = numpy.linalg.eigh(S) + s = numpy.diag(numpy.asarray([1.0 / numpy.sqrt(x) for x in sv])) + C = U.dot(s.dot(U.transpose())) + return C
+ + + @property + def active_orbitals(self): + return [self._orbitals[i] for i in self._active_space.active_orbitals] + + @property + def orbitals(self): + return self._orbitals + + @property + def active_space(self): + return self._active_space + + @active_space.setter + def active_space(self, other): + self._active_space = other + for x in self._orbitals: + x.idx = None + for ii,i in enumerate(other.active_orbitals): + self._orbitals[i].idx = ii + + @property + def reference_orbitals(self): + return [self._orbitals[i] for i in self.active_space.reference_orbitals] + + @property + def active_reference_orbitals(self): + return [self._orbitals[i] for i in self.active_space.active_orbitals if i in self.active_space.reference_orbitals] + + @property + def overlap_integrals(self): + """ + Returns + ------- + Overlap integrals in given basis (using basis functions, not molecular orbitals. No active space considered) + """ + return self._overlap_integrals + + @property + def one_body_integrals(self): + """ + Returns + ------- + one_body integrals in given basis (using basis functions, not molecular orbitals. No active space considered) + """ + return self._one_body_integrals + + @property + def two_body_integrals(self): + """ + Returns + ------- + two-body orbitals in given basis (using basis functions, not molecular orbitals. No active space considered) + ordering is "chem" i.e. Mulliken i.e. integrals_{abcd} = <ac|g|bd> + """ + return self._two_body_integrals + + @property + def constant_term(self): + """ + Returns + ------- + return constant term (usually nuclear repulsion). No active space considered + """ + return self._constant_term + + @property + def orbital_coefficients(self): + """ + second index is the orbital index, first the basis index + Returns + ------- + orbital coefficient matrix C_{basis,orbital} + """ + return self._orbital_coefficients + + @orbital_coefficients.setter + def orbital_coefficients(self, other): + self.verify_orbital_coefficients(orbital_coefficients=other) + self._orbital_coefficients = other + for i,x in enumerate(self._orbitals): + y = OrbitalData(idx=x.idx, idx_total=x.idx_total) + self._orbitals[i] = y + +
+[docs] + def transform_to_native_orbitals(self): + """ + Transform orbitals to orthonormal functions closest to the native basis + """ + c = self.get_orthonormalized_orbital_coefficients() + self.orbital_coefficients=c + self._orbital_type="orthonormalized-{}-basis".format(self._basis_name)
+ + +
+[docs] + def is_unitary(self, U): + if len(U.shape) != 2: return False + if U.shape[0] != U.shape[1]: return False + test = (U.conj().T).dot(U) - numpy.eye(U.shape[0]) + if not numpy.isclose(numpy.linalg.norm(test), 0.0): return False + return True
+ + +
+[docs] + def transform_orbitals(self, U, name=None): + """ + Transform orbitals + Parameters + ---------- + U: second index is new orbital indes, first is old orbital index (summed over) + + Returns + ------- + updates the structure with new orbitals: c = cU + """ + assert self.is_unitary(U) + self.orbital_coefficients = numpy.einsum("ix, xj -> ij", self.orbital_coefficients, U, optimize="greedy") + if name is None: + self._orbital_type += "-transformed" + else: + self._orbital_type = name
+ + +
+[docs] + def get_integrals(self, orbital_coefficients=None, ordering="openfermion", ignore_active_space=False, *args, **kwargs): + """ + Get all molecular integrals in given orbital basis (determined by orbital_coefficients in self or the ones passed here) + active space is considered if not explicitly ignored + Parameters + ---------- + orbital_coefficients: orbital coefficients in the given basis (first index is basis, second index is orbitals). Need to go over full basis (no active space) + ordering: ordering of the two-body integrals (default is openfermion) + ignore_active_space: ignore active space and give back full integrals + + Returns + ------- + + """ + if orbital_coefficients is None: + orbital_coefficients = self.orbital_coefficients + + c = self.constant_term + h = self._get_transformed_one_body_integrals(orbital_coefficients=orbital_coefficients) + g = self._get_transformed_two_body_integrals(orbital_coefficients=orbital_coefficients, ordering=ordering) + if not ignore_active_space and self._active_space is not None: + + g = g.reorder(to="openfermion").elems + + active_integrals = get_active_space_integrals(one_body_integrals=h, two_body_integrals=g, + occupied_indices=self._active_space.frozen_reference_orbitals, + active_indices=self._active_space.active_orbitals) + + c = active_integrals[0] + c + + h = active_integrals[1] + g = NBodyTensor(elems=active_integrals[2], ordering="openfermion") + g.reorder(to=ordering) + return c, h, g
+ + + def _get_transformed_one_body_integrals(self, orbital_coefficients=None, verify=True): + if orbital_coefficients is None: + orbital_coefficients = self.orbital_coefficients + elif verify: + assert self.verify_orbital_coefficients(orbital_coefficients=orbital_coefficients) + h = self.one_body_integrals + h = numpy.einsum("ix, xj -> ij", h, orbital_coefficients, optimize='greedy') + h = numpy.einsum("xj, xi -> ij", h, orbital_coefficients, optimize='greedy') + + return h + + def _get_transformed_two_body_integrals(self, orbital_coefficients=None, ordering="openfermion", verify=True): + if orbital_coefficients is None: + orbital_coefficients = self.orbital_coefficients + elif verify: + assert self.verify_orbital_coefficients(orbital_coefficients=orbital_coefficients) + + g = self.two_body_integrals + g = g.reorder("chem").elems + g = numpy.einsum("ijkx, xl -> ijkl", g, orbital_coefficients, optimize='greedy') + g = numpy.einsum("ijxl, xk -> ijkl", g, orbital_coefficients, optimize='greedy') + g = numpy.einsum("ixkl, xj -> ijkl", g, orbital_coefficients, optimize='greedy') + g = numpy.einsum("xjkl, xi -> ijkl", g, orbital_coefficients, optimize='greedy') + g = NBodyTensor(elems=numpy.asarray(g), ordering='chem') + g = g.reorder(to=ordering) + + return g + +
+[docs] + def verify_orbital_coefficients(self, orbital_coefficients, tolerance=1.e-5): + """ + Verify if orbital coefficients are valid (i.e. if they define a orthonormal set of orbitals) + Parameters + ---------- + orbital_coefficients: the orbital coefficients C_ij with i:basis and j:orbitals + tolerance + + Returns + ------- + True or False depending if the overlap matrix of the basis is transformed to a unit matrix + + """ + S = self.overlap_integrals + St = numpy.einsum("ix, xj -> ij", S, orbital_coefficients, optimize='greedy') + St = numpy.einsum("xj, xi -> ij", St, orbital_coefficients, optimize='greedy') + return numpy.linalg.norm(St - numpy.eye(S.shape[0])) < tolerance
+ + +
+[docs] + def basis_is_orthogonal(self, tolerance=1.e-5): + S = self.overlap_integrals + return numpy.linalg.norm(S - numpy.eye(S.shape[0])) < tolerance
+ + +
+[docs] + def active_space_is_trivial(self): + return len(self.active_orbitals) == len(self.orbitals)
+ + + def __str__(self): + result = "\nIntegralManager:\n" + result+= "ActiveSpace:\n" + result+= str(self.active_space) + result+= "Orbitals:\n" + for x in self.orbitals: + result += str(x) + "\n" + return result + +
+[docs] + def print_basis_info(self, print_coefficients=True, *args, **kwargs) -> None: + print("{:15} : {}".format("basis_name", self._basis_name), *args, **kwargs) + print("{:15} : {}".format("orbital_type", self._orbital_type), *args, **kwargs) + print("{:15} : {}".format("orthogonal basis", self.basis_is_orthogonal()), *args, **kwargs) + print("{:15} : {}".format("basis functions", self.one_body_integrals.shape[0]), *args, **kwargs) + print("{:15} : {}".format("active orbitals", [o.idx_total for o in self.active_orbitals]), *args, **kwargs) + print("{:15} : {}".format("reference", [x.idx_total for x in self.reference_orbitals]), *args, **kwargs) + + if not print_coefficients: return + + print("Current Orbitals", *args, **kwargs) + for i,x in enumerate(self.orbitals): + print(x, *args, **kwargs) + print("coefficients: ", self.orbital_coefficients[:,i], *args, **kwargs)
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/quantumchemistry/encodings.html b/docs/sphinx/_modules/tequila_code/quantumchemistry/encodings.html new file mode 100644 index 0000000..f10d76e --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/quantumchemistry/encodings.html @@ -0,0 +1,531 @@ + + + + + + + + tequila_code.quantumchemistry.encodings — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.quantumchemistry.encodings

+"""
+Collections of Fermion-to-Qubit encodings known to tequila
+Most are Interfaces to OpenFermion
+"""
+import abc
+
+from tequila import TequilaException
+from tequila.circuit.circuit import QCircuit
+from tequila.circuit.gates import X, CNOT
+from tequila.hamiltonian.qubit_hamiltonian import QubitHamiltonian
+import openfermion
+import numpy
+
+
+
+[docs] +def known_encodings(): + # convenience for testing and I/O + encodings = { + "JordanWigner": JordanWigner, + "BravyiKitaev": BravyiKitaev, + "BravyiKitaevFast": BravyiKitaevFast, + "BravyiKitaevTree": BravyiKitaevTree, + "TaperedBravyiKitaev": TaperedBravyKitaev + } + # aliases + encodings = {**encodings, + "ReorderedJordanWigner": lambda **kwargs: JordanWigner(up_then_down=True, **kwargs), + "ReorderedBravyiKitaev": lambda **kwargs: BravyiKitaev(up_then_down=True, **kwargs), + "ReorderedBravyiKitaevTree": lambda **kwargs: BravyiKitaevTree(up_then_down=True, **kwargs), + } + return {k.replace("_", "").replace("-", "").upper(): v for k, v in encodings.items()}
+ + + +
+[docs] +class EncodingBase(metaclass=abc.ABCMeta): + # true if the encoding is fully integrated + # false: can only do special things (like building the Hamiltionian) + # but is not consistent with UCC gate generation + _ucc_support = False + + @property + def supports_ucc(self): + return self._ucc_support + + @property + def name(self): + prefix = "" + if self.up_then_down: + prefix = "Reordered" + if hasattr(self, "_name"): + return prefix + self._name + else: + return prefix + type(self).__name__ + + def __init__(self, n_electrons, n_orbitals, up_then_down=False, *args, **kwargs): + self.n_electrons = n_electrons + self.n_orbitals = n_orbitals + self.up_then_down = up_then_down + + def __call__(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> QubitHamiltonian: + """ + :param fermion_operator: + an openfermion FermionOperator + :return: + The openfermion QubitOperator of this class ecoding + """ + if self.up_then_down: + op = openfermion.reorder(operator=fermion_operator, order_function=openfermion.up_then_down, + num_modes=2 * self.n_orbitals) + else: + op = fermion_operator + + fop = self.do_transform(fermion_operator=op, *args, **kwargs) + fop.compress() + return self.post_processing(QubitHamiltonian.from_openfermion(fop)) + +
+[docs] + def post_processing(self, op, *args, **kwargs): + return op
+ + +
+[docs] + def up(self, i): + if self.up_then_down: + return i + else: + return 2 * i
+ + +
+[docs] + def down(self, i): + if self.up_then_down: + return i + self.n_orbitals + else: + return 2 * i + 1
+ + +
+[docs] + def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator: + raise Exception("{}::do_transform: called base class".format(type(self).__name__))
+ + +
+[docs] + def map_state(self, state: list, *args, **kwargs) -> list: + """ + Expects a state in spin-orbital ordering + Returns the corresponding qubit state in the class encoding + :param state: + basis-state as occupation number vector in spin orbitals + sorted as: [0_up, 0_down, 1_up, 1_down, ... N_up, N_down] + with N being the number of spatial orbitals + :return: + basis-state as qubit state in the corresponding mapping + """ + """Does a really lazy workaround ... but it works + :return: Hartree-Fock Reference as binary-number + + Parameters + ---------- + reference_orbitals: list: + give list of doubly occupied orbitals + default is None which leads to automatic list of the + first n_electron/2 orbitals + + Returns + ------- + + """ + # default is a lazy workaround, but it workds + n_qubits = 2 * self.n_orbitals + + spin_orbitals = sorted([i for i, x in enumerate(state) if int(x) == 1]) + + string = "1.0 [" + for i in spin_orbitals: + string += str(i) + "^ " + string += "]" + + fop = openfermion.FermionOperator(string, 1.0) + op = self(fop) + from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction + wfn = QubitWaveFunction.from_int(0, n_qubits=n_qubits) + wfn = wfn.apply_qubitoperator(operator=op) + assert (len(wfn.keys()) == 1) + key = list(wfn.keys())[0].array + return key
+ + +
+[docs] + @abc.abstractmethod + def me_to_jw(self) -> QCircuit: + """ + This method needs to be implemented to enable default conversions via Jordan-Wigner + """ + pass
+ + + # independent conversion methods, these are used for default conversions + # arXiv:1808.10402 IV. B. 2, Eq. 57 + # original: https://doi.org/10.1063/1.4768229 + def _jw_to_bk(self) -> QCircuit: + U = QCircuit() # Constructs empty circuit + + flipper = False + for i in range(self.n_orbitals * 2): + # even qubits only hold their own value + if i % 2 == 0: + continue + + # sum always includes the last qubit + U += CNOT(control=i - 1, target=i) + + # every second odd qubit ties together with the last odd qubit + if flipper: + U += CNOT(control=i - 2, target=i) + + flipper = not flipper + + # we have now created the 4x4 blocks on the diagonal of this operators matrix + + # every power of 2 connects to the last power of 2 + # this corresponds to the last row in the recursive definitions being all 1s + x = numpy.log2(i + 1) + if x.is_integer() and x >= 3: + x = int(x) + U += CNOT(control=2 ** (x - 1) - 1, target=i) + + return U + + def _hcb_to_jw(self): + U = QCircuit() + for i in range(self.n_orbitals): + U += X(target=self.down(i), control=self.up(i)) + return U + + # Convenience Methods +
+[docs] + def jw_to_me(self) -> QCircuit: + return self.me_to_jw().dagger()
+ + +
+[docs] + def me_to_bk(self) -> QCircuit: + return self.me_to_jw() + self._jw_to_bk()
+ + +
+[docs] + def bk_to_me(self) -> QCircuit: + return self.me_to_bk().dagger()
+ + +
+[docs] + def hcb_to_me(self) -> QCircuit: + return self._hcb_to_jw() + self.jw_to_me()
+ + + def __str__(self): + return type(self).__name__
+ + + +
+[docs] +class JordanWigner(EncodingBase): + """ + OpenFermion::jordan_wigner + """ + _ucc_support = True + +
+[docs] + def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator: + return openfermion.jordan_wigner(fermion_operator, *args, **kwargs)
+ + +
+[docs] + def map_state(self, state: list, *args, **kwargs): + state = state + [0] * (self.n_orbitals - len(state)) + result = [0] * len(state) + if self.up_then_down: + return [state[2 * i] for i in range(self.n_orbitals)] + [state[2 * i + 1] for i in range(self.n_orbitals)] + else: + return state
+ + +
+[docs] + def hcb_to_me(self, *args, **kwargs): + U = QCircuit() + for i in range(self.n_orbitals): + U += X(target=self.down(i), control=self.up(i)) + return U
+ + +
+[docs] + def me_to_jw(self) -> QCircuit: + return QCircuit()
+ + +
+[docs] + def jw_to_me(self) -> QCircuit: + return QCircuit()
+
+ + + +
+[docs] +class BravyiKitaev(EncodingBase): + """ + Uses OpenFermion::bravyi_kitaev + """ + + _ucc_support = True + +
+[docs] + def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator: + return openfermion.bravyi_kitaev(fermion_operator, n_qubits=self.n_orbitals * 2)
+ + +
+[docs] + def me_to_jw(self) -> QCircuit: + return self._jw_to_bk().dagger()
+ + +
+[docs] + def jw_to_me(self) -> QCircuit: + return self._jw_to_bk()
+ + +
+[docs] + def bk_to_me(self) -> QCircuit: + return QCircuit()
+ + +
+[docs] + def me_to_bk(self) -> QCircuit: + return QCircuit()
+
+ + + +
+[docs] +class BravyiKitaevTree(EncodingBase): + """ + Uses OpenFermion::bravyi_kitaev_tree + """ + + _ucc_support = True + +
+[docs] + def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator: + return openfermion.bravyi_kitaev_tree(fermion_operator, n_qubits=self.n_orbitals * 2)
+ + +
+[docs] + def me_to_jw(self) -> QCircuit: + raise TequilaException("{}::me_to_jw: unimplemented".format(type(self).__name__))
+
+ + + +
+[docs] +class BravyiKitaevFast(EncodingBase): + """ + Uses OpenFermion::bravyi_kitaev_tree + """ + + _ucc_support = False + +
+[docs] + def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator: + n_qubits = openfermion.count_qubits(fermion_operator) + if n_qubits != self.n_orbitals * 2: + raise Exception( + "BravyiKitaevFast transformation currently only possible for full Hamiltonians (no UCC generators).\nfermion_operator was {}".format( + fermion_operator)) + op = openfermion.get_interaction_operator(fermion_operator) + return openfermion.bravyi_kitaev_fast(op)
+ + +
+[docs] + def me_to_jw(self) -> QCircuit: + raise TequilaException("{}::me_to_jw: unimplemented".format(type(self).__name__))
+
+ + + +
+[docs] +class TaperedBravyKitaev(EncodingBase): + _ucc_support = False + + """ + Uses OpenFermion::symmetry_conserving_bravyi_kitaev (tapered bravyi_kitaev_tree arxiv:1701.07072) + Reduces Hamiltonian by 2 qubits + See OpenFermion Documentation for more + Does not work for UCC generators yet + """ + + def __init__(self, n_electrons, n_orbitals, active_fermions=None, active_orbitals=None, *args, **kwargs): + if active_fermions is None: + self.active_fermions = n_electrons + else: + self.active_fermions = active_fermions + + if active_orbitals is None: + self.active_orbitals = n_orbitals * 2 # in openfermion those are spin-orbitals + else: + self.active_orbitals = active_orbitals + + if "up_then_down" in kwargs: + raise Exception("Don't pass up_then_down argument to {}, it can't be changed".format(type(self).__name__)) + super().__init__(n_orbitals=n_orbitals, n_electrons=n_electrons, up_then_down=False, *args, **kwargs) + +
+[docs] + def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator: + if openfermion.count_qubits(fermion_operator) != self.n_orbitals * 2: + raise Exception("TaperedBravyiKitaev not ready for UCC generators yet") + return openfermion.symmetry_conserving_bravyi_kitaev(fermion_operator, active_orbitals=self.active_orbitals, + active_fermions=self.active_fermions)
+ + +
+[docs] + def map_state(self, state: list, *args, **kwargs): + non_tapered_trafo = BravyiKitaevTree(up_then_down=True, n_electrons=self.n_electrons, + n_orbitals=self.n_orbitals) + key = non_tapered_trafo.map_state(state=state, *args, **kwargs) + n_qubits = self.n_orbitals * 2 + active_qubits = [i for i in range(n_qubits) if i not in [n_qubits - 1, n_qubits // 2 - 1]] + key = [key[i] for i in active_qubits] + return key
+ + +
+[docs] + def me_to_jw(self) -> QCircuit: + raise TequilaException("{}::me_to_jw: unimplemented".format(type(self).__name__))
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/quantumchemistry/madness_interface.html b/docs/sphinx/_modules/tequila_code/quantumchemistry/madness_interface.html new file mode 100644 index 0000000..25b9b45 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/quantumchemistry/madness_interface.html @@ -0,0 +1,973 @@ + + + + + + + + tequila_code.quantumchemistry.madness_interface — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.quantumchemistry.madness_interface

+from tequila.quantumchemistry.qc_base import QuantumChemistryBase, TequilaException, TequilaWarning, \
+    QCircuit, gates
+from tequila.quantumchemistry import ParametersQC, NBodyTensor
+from tequila import ExpectationValue
+from .chemistry_tools import OrbitalData
+import typing
+import numpy
+import warnings
+import os
+import shutil
+
+
+# Examples how to initialize the madness backend
+# tq.Molecule(geometry="...") will initialize a molecule with n_qubits=n_electrons (n_electrons//2 HF orbitals + n_electrons//2 PNOs)
+# tq.Molecule(geometry="...", n_pno="read") will read in files (name is auto-generated from geometry)
+# tq.Molecule(geometry="...", name="X", n_pno="read") will read in files X_htensor.npy, X_gtensor.npy, X_pnoinfo.txt
+# tq.Molecule(geometry="...", name="X", datadir="asd/Y/", n_pno="read") reads in files from directory asd/Y/
+# control madness input sections with dictionaries
+# tq.Molecule(geometry="...", pno={"maxrank":10, "freeze":0}, dft={"k":9, "L":25.0})
+# compute more orbitals
+# tq.Molecule(geometry="...", n_pno=10) # computes 10 PNOs additional to the occupied HF orbitals
+
+
+
+[docs] +class TequilaMadnessException(TequilaException): + def __str__(self): + return "Error in madness backend:" + self.message
+ + + +
+[docs] +class QuantumChemistryMadness(QuantumChemistryBase): + +
+[docs] + @staticmethod + def find_executable(madness_root_dir=None): + executable = shutil.which("pno_integrals") + if madness_root_dir is None: + madness_root_dir = str(os.environ.get("MAD_ROOT_DIR")) + if executable is None and madness_root_dir is not None: + executable = shutil.which("{}/src/apps/pno/pno_integrals".format(madness_root_dir)) + return executable
+ + +
+[docs] + def plot2cube(self, orbital, filename=None, *args, **kwargs): + """ + plot orbitals to cube file (needs madtequila backend installed) + Parameters + ---------- + method: orbital, the orbital index (starting from 0 on the active orbitals) + if you want to plot frozen orbitals you can hand in a Tequila Orbital structure with idx_total defined + filename: name of the cubefile (default: mra_orbital_X.cube where X is the total index of the active orbital) + args: further arguments for plot2cube + kwargs further keyword arguments for plot2cube + + see here for more https://github.com/kottmanj/madness/tree/tequila/src/apps/plot + """ + + plot2cube = shutil.which("plot2cube") + if plot2cube is None: + raise TequilaMadnessException( + "can't plot to cube file. Couldn't find plot2cube executable.\n\nTry installing\n\t conda install madtequila -c kottmann\nand assure the version is >2.3") + + if hasattr(orbital,"idx"): + idx = orbital.idx + else: + idx = self.orbitals[orbital].idx_total + + callist = [plot2cube, "file=mra_orbital_{}".format(idx)] + + if filename is not None: + callist.append("outfile={}".format(filename)) + for k, v in kwargs.items(): + callist.append("{}={}".format(k, v)) + for k in args: + callist.append("{}".format(k)) + + import subprocess + try: + with open("plot2cube_{}.log".format(orbital), "w") as logfile: + subprocess.call(callist, stdout=logfile) + except: + print("plotting failed ....") + print("see plot2cube_{}.log".format(orbital))
+ + + def __init__(self, parameters: ParametersQC, + transformation: typing.Union[str, typing.Callable] = None, + active_orbitals: list = "auto", + executable: str = None, + n_pno: int = None, + n_virt: int = 0, + keep_mad_files=False, + datadir=None, + *args, + **kwargs): + + self.datadir = datadir + + # see if MAD_ROOT_DIR is defined + self.madness_root_dir = os.environ.get("MAD_ROOT_DIR") + # see if the pno_integrals executable can be found + if executable is None: + executable = self.find_executable() + if executable is None and self.madness_root_dir is not None: + warnings.warn("MAD_ROOT_DIR={} found\nbut couldn't find executable".format(self.madness_root_dir), + TequilaWarning) + + + else: + executable = shutil.which(executable) + + self.executable = executable + self.n_pno = n_pno + self.n_virt = n_virt + self.kwargs = kwargs + + # if no n_pno is given, look for MRA data (default) + name = parameters.name + + # try to read in data in the following cases + # - no executable found + # - executable found but read in explicitly demanded through n_pno="read" + if (n_pno is None and executable is None) or (hasattr(n_pno, "lower") and n_pno.lower() == "read"): + h, g = self.read_tensors(name=name, datadir=datadir) + n_pno = None + else: + h = "failed" + g = "failed" + + if (isinstance(h, str) and "failed" in h) or (isinstance(g, str) and "failed" in g): + status = "found {}_htensor.npy={}\n".format(name, "failed" not in h) + status += "found {}_gtensor.npy={}\n".format(name, "failed" not in g) + try: + # try to run madness + self.parameters = parameters + status += "madness=" + madness_status = self.run_madness(*args, **kwargs) + if int(madness_status) != 0: + warnings.warn("MADNESS did not terminate as expected! status = {}".format(status), TequilaWarning) + status += str(madness_status) + "\n" + except Exception as E: + status += str(E) + "\n" + + # will read the binary files, convert them and save them with the right name + h, g, pinfo = self.convert_madness_output_from_bin_to_npy(name=name, datadir=datadir) + status += "found {}_htensor.npy={}\n".format(name, "failed" not in h) + status += "found {}_gtensor.npy={}\n".format(name, "failed" not in g) + status += "found {}_pnoinfo.txt={}\n".format(name, "failed" not in pinfo) + status += "h_tensor report:\n" + status += str(h) + status += "g_tensor report:\n" + status += str(g) + status += "pnoinfo report:\n" + status += str(pinfo) + + solution = "Solution 1: Assuming precomputed files are available:\n provide {name}_gtensor.npy, {name}_htensor.npy and {name}_pnoinfo.txt\n and call the Molecule constructor with n_pno='read' keyword \n\nSolution 2: Try installing with conda\n conda install madtequila -c kottmann\n\nSolution 3: Install from source\n follow instructions on github.com/kottmanj/madness".format( + name=name) + if self.executable is not None: + solution = "madness executable was found, but calculation did not succeed, check {name}_pno_integrals.out for clues".format( + name=name) + + if "failed" in h or "failed" in g: + raise TequilaMadnessException("Could not initialize the madness interface\n" + "Status report is\n" + "{status}\n\n".format(status=status) + solution) + # get additional information from madness file + nuclear_repulsion = 0.0 + pairinfo = None + occinfo = None + path = parameters.name + if datadir is not None: + path = "{}/{}".format(datadir, path) + for name in [path + "_pnoinfo.txt", parameters.name + "_pnoinfo.txt", "pnoinfo.txt"]: + try: + with open(name, "r") as f: + for line in f.readlines(): + if "nuclear_repulsion" in line: + nuclear_repulsion = float(line.split("=")[1]) + elif "pairinfo" in line: + pairinfo = line.split("=")[1].split(",") + pairinfo = [tuple([int(i) for i in x.split(".")]) for x in pairinfo] + elif "occinfo" in line: + occinfo = line.split("=")[1].split(",") + occinfo = [float(x) for x in occinfo] + + if pairinfo is not None: + break + except: + continue + + if pairinfo is None: + raise TequilaMadnessException("Pairinfo from madness calculation not found\nPlease provide pnoinfo.txt") + + n_orbitals_total = h.shape[0] + if "n_orbitals" in kwargs: + # this would be the active orbitals + kwargs.pop("n_orbitals") + + assert h.shape[1] == n_orbitals_total + assert sum(g.shape) == 4 * n_orbitals_total + assert len(g.shape) == 4 + assert len(h.shape) == 2 + + g = NBodyTensor(elems=g, ordering='mulliken') + + orbitals = [] + if pairinfo is not None: + orbitals = [OrbitalData(idx_total=i, idx=i, pair=p, occ=occinfo[i]) for i, p in + enumerate(pairinfo)] + reference_orbitals = [x for x in orbitals if x.occ == 2.0] + if active_orbitals == "auto": + not_active = [i for i in reference_orbitals if + sum([1 for x in orbitals if i.idx_total in x.pair]) < 2] + active_orbitals = [x.idx_total for x in orbitals if x not in not_active] + + if active_orbitals is not None: + i = 0 + for x in orbitals: + if x.idx_total in active_orbitals: + orbitals[x.idx_total].idx = i + i += 1 + else: + orbitals[x.idx_total].idx = None + else: + raise TequilaMadnessException("No pairinfo given: madness interface needs a file moleculename_pnoinfo.txt") + + # convert to indices only + # active space data will be set in baseclass constructor + reference_orbitals = [x.idx_total for x in reference_orbitals] + super().__init__(parameters=parameters, + transformation=transformation, + active_orbitals=active_orbitals, + one_body_integrals=h, + two_body_integrals=g, + nuclear_repulsion=nuclear_repulsion, + n_orbitals=n_orbitals_total, + orbitals=orbitals, + reference_orbitals=reference_orbitals, + *args, + **kwargs) + + # print warning if read data does not match expectations + if n_pno is not None: + nrefs = len(self.reference_orbitals) + if n_pno + nrefs + n_virt != self.n_orbitals: + warnings.warn( + "read in data has {} pnos/virtuals, but n_pno and n_virt where set to {} and {}".format( + self.n_orbitals - nrefs, n_pno, n_virt), TequilaWarning) + + # delete *.bin files and pnoinfo.txt form madness calculation + if not keep_mad_files: + self.cleanup(warn=False, delete_all_files=False) + +
+[docs] + def cleanup(self, warn=False, delete_all_files=False): + + filenames = ["pnoinfo.txt", "molecule_htensor.bin", "molecule.gtensor.bin"] + if delete_all_files: + filenames = ["{}_htensor.npy".format(self.parameters.name), "{}_gtensor.npy".format(self.parameters.name), + "{}_pnoinfo.txt".format(self.parameters.name), + "{}_pno_integrals.out".format(self.parameters.name)] + for filename in filenames: + if os.path.exists(filename): + if warn: + warnings.warn("Found file {} from previous calculation ... deleting it".format(filename), + TequilaWarning) + os.remove(filename)
+ + +
+[docs] + def run_madness(self, *args, **kwargs): + if self.executable is None: + return "\n\n----> pno_integrals executable not found <----\n\n" + self.write_madness_input(n_pno=self.n_pno, n_virt=self.n_virt, *args, **kwargs) + + # prevent reading in old files + self.cleanup(warn=True, delete_all_files=True) + + import subprocess + import time + start = time.time() + filename = "{}_pno_integrals.out".format(self.parameters.name) + print("Starting madness calculation with executable: ", self.executable) + print("output redirected to {} logfile".format(filename)) + with open(filename, "w") as logfile: + madout = subprocess.call([self.executable], stdout=logfile) + print("finished after {}s".format(time.time() - start)) + + os.rename("pnoinfo.txt", "{}_pnoinfo.txt".format(self.parameters.name)) + + return madout
+ + +
+[docs] + def read_tensors(self, name="molecule", filetype="npy", datadir=None): + """ + Try to read files "name_htensor.npy" and "name_gtensor.npy" + """ + + path = name + if datadir is not None: + path = "{}/{}".format(datadir, name) + + try: + h = numpy.load("{}_htensor.{}".format(path, filetype)) + except: + h = "failed" + + try: + g = numpy.load("{}_gtensor.{}".format(path, filetype)) + except: + g = "failed" + + return h, g
+ + +
+[docs] + def get_pair_orbitals(self, i: OrbitalData, j: OrbitalData, + exclude: typing.List[OrbitalData] = None): + if isinstance(i, int): + i = self.orbitals[i] + if isinstance(j, int): + j = self.orbitals[j] + if isinstance(exclude, int): + exclude = [self.orbitals[exclude]] + if exclude is None or isinstance(exclude, OrbitalData): + exclude = [exclude] + return [x for x in self.orbitals if (i.idx_total, j.idx_total) == x.pair and x not in exclude]
+ + +
+[docs] + def get_virtual_orbitals(self): + return [x for x in self.orbitals if len(x.pair) == 1 and x.pair[0] < 0]
+ + +
+[docs] + def compute_energy(self, method, *args, **kwargs): + """ + Call classical methods over PySCF (needs to be installed) or + use as a shortcut to calculate quantum energies (see make_upccgsd_ansatz) + + Parameters + ---------- + method: method name + classical: HF, MP2, CCSD, CCSD(T), FCI + quantum: SPA-GASD (SPA can be dropped as well as letters in GASD) + examples: GSD is the same as UpCCGSD, SPA alone is equivalent to SPA-D + see make_upccgsd_ansatz of the this class for more information + args + kwargs + + Returns + ------- + + """ + + if any([x in method.upper() for x in ["U", "SPA", "PNO", "HCB"]]): + # simulate entirely in HCB representation if no singles are involved + if "S" not in method.upper().split("-")[-1] and "HCB" not in method.upper(): + method = "HCB-" + method + U = self.make_upccgsd_ansatz(name=method) + if "hcb" in method.lower(): + H = self.make_hardcore_boson_hamiltonian() + else: + H = self.make_hamiltonian() + E = ExpectationValue(H=H, U=U) + from tequila import minimize + return minimize(objective=E, *args, **kwargs).energy + else: + return super().compute_energy(method=method, *args, **kwargs)
+ + +
+[docs] + def local_qubit_map(self, hcb=False, up_then_down=False): + # re-arrange orbitals to result in more local circuits + # does not make the circuit more local, but rather will show locality better in pictures + # transform circuits and Hamiltonians with this map + # H = H.map_qubits(qubit_map), U = U.map_qubits(qubit_map) + # hcb: same for the harcore_boson representation + ordered_qubits = [] + pairs = [i for i in range(self.n_electrons // 2)] + for i in pairs: + pnos = [i] + [a.idx for a in self.get_pair_orbitals(i=i, j=i, exclude=i)] + if hcb: + up = [i for i in pnos] + ordered_qubits += up + else: + if up_then_down: + up = [self.transformation.up(i) for i in pnos] + down = [self.transformation.down(i) for i in pnos] + ordered_qubits += up + down + else: + for i in pnos: + ordered_qubits.append(self.transformation.up(i)) + ordered_qubits.append(self.transformation.down(i)) + + qubit_map = {x: i for i, x in enumerate(ordered_qubits)} + return qubit_map
+ + +
+[docs] + def make_spa_ansatz(self, label=None, hcb=False): + """ + Shortcut for convenience + Parameters + ---------- + label: + label for the angles + hcb: + if True the circuit will not map from HCB to JW (or other encodings that might be supported in the future) + Returns + ------- + Default SPA ansatz (equivalent to PNO-UpCCD with madness PNOs) + + """ + name = "SPA-UpCCD" + if hcb and "HCB" not in name.upper(): + name = "HCB-" + name + return self.make_upccgsd_ansatz(name=name, label=label)
+ + +
+[docs] + def make_upccgsd_ansatz(self, name="UpCCGSD", label=None, direct_compiling=None, order=None, neglect_z=None, + hcb_optimization=None, include_reference=True, *args, **kwargs): + """ + Overwriting baseclass to allow names like : PNO-UpCCD etc + Parameters + ---------- + label: label the variables of the ansatz ( variables will be labelled (indices, X, (label, layer) witch X=D/S) + direct_compiling: Directly compile the first layer (works only for transformation that implement the hcb_to_me function) + name: ansatz name (SPA-UpCCD or SPA-D, SPA-UpCCGD or SPA-GD, SPA-UpCCGSD or SPA-GSD, UpCCGSD or GSD ..., in general {HCB}-{SPA}-{Excitations} + if HCB is included in name: do not map from hard-core Boson to qubit encoding of this molecule + if SPA is included in name: Use the separable pair ansatz (excitations will be restricted to the PNO structure of the surrogate model) + Excitations: can be "S" (use only singles), "D" (use only doubles), "GSD" (generalized singles and doubles), "GASD" (approximate singles, neglecting Z terms in JW) + neglect_z: neglect all Z terms in singles excitations generators + order: repetition of layers, can be given over the name as well, the order needs to be the first in the name then (i.e. 2-UpCCGSD, 2-SPA-GSD, etc) + args + kwargs + + Returns + ------- + + """ + # check if the used qubit encoding has a hcb transformation + try: + have_hcb_trafo = self.transformation.hcb_to_me() is not None + except: + have_hcb_trafo = False + name = name.upper() + + # Default Method + if "SPA" in name and name.split("-")[-1] in ["SPA", "HCB"]: + name += "-D" + + excitations = name.split("-")[-1] + + if "HCB" in name and "S" in excitations: + raise TequilaMadnessException("name={}, HCB + Singles can't be realized".format(name)) + + if "HCB" in name and "D" not in excitations: + raise warnings.warn("name={}, HCB without Doubles has no result ".format(name), TequilaWarning) + + if "S" not in excitations and "D" not in excitations: + raise warnings.warn("name={}, neither singles nor doubles requested".format(name), TequilaWarning) + + if "T" in excitations or "Q" in excitations: + raise warnings.warn("name={}, only singles and doubles supported".format(name), TequilaWarning) + + if (have_hcb_trafo and "D" in excitations or "HCB" in name) and include_reference and hcb_optimization is None: + hcb_optimization = True + + if hcb_optimization and direct_compiling is None: + direct_compiling = True + + if ("A" in excitations) and neglect_z is None: + neglect_z = True + # spin adaption does not work with z neglected + if "spin_adapt_singles" not in kwargs: + kwargs["spin_adapt_singles"] = False + else: + neglect_z = False + # switch on by default + if "spin_adapt_singles" not in kwargs: + kwargs["spin_adapt_singles"] = True + + if direct_compiling and not have_hcb_trafo and not "HCB" in name: + raise TequilaMadnessException( + "direct_compiling={} demanded but no hcb_to_me in transformation={}\ntry transformation=\'ReorderedJordanWigner\' ".format( + direct_compiling, self.transformation)) + + name = name.upper() + if order is None: + try: + if "-" in name: + order = int(name.split("-")[0]) + else: + order = 1 + except: + order = 1 + + # first layer + U = QCircuit() + if hcb_optimization: + if "D" in excitations: + U = self.make_hardcore_boson_pno_upccd_ansatz(include_reference=include_reference, + direct_compiling=direct_compiling, + label=(label, 0)) + elif include_reference: + U = self.prepare_hardcore_boson_reference() + + indices0 = [k.name[0] for k in U.extract_variables()] + indices1 = self.make_upccgsd_indices(label=label, name=name, exclude=indices0, *args, **kwargs) + if "D" in excitations: + U += self.make_hardcore_boson_upccgd_layer(indices=indices1, label=(label, 0), *args, **kwargs) + indices = indices0 + indices1 + if "HCB" not in name and len(U.gates) > 0: + U = self.hcb_to_me(U=U) + else: + assert "S" not in excitations + if "S" in excitations: + U += self.make_upccgsd_singles(indices=indices, label=(label, 0), neglect_z=neglect_z, *args, **kwargs) + else: + indices = self.make_upccgsd_indices(label=(label, 0), name=name, *args, **kwargs) + if include_reference: + U = self.prepare_reference() + U += self.make_upccgsd_layer(indices=indices, include_singles="S" in excitations, + include_doubles="D" in excitations, label=(label, 0), neglect_z=neglect_z, + *args, **kwargs) + + if order > 1: + for layer in range(1, order): + indices = self.make_upccgsd_indices(label=(label, layer), name=name, *args, **kwargs) + if "HCB" in name: + U += self.make_hardcore_boson_upccgd_layer(indices=indices, label=(label, layer), *args, **kwargs) + else: + U += self.make_upccgsd_layer(indices=indices, include_singles="S" in excitations, + include_doubles="D" in excitations, label=(label, layer), + neglect_z=neglect_z, *args, **kwargs) + return U
+ + +
+[docs] + def make_hardcore_boson_pno_upccd_ansatz(self, pairs=None, label=None, include_reference=True, + direct_compiling=False): + if pairs is None: + pairs = [x for x in self.reference_orbitals] + U = QCircuit() + if direct_compiling: + if not include_reference: + raise Exception("HCB_PNO_UPCCD: Direct compiling needs reference included") + for x in pairs: + U += gates.X(x.idx) + c = [None, x.idx] + for a in self.get_pair_orbitals(i=x, j=x): + if a == x: + continue + idx = self.format_excitation_indices([(x.idx, a.idx)]) + U += gates.Ry(angle=(idx, "D", label), target=a.idx, control=c[0]) + U += gates.X(target=c[1], control=a.idx) + if hasattr(direct_compiling, "lower") and direct_compiling.lower() == "ladder": + c = [a.idx, a.idx] + else: + c = [x.idx, x.idx] + + alpha_map = {k.idx: self.transformation.up(k.idx) for k in self.orbitals} + U = U.map_qubits(alpha_map) + else: + for x in pairs: + if include_reference: + U += gates.X(self.transformation.up(x.idx)) + for a in self.get_pair_orbitals(i=x, j=x): + if x == a: + continue + idx = self.format_excitation_indices([(x.idx, a.idx)]) + U += self.make_hardcore_boson_excitation_gate(indices=idx, angle=(idx, "D", label)) + + return U
+ + +
+[docs] + def make_upccgsd_indices(self, label=None, name="UpCCGD", exclude: list = None, *args, **kwargs): + """ + :param label: label the angles + :param generalized: if true the complement to UpCCGD is created (otherwise UpCCD) + :param exclude: list of indices to exclude + :return: All gates missing between PNO-UpCCD and UpCC(G)D + """ + + if exclude is None: + exclude = [] + name = name.upper() + + indices = [] + + # HF-X -- PNO-XX indices + for i in self.reference_orbitals: + for a in self.get_pair_orbitals(i=i, j=i, exclude=i): + idx = self.format_excitation_indices([(i.idx, a.idx)]) + if idx not in exclude and idx not in indices: + indices.append(idx) + + if "G" in name: + for i in self.reference_orbitals: + for a in self.get_pair_orbitals(i=i, j=i, exclude=i): + for b in self.get_pair_orbitals(i=i, j=i, exclude=i): + if a.idx <= b.idx: + continue + + idx = self.format_excitation_indices([(a.idx, b.idx)]) + if idx not in exclude and idx not in indices: + indices.append(idx) + + if "PNO" in name or "SPA" in name: + return indices + + virtuals = [i for i in self.orbitals if len(i.pair) == 2 and i.occ != 2.0] + virtuals += self.get_virtual_orbitals() # this is usually empty + # HF-X -- PNO-XY/PNO-YY indices + for i in self.reference_orbitals: + for a in virtuals: + idx = self.format_excitation_indices([(i.idx, a.idx)]) + if idx not in exclude and idx not in indices: + indices.append(idx) + # HF-HF and PNO-PNO indices + if "G" in name: + for i in self.reference_orbitals: + for j in self.reference_orbitals: + if i.idx <= j.idx: + continue + idx = self.format_excitation_indices([(i.idx, j.idx)]) + if idx not in exclude and idx not in indices: + indices.append(idx) + for a in virtuals: + for b in virtuals: + if a.idx_total <= b.idx_total: + continue + idx = self.format_excitation_indices([(a.idx, b.idx)]) + if idx not in exclude and idx not in indices: + indices.append(idx) + return indices
+ + +
+[docs] + def make_pno_upccgsd_ansatz(self, generalized=False, include_offdiagonals=False, + **kwargs): + indices = [] + refs = self.reference_orbitals + for i in self.reference_orbitals: + for a in self.get_pair_orbitals(i=i, j=i, exclude=i): + indices.append((i.idx, a.idx)) + if generalized: + for a in self.get_pair_orbitals(i=i, j=i, exclude=i): + for b in self.get_pair_orbitals(i=i, j=i, exclude=i): + if b.idx_total <= a.idx_total: + continue + indices.append((i.idx, a.idx)) + + if include_offdiagonals: + for i in self.reference_orbitals: + for j in self.reference_orbitals: + pairs_ij = self.get_pair_orbitals(i=i, j=j, exclude=[i, j]) + if i.idx <= j.idx: + continue + for a in pairs_ij: + indices.append((j.idx, a.idx)) + + if generalized: + for a in pairs_ij: + for b in pairs_ij: + if a.idx <= b.idx: + continue + indices.append((a.idx, b.idx)) + + return self.make_upccgsd_ansatz(indices=indices, **kwargs)
+ + +
+[docs] + def write_madness_input(self, n_pno=None, n_virt=0, filename="input", maxrank=None, + n_orbitals=None, *args, **kwargs): + + if n_pno is not None and n_orbitals is not None: + raise TequilaMadnessException( + "n_pno={} and n_orbitals={} given ... please pick one".format(n_pno, n_orbitals)) + + n_electrons = self.parameters.n_electrons + if self.parameters.frozen_core: + # only count active electrons (will not compute pnos for frozen pairs) + n_core_electrons = self.parameters.get_number_of_core_electrons() + n_electrons -= n_core_electrons + + n_pairs = n_electrons // 2 + if n_orbitals is None: + n_orbitals = n_electrons # minimal correlated (each active pair will have one virtual) + + if n_pno is None: + n_pno = n_orbitals - n_pairs + + if maxrank is None: + # need at least maxrank=1, otherwise no PNOs are computed + # this was a bug in <=v1.8.5 + maxrank = max(1, int(numpy.ceil(n_pno // n_pairs))) + + if maxrank <= 0: + warnings.warn( + "maxrank={} in tequila madness backend! No PNOs will be computed. Set the value when initializing the Molecule as tq.Molecule(..., pno={\"maxrank\":1, ...})".format( + maxrank), TequilaWarning) + + data = {} + if self.parameters.multiplicity != 1: + raise TequilaMadnessException( + "Currently only closed shell supported for MRA-PNO-MP2, you demanded multiplicity={} for the surrogate".format( + self.parameters.multiplicity)) + data["dft"] = {"charge": self.parameters.charge, "xc": "hf", "k": 7, "econv": 1.e-4, "dconv": 5.e-4, + "localize": "boys", + "ncf": "( none , 1.0 )"} + data["pno"] = {"maxrank": maxrank, "f12": "false", "thresh": 1.e-4, "diagonal": True} + if not self.parameters.frozen_core: + data["pno"]["freeze"] = 0 + data["pnoint"] = {"n_pno": n_pno, "n_virt": n_virt, "orthog": "symmetric"} + data["plot"] = {} + data["f12"] = {} + for key in data.keys(): + if key in kwargs: + data[key] = {**data[key], **kwargs[key]} + + if filename is not None: + with open(filename, "w") as f: + for k1, v1 in data.items(): + print(k1, file=f) + for k2, v2 in v1.items(): + print("{} {}".format(k2, v2), file=f) + print("end\n", file=f) + + print("geometry", file=f) + print("units angstrom", file=f) + print("eprec 1.e-6", file=f) + for line in self.parameters.get_geometry_string().split("\n"): + line = line.strip() + if line != "": + print(line, file=f) + print("end", file=f) + + return data
+ + +
+[docs] + def convert_madness_output_from_bin_to_npy(self, name, datadir=None): + path = name + if datadir is not None: + # if the datadir does not exist then tequila will crash + try: + import os + if not os.path.exists(datadir): + os.makedirs(datadir) + except Exception as E: + warnings.warn("tried to create datadir={} and caught\n{}".format(datadir, str(E)), TequilaWarning) + + path = "{}/{}".format(datadir, name) + try: + g_data = numpy.fromfile("molecule_gtensor.bin".format()) + sd = int(numpy.power(g_data.size, 0.25)) + assert (sd ** 4 == g_data.size) + sds = [sd] * 4 + g = g_data.reshape(sds) + numpy.save("{}_gtensor.npy".format(path), arr=g) + except Exception as E: + g = "failed\n{}\n".format(str(E)) + + try: + h_data = numpy.fromfile("molecule_htensor.bin") + sd = int(numpy.sqrt(h_data.size)) + assert (sd ** 2 == h_data.size) + sds = [sd] * 2 + h = h_data.reshape(sds) + numpy.save("{}_htensor.npy".format(path), arr=h) + except Exception as E: + h = "failed\n{}\n".format(str(E)) + + try: + with open("{}_pnoinfo.txt".format(name), "r") as f1: + pnoinfo = f1.read().strip() + except Exception as E: + pnoinfo = "failed\n{}\n".format(str(E)) + + if datadir is not None: + try: + with open("{}_pnoinfo.txt".format(name), "r") as f1, open("{}_pnoinfo.txt".format(path), "w") as f2: + f2.write(f1.read().strip()) + except Exception as E: + pnoinfo = "failed\n{}\n".format(str(E)) + try: + with open("{}_pno_integrals.out".format(name), "r") as f1, open("{}_pno_integrals.out".format(path), + "w") as f2: + f2.write(f1.read().strip()) + except Exception as E: + pass + + return h, g, pnoinfo
+ + +
+[docs] + def perturbative_f12_correction(self, rdm1: numpy.ndarray = None, rdm2: numpy.ndarray = None, n_ri: int = None, + f12_filename: str = "molecule_f12tensor.bin", **kwargs) -> float: + """ + Computes the spin-free [2]_R12 correction, needing only the 1- and 2-RDM of a reference method + Requires either 1-RDM, 2-RDM or information to compute them in kwargs + + Parameters + ---------- + rdm1 : + 1-electron reduced density matrix + rdm2 : + 2-electron reduced density matrix + gamma : + f12-exponent, for a correlation factor f_12 = -1/gamma * exp[-gamma*r_12] + n_ri : + dimensionality of RI-basis; if None, then the maximum available via tensors / basis-set is used + f12_filename : + when using madness_interface, <q|h|p> and <rs|1/r_12|pq> already available; + need to provide f12-tensor <rs|f_12|pq> as ".bin" from madness or ".npy", assuming Mulliken ordering + kwargs : + e.g. RDM-information via {"U": QCircuit, "variables": optimal angles}, needs to be passed if rdm1,rdm2 not + yet computed + + Returns + ------- + the f12 correction for the energy + """ + from .f12_corrections._f12_correction_madness import ExplicitCorrelationCorrectionMadness + correction = ExplicitCorrelationCorrectionMadness(mol=self, rdm1=rdm1, rdm2=rdm2, n_ri=n_ri, + f12_filename=f12_filename, **kwargs) + + return correction.compute()
+ + + def __str__(self): + path = self.parameters.name + if hasattr(self, "datadir") and self.datadir is not None: + path = "{}/{}".format(self.datadir, path) + info = super().__str__() + info += "\n" + info += "{:15} : {}\n".format("executable", self.executable) + info += "{:15} : {}\n".format("htensor", "{}_htensor.npy".format(path)) + info += "{:15} : {}\n".format("gtensor", "{}_gtensor.npy".format(path)) + + return info + + def __repr__(self): + return self.__str__()
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/quantumchemistry/orbital_optimizer.html b/docs/sphinx/_modules/tequila_code/quantumchemistry/orbital_optimizer.html new file mode 100644 index 0000000..e99a9d9 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/quantumchemistry/orbital_optimizer.html @@ -0,0 +1,381 @@ + + + + + + + + tequila_code.quantumchemistry.orbital_optimizer — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.quantumchemistry.orbital_optimizer

+import numpy
+import typing
+import copy
+import warnings
+from dataclasses import dataclass, field
+
+from tequila import QCircuit, ExpectationValue, minimize, TequilaWarning
+from . import QuantumChemistryBase, ParametersQC, NBodyTensor
+
+"""
+Small application that wraps a tequila VQE object and passes it to the PySCF CASSCF solver.
+This way we can conveniently optimize orbitals.
+This basically does what is described here in the context of orbital-optimized unitary coupled-cluster (oo-ucc): https://journals.aps.org/prresearch/pdf/10.1103/PhysRevResearch.2.033421
+Of course we don't have to use UCC circuits but can pass whatever we want as circuit, or pass a "vqe_solver" object.
+
+The Interface with the PySCF module follows the original PySCF article  https://arxiv.org/abs/2002.12531 (see Fig.3)
+
+Currently this is a beta version (not extensively used in real life), so be careful when using it and please report issues on github :-)
+"""
+
+
+[docs] +@dataclass +class OptimizeOrbitalsResult: + + old_molecule: QuantumChemistryBase = None # the old tequila molecule + molecule: QuantumChemistryBase = None # the new tequila molecule with transformed orbitals + mcscf_object:object = None # the pyscf mcscf object + mcscf_local_data:dict = None + mo_coeff = None # the optimized mo coefficients + energy: float = None # the optimized energy + iterations:int = 0 + + def __call__(self, local_data, *args, **kwargs): + # use as callback + if "u" in local_data: + self.rotation_matrix = copy.deepcopy(local_data["u"]) + self.mcscf_local_data=local_data + self.iterations += 1
+ + +
+[docs] +def optimize_orbitals(molecule, circuit=None, vqe_solver=None, pyscf_arguments=None, silent=False, + vqe_solver_arguments=None, initial_guess=None, return_mcscf=False, use_hcb=False, molecule_factory=None, molecule_arguments=None, restrict_to_active_space=True, *args, **kwargs): + """ + + Parameters + ---------- + molecule: The tequila molecule whose orbitals are to be optimized + circuit: The circuit that defines the ansatz to the wavefunction in the VQE + can be None, if a customized vqe_solver is passed that can construct a circuit + vqe_solver: The VQE solver (the default - vqe_solver=None - will take the given circuit and construct an expectationvalue out of molecule.make_hamiltonian and the given circuit) + A customized object can be passed that needs to be callable with the following signature: vqe_solver(H=H, circuit=self.circuit, molecule=molecule, **self.vqe_solver_arguments) + pyscf_arguments: Arguments for the MCSCF structure of PySCF, if None, the defaults are {"max_cycle_macro":10, "max_cycle_micro":3} (see here https://pyscf.org/pyscf_api_docs/pyscf.mcscf.html) + silent: silence printout + use_hcb: indicate if the circuit is in hardcore Boson encoding + vqe_solver_arguments: Optional arguments for a customized vqe_solver or the default solver + for the default solver: vqe_solver_arguments={"optimizer_arguments":A, "restrict_to_hcb":False} where A holds the kwargs for tq.minimize + restrict_to_hcb keyword controls if the standard (in whatever encoding the molecule structure has) Hamiltonian is constructed or the hardcore_boson hamiltonian + initial_guess: Initial guess for the MCSCF module of PySCF (Matrix of orbital rotation coefficients) + The default (None) is a unit matrix + predefined commands are + initial_guess="random" + initial_guess="random_loc=X_scale=Y" with X and Y being floats + This initialized a random guess using numpy.random.normal(loc=X, scale=Y) with X=0.0 and Y=0.1 as defaults + return_mcscf: return the PySCF MCSCF structure after optimization + molecule_arguments: arguments to pass to molecule_factory or default molecule constructor | only change if you know what you are doing + args: just here for convenience + kwargs: just here for conveniece + + Returns + ------- + Optimized Tequila Molecule + """ + + try: + from pyscf import mcscf + from . import QuantumChemistryPySCF + except Exception as exception: + raise Exception("{}\noptimize_orbitals: Need pyscf to run (pip install pyscf)".format(str(exception))) + + if pyscf_arguments is None: + pyscf_arguments = {"max_cycle_macro": 10, "max_cycle_micro": 3} + no = molecule.n_orbitals + + if not isinstance(molecule, QuantumChemistryPySCF): + pyscf_molecule = QuantumChemistryPySCF.from_tequila(molecule=molecule, transformation=molecule.transformation) + else: + pyscf_molecule = molecule + + mf = pyscf_molecule._get_hf() + result=OptimizeOrbitalsResult() + mc = mcscf.CASSCF(mf, pyscf_molecule.n_orbitals, pyscf_molecule.n_electrons) + mc.callback=result + c = pyscf_molecule.compute_constant_part() + + if circuit is None and vqe_solver is None: + raise Exception("optimize_orbitals: Either provide a circuit or a callable vqe_solver") + + if use_hcb: + if vqe_solver_arguments is None: + vqe_solver_arguments={} + vqe_solver_arguments["restrict_to_hcb"]=True + # consistency check + n_qubits = len(circuit.qubits) + n_orbitals = molecule.n_orbitals + if n_qubits > n_orbitals: + warnings.warn("Potential inconsistency in orbital optimization: use_hcb is switched on but we have\n n_qubits={} in the circuit\n n_orbital={} in the molecule\n".format(n_qubits,n_orbitals), TequilaWarning) + + if molecule_arguments is None: + molecule_arguments = {"parameters": pyscf_molecule.parameters, "transformation": molecule.transformation} + + wrapper = PySCFVQEWrapper(molecule_arguments=molecule_arguments, n_electrons=pyscf_molecule.n_electrons, + const_part=c, circuit=circuit, vqe_solver_arguments=vqe_solver_arguments, silent=silent, + vqe_solver=vqe_solver, molecule_factory=molecule_factory, *args, **kwargs) + mc.fcisolver = wrapper + mc.internal_rotation = True + if pyscf_arguments is not None: + for k, v in pyscf_arguments.items(): + if hasattr(mc, str(k)): + setattr(mc, str(k), v) + else: + print("unknown arguments: {}".format(k)) + if not silent: + print("Optimizing Orbitals with PySCF and VQE Solver:") + print("{:25} : {}".format("pyscf_arguments", pyscf_arguments)) + print(wrapper) + if initial_guess is not None: + if hasattr(initial_guess, "lower"): + if "random" or "near_zero" in initial_guess.lower(): + scale = 1.e-3 + if "random" in initial_guess.lower(): + scale = 1.0 + loc = 0.0 + if "scale" in kwargs: + scale = float(initial_guess.split("scale")[1].split("_")[0].split("=")[1]) + if "loc" in kwargs: + loc = float(initial_guess.split("loc")[1].split("_")[0].split("=")[1]) + initial_guess = numpy.eye(no) + numpy.random.normal(scale=scale, loc=loc, size=no * no).reshape(no, no) + else: + raise Exception("Unknown initial_guess={}".format(initial_guess.lower())) + + assert len(initial_guess.shape) == 2 + assert initial_guess.shape[0] == no + assert initial_guess.shape[1] == no + initial_guess = mcscf.project_init_guess(mc, initial_guess) + mc.kernel(mo_coeff=initial_guess) + else: + mc.kernel() + # make new molecule + + mo_coeff = mc.mo_coeff + transformed_molecule = pyscf_molecule.transform_orbitals(orbital_coefficients=mo_coeff, name="optimized") + result.molecule=transformed_molecule + result.old_molecule=molecule + result.mo_coeff=mo_coeff + result.energy=mc.e_tot + + if return_mcscf: + result.mcscf_object = mc + + return result
+ + +
+[docs] +@dataclass +class PySCFVQEWrapper: + """ + Wrapper for tequila VQE's to be compatible with PySCF orbital optimization + """ + + # needs initialization + n_electrons: int = None + molecule_arguments: dict = None + + # internal data + rdm1: numpy.ndarray = None + rdm2: numpy.ndarray = None + one_body_integrals: numpy.ndarray = None + two_body_integrals: numpy.ndarray = None + history: list = field(default_factory=list) + + # optional + const_part: float = 0.0 + silent: bool = False + vqe_solver: typing.Callable = None + circuit: QCircuit = None + vqe_solver_arguments: dict = field(default_factory=dict) + molecule_factory: typing.Callable = None + +
+[docs] + def reorder(self, M, ordering, to): + # convenience since we need to reorder + # all the time + M = NBodyTensor(elems=M, ordering=ordering) + M.reorder(to=to) + return M.elems
+ + +
+[docs] + def kernel(self, h1, h2, *args, **kwargs): + if self.history is None: + self.history = [] + h2of = self.reorder(h2, "mulliken", "openfermion") + restrict_to_hcb = self.vqe_solver_arguments is not None and "restrict_to_hcb" in self.vqe_solver_arguments and \ + self.vqe_solver_arguments["restrict_to_hcb"] + + if self.molecule_factory is None: + molecule = QuantumChemistryBase(one_body_integrals=h1, two_body_integrals=h2of, + nuclear_repulsion=self.const_part, n_electrons=self.n_electrons, + **self.molecule_arguments) + else: + molecule = self.molecule_factory(one_body_integrals=h1, two_body_integrals=h2of, + nuclear_repulsion=self.const_part, n_electrons=self.n_electrons, + **self.molecule_arguments) + if restrict_to_hcb: + H = molecule.make_hardcore_boson_hamiltonian() + else: + H = molecule.make_hamiltonian() + if self.vqe_solver is not None: + vqe_solver_arguments = {} + if self.vqe_solver_arguments is not None: + vqe_solver_arguments = self.vqe_solver_arguments + result = self.vqe_solver(H=H, circuit=self.circuit, molecule=molecule, **vqe_solver_arguments) + elif self.circuit is None: + raise Exception("Orbital Optimizer: Either provide a callable vqe_solver or a circuit") + else: + U = self.circuit + E = ExpectationValue(H=H, U=U) + optimizer_arguments = {} + if self.vqe_solver_arguments is not None and "optimizer_arguments" in self.vqe_solver_arguments: + optimizer_arguments = self.vqe_solver_arguments["optimizer_arguments"] + if self.silent is not None and "silent" not in optimizer_arguments: + optimizer_arguments["silent"] = True + + result = minimize(E, **optimizer_arguments) + if hasattr(result, "circuit"): + # potential adaptive ansatz + U = result.circuit + self.circuit = U + else: + # static ansatz + U = self.circuit + + rdm1, rdm2 = molecule.compute_rdms(U=U, variables=result.variables, spin_free=True, get_rdm1=True, get_rdm2=True, use_hcb=restrict_to_hcb) + rdm2 = self.reorder(rdm2, 'dirac', 'mulliken') + if not self.silent: + print("{:20} : {}".format("energy", result.energy)) + if len(self.history) > 0: + print("{:20} : {}".format("deltaE", result.energy - self.history[-1].energy)) + print("{:20} : {}".format("||delta RDM1||", numpy.linalg.norm(self.rdm1 - rdm1))) + self.history.append(result) + self.rdm1 = rdm1 + self.rdm2 = rdm2 + self.one_body_integrals = h1 + self.two_body_integrals = h2 + return result.energy, None
+ + +
+[docs] + def make_rdm12(self, *args, **kwargs): + return self.rdm1, self.rdm2
+ + + def __str__(self): + result = "{}\n".format(type(self).__name__) + for k, v in self.__dict__.items(): + if k == "circuit" and v is not None: + result += "{:30} : {}\n".format(k, "{} gates, {} parameters".format(len(v.gates), + len(v.extract_variables()))) + else: + result += "{:30} : {}\n".format(k, v) + return result
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/quantumchemistry/psi4_interface.html b/docs/sphinx/_modules/tequila_code/quantumchemistry/psi4_interface.html new file mode 100644 index 0000000..99bc735 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/quantumchemistry/psi4_interface.html @@ -0,0 +1,815 @@ + + + + + + + + tequila_code.quantumchemistry.psi4_interface — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.quantumchemistry.psi4_interface

+from tequila import TequilaException, TequilaWarning
+
+from tequila.circuit import QCircuit
+from tequila.objective.objective import Variables
+from tequila.quantumchemistry.qc_base import QuantumChemistryBase
+from tequila.quantumchemistry.chemistry_tools import ClosedShellAmplitudes, Amplitudes
+from tequila.quantumchemistry import ParametersQC, NBodyTensor
+
+from .chemistry_tools import ActiveSpaceData, OrbitalData
+
+import copy
+import numpy
+import typing
+import psi4
+import warnings
+
+from dataclasses import dataclass
+
+
+
+[docs] +class TequilaPsi4Exception(TequilaException): + pass
+ + + +
+[docs] +class OpenVQEEPySCFException(TequilaException): + pass
+ + + +
+[docs] +@dataclass +class Psi4Results: + variables: dict = None # psi4 variables dictionary, storing all computed values + filename: str = None # psi4 output file + wfn: typing.Union[ + psi4.core.Wavefunction, psi4.core.CCWavefunction, psi4.core.CIWavefunction] = None # psi4 wavefunction + mol: psi4.core.Molecule = None
+ + + +
+[docs] +class QuantumChemistryPsi4(QuantumChemistryBase): + + def _make_psi4_active_space_data(self, active_orbitals, reference=None): + """ + Small helper function + Internal use only + Parameters + ---------- + active_orbitals: dictionary : + dictionary with irreps as keys and a list of integers as values + i.e. occ = {"A1":[0,1], "A2":[0]} + means the occupied active space is made up of spatial orbitals + 0A1, 1A1 and 0A2 + as list: Give a list of spatial orbital indices + i.e. occ = [0,1,3] means that spatial orbital 0, 1 and 3 are used + reference: (Default value=None) + List of orbitals which form the reference + Can be given in the same format as active_orbitals + If given as None then the first N_electron/2 orbitals are taken + and the corresponding active orbitals are removed + + Returns + ------- + Dataclass with active indices and reference indices (in spatial notation) + + """ + + if active_orbitals is None: + return None + + @dataclass + class ActiveSpaceDataPsi4(ActiveSpaceData): + + frozen_docc: list = None # frozen reference orbitals grouped by irrep (psi4 option, if None then the active space can not be represented by psi4) + frozen_uocc: list = None # frozen virtual orbtials grouped by irrep (psi4 option, if None then the active space can not be represented by psi4) + + def __str__(self): + result = super().__str__() + result += "{key:15} : {value:15} \n".format(key="frozen_docc", value=str(self.frozen_docc)) + result += "{key:15} : {value:15} \n".format(key="frozen_uocc", value=str(self.frozen_uocc)) + return result + + @property + def psi4_representable(self): + standard_ref = [self.reference_orbitals[0] == 0] + [ + self.reference_orbitals[i] == self.reference_orbitals[i + 1] - 1 for i in + range(len(self.reference_orbitals) - 1)] + return self.frozen_docc is not None and self.frozen_uocc is not None and all(standard_ref) + + # transform irrep notation to absolute ints + active_idx = active_orbitals + ref_idx = reference + if isinstance(active_orbitals, dict): + active_idx = [] + for key, value in active_orbitals.items(): + active_idx += [self.orbitals_by_irrep[key.upper()][i].idx_total for i in value] + elif active_orbitals is None: + active_idx = [i for i in range(self.n_orbitals)] + + standard_ref = sorted([i for i in range(self.n_electrons // 2)]) + if isinstance(reference, dict): + ref_idx = [] + for key, value in reference.items(): + orbitals = [self.orbitals_by_irrep[key.upper()][i] for i in value] + ref_idx += [x.idx_total for x in orbitals] + ref_idx = sorted(ref_idx) + elif reference is None: + assert (self.n_electrons % 2 == 0) + ref_idx = standard_ref + + # determine if the active space can be represented by psi4 + # reference needs to be the scf reference + # all frozen orbitals need to be without gaps since we can not freeze individual orbitals + frozen_docc = None + if ref_idx == standard_ref: + frozen_docc = [0] * self.nirrep + frozen_docc_all = [self.orbitals[i] for i in standard_ref if self.orbitals[i].idx_total not in active_idx] + for i, irrep in enumerate(self.irreps): + sorted_array = sorted([x.idx_irrep for x in frozen_docc_all if x.irrep.upper() == irrep.upper()]) + frozen_docc[i] = len(sorted_array) + if len(sorted_array) > 0 and (sorted_array[0] != 0 and sorted_array[-1] != len(sorted_array) - 1): + frozen_docc = None + print("active space not CAS type: frozen_docc of {} ".format(irrep), sorted_array) + break + + # and the same for the unoccupied ones + frozen_uocc = None + if frozen_docc is not None: + frozen_uocc = [0] * self.nirrep + frozen_uocc_all = [o for o in self.orbitals if o.idx_total not in active_idx + ref_idx] + for i, irrep in enumerate(self.irreps): + if irrep not in self.orbitals_by_irrep: + continue + sorted_array = sorted([x.idx_irrep for x in frozen_uocc_all if x.irrep.upper() == irrep.upper()]) + frozen_uocc[i] = len(sorted_array) + last = self.orbitals_by_irrep[irrep][-1] + if len(sorted_array) > 0 and ( + sorted_array[-1] != last.idx_irrep or sorted_array[-1] != sorted_array[0] + len( + sorted_array) - 1): + frozen_uocc = None + break + + return ActiveSpaceDataPsi4(active_orbitals=sorted(active_idx), + reference_orbitals=sorted(ref_idx), + frozen_docc=frozen_docc, + frozen_uocc=frozen_uocc) + + def __init__(self, parameters: ParametersQC, + transformation: typing.Union[str, typing.Callable] = None, + active_orbitals=None, + reference_orbitals=None, + frozen_orbitals=None, + *args, + **kwargs): + """ + + Parameters + ---------- + parameters + transformation + active_orbitals: dictionary : + dictionary with irreps as keys and a list of integers as values + i.e. occ = {"A1":[0,1], "A2":[0]} + means the occupied active space is made up of spatial orbitals + 0A1, 1A1 and 0A2 + as list: Give a list of spatial orbital indices + i.e. occ = [0,1,3] means that spatial orbital 0, 1 and 3 are used + reference: (Default value=None) + List of orbitals which form the reference + Can be given in the same format as active_orbitals + If given as None then the first N_electron/2 orbitals are taken + and the corresponding active orbitals are removed + args + kwargs + """ + psi4.core.clean() + psi4.core.clean_options() + psi4.core.clean_variables() + + psi4.core.clean() + psi4.core.clean_options() + psi4.core.clean_variables() + + self.psi4_mol = psi4.geometry(parameters.get_geometry_string()) + psi4.activate(self.psi4_mol) + self._point_group = self.psi4_mol.point_group().symbol() + if "point_group" in kwargs: + self._point_group = kwargs["point_group"] + + self.energies = {} # history to avoid recomputation + self.logs = {} # store full psi4 output + + # psi4 active space will be formed later + super().__init__(parameters=parameters, transformation=transformation, active_orbitals=None, + reference_orbitals=reference_orbitals,frozen_orbitals=[], + *args, **kwargs) + + oenergies = [] + for i in self.irreps: + oenergies += [(i, j, x) for j, x in enumerate(self.orbital_energies(irrep=i))] + + oenergies = sorted(oenergies, key=lambda x: x[2]) + + for x in self.orbitals: + x.irrep = oenergies[x.idx_total][0] + x.idx_irrep = oenergies[x.idx_total][1] + x.energy = oenergies[x.idx_total][2] + + orbitals_by_irrep = {o.irrep: [] for o in self.orbitals} + for o in self.orbitals: + orbitals_by_irrep[o.irrep] += [o] + + self.orbitals_by_irrep = orbitals_by_irrep + if reference_orbitals is None: + reference_orbitals = [x.idx_total for x in self.reference_orbitals] + + if active_orbitals is None: + active_orbitals = [i for i in range(self.n_orbitals)] + + if frozen_orbitals is None and self.parameters.frozen_core: + frozen_orbitals = [i for i in range(self.parameters.get_number_of_core_electrons()//2)] + + def list_to_irrep_dict(orbital_list): + # assume we have been given a list of orbitals with their total indices instead of a dictionary with irreps + active_dict = {} + if orbital_list is None: + return active_dict + for x in orbital_list: + orbital = self.orbitals[x] + if orbital.irrep not in active_dict: + active_dict[orbital.irrep] = [orbital.idx_irrep] + else: + active_dict[orbital.irrep] += [orbital.idx_irrep] + return active_dict + + if not hasattr(active_orbitals, "keys"): + active_orbitals = list_to_irrep_dict(active_orbitals) + + if not hasattr(reference_orbitals, "keys"): + reference_orbitals = list_to_irrep_dict(reference_orbitals) + + if not hasattr(frozen_orbitals, "keys"): + frozen_orbitals = list_to_irrep_dict(frozen_orbitals) + + # remove frozen-orbitals from active orbitals + for k,v in frozen_orbitals.items(): + for x in v: + if k in active_orbitals and x in active_orbitals[k]: + active_orbitals[k].remove(x) + + self.integral_manager.active_space = self._make_psi4_active_space_data(active_orbitals=active_orbitals, + reference=reference_orbitals) + # need to recompute + # (psi4 won't take over active space information otherwise) + self.compute_energy(method="hf", recompute=True, *args, **kwargs) + self.ref_wfn = self.logs["hf"].wfn + + self.transformation = self._initialize_transformation(transformation=transformation, *args, **kwargs) + + self.kwargs = kwargs + + @property + def point_group(self): + return self._point_group + + @property + def nirrep(self): + return self.ref_wfn.nirrep() + +
+[docs] + def orbital_energies(self, irrep: typing.Union[int, str] = None, beta: bool = False, wfn=None): + """ + Returns orbital energies of a given irrep + or all orbital energies of all irreps (default) + + Parameters + ---------- + irrep: int or str : + int: specify the irrep by number (in cotton ordering) + str: specify the irrep by name (like 'A1') + specify from which irrep you want the orbital energies + psi4 orders irreps in 'Cotton ordering' + http://www.psicode.org/psi4manual/master/psithonmol.html#table-irrepordering + beta: bool : (Default value=False) + get the beta electrons + + Returns + ------- + list or orbital energies + """ + if wfn is None: + wfn = self.ref_wfn + + if hasattr(irrep, "upper"): + irrep = self.irreps.index(irrep.upper()) + + if beta: + tmp = psi4.driver.p4util.numpy_helper._to_array(wfn.epsilon_b(), dense=False) + else: + tmp = psi4.driver.p4util.numpy_helper._to_array(wfn.epsilon_a(), dense=False) + + if irrep is None or self.point_group.lower() == "c1": + result = [] + for x in tmp: + result += [x] + return result + else: + return tmp[irrep]
+ + +
+[docs] + def initialize_integral_manager(self, *args, **kwargs): + # get HF wavefunction and orbital coefficients + if "ref_wfn" in kwargs: + ref_wfn = kwargs["ref_wfn"] + hf_energy = 0.0 + else: + hf_energy = self.compute_energy(method="hf", ignore_active_space=True, + options={"RHF__FAIL_ON_MAXITER": False}, point_group=self.point_group) + ref_wfn = self.logs['hf'].wfn + + if ref_wfn.nirrep() != 1: + wfn = ref_wfn.c1_deep_copy(ref_wfn.basisset()) + else: + wfn = ref_wfn + Ca = numpy.asarray(wfn.Ca()) + + basisset = ref_wfn.basisset() + mints = psi4.core.MintsHelper(basisset) + + # get integrals in atomic basis + S = numpy.asarray(mints.ao_overlap()) + h = numpy.asarray(wfn.H()) + g = numpy.asarray(mints.ao_eri()) + c = float(wfn.variables()['NUCLEAR REPULSION ENERGY']) + + g = NBodyTensor(elems=numpy.asarray(g), ordering='chem') + + kwargs["overlap_integrals"] = S + kwargs["two_body_integrals"] = g + kwargs["one_body_integrals"] = h + kwargs["constant_term"] = c + kwargs["orbital_coefficients"] = Ca + kwargs["basis_type"] = "GBS" + kwargs["basis_name"] = self.parameters.basis_set + + irreps = [self.psi4_mol.point_group().char_table().gamma(i).symbol().upper() for i in range(ref_wfn.nirrep())] + + self.irreps = irreps + + oenergies = [] + for i in self.irreps: + oenergies += [(i, j, x) for j, x in enumerate(self.orbital_energies(irrep=i, wfn=ref_wfn))] + + oenergies = sorted(oenergies, key=lambda x: x[2]) + + if "orbitals" in kwargs: + orbitals = kwargs["orbitals"] + else: + orbitals = None + + if orbitals is None: + orbitals = [OrbitalData(idx_total=i) for i in range(h.shape[0])] + + for x in orbitals: + x.irrep = oenergies[x.idx_total][0] + x.idx_irrep = oenergies[x.idx_total][1] + x.energy = oenergies[x.idx_total][2] + + kwargs["orbitals"] = orbitals + + # set some psi4 specific features + self.ref_energy = hf_energy + self.ref_wfn = self.logs['hf'].wfn + self.irreps = irreps + + return super().initialize_integral_manager(*args, **kwargs)
+ + +
+[docs] + def compute_ccsd_amplitudes(self): + return self.compute_amplitudes(method='ccsd')
+ + + def _run_psi4(self, options: dict, method=None, return_wfn=True, point_group=None, filename: str = None, + guess_wfn=None, ref_wfn=None, ignore_active_space=False, *args, **kwargs): + psi4.core.clean() + psi4.core.clean_variables() + psi4.core.clean_options() + + if "threads" in kwargs: + psi4.set_num_threads(nthread=kwargs["threads"]) + + if filename is None: + filename = "{}_{}.out".format(self.parameters.filename, method) + + psi4.core.set_output_file(filename) + + # easier guess read in + if guess_wfn is not None: + if isinstance(guess_wfn, QuantumChemistryPsi4): + guess_wfn = guess_wfn.logs["hf"].wfn + if isinstance(guess_wfn, str): + guess_wfn = psi4.core.Wavefunction.from_file(guess_wfn) + guess_wfn.to_file(guess_wfn.get_scratch_filename(180)) # this is necessary + options["guess"] = "read" + + # prevent known flaws + if "guess" in options and options["guess"].lower() == "read": + options["basis_guess"] = False + # additionally the outputfile needs to be the same + # as in the previous guess + # this can not be determined here + # better pass down a guess_wfn + + mol = psi4.geometry(self.parameters.get_geometry_string()) + mol.set_multiplicity(self.parameters.multiplicity) + if self.parameters.multiplicity != 1: + raise TequilaPsi4Exception("Multiplicity != 1 no yet supported") + mol.set_molecular_charge(self.parameters.charge) + + if point_group is not None: + mol.reset_point_group(point_group.lower()) + + if ref_wfn is None and hasattr(self, "ref_wfn"): + ref_wfn = self.ref_wfn + + if point_group is not None and point_group.lower() == "c1": + ref_wfn = None # ref_wfn.c1_deep_copy(ref_wfn.basisset()) # CC will not converge otherwise + guess_wfn = None + + psi4.activate(mol) + + psi4.set_options(options) + if ref_wfn is None or method.lower() == "hf": + energy, wfn = psi4.energy(name=method.lower(), return_wfn=return_wfn, molecule=mol) + else: + energy, wfn = psi4.energy(name=method.lower(), ref_wfn=ref_wfn, return_wfn=return_wfn, molecule=mol, + guess_wfn=guess_wfn) + self.energies[method.lower()] = energy + self.logs[method.lower()] = Psi4Results(filename=filename, variables=copy.deepcopy(psi4.core.variables()), + wfn=wfn, mol=mol) + return energy, wfn + + def _extract_active_space(self, arr): + """ + Internal function that helps to convert CCSD amplitudes if an actice space was set + """ + if self.integral_manager.active_space is None: + return arr + elif len(self.integral_manager.active_space.active_orbitals) == self.integral_manager.one_body_integrals.shape[ + 0]: + return arr + + if isinstance(arr, ClosedShellAmplitudes): + result = {} + for k, v in arr.__dict__.items(): + if v is not None: + result[k] = self._extract_active_space(arr=v) + + return ClosedShellAmplitudes(**result) + asd = self.integral_manager.active_space + aocc = [i for i in asd.active_orbitals if i in asd.reference_orbitals] + avir = [i for i in asd.active_orbitals if i not in asd.reference_orbitals] + assert self.n_orbitals == len(aocc) + len(avir) + assert self.n_electrons == len(aocc) * 2 + + n_orb_total = len(self.orbitals) + n_electrons_total = self.n_electrons + 2 * len(asd.frozen_reference_orbitals) + nocc = n_electrons_total // 2 + nvirt = n_orb_total - nocc + avir = [x - nocc for x in avir] + nav = len(avir) + nao = len(aocc) + + arr_shape = arr.shape + final_shape = [] + active_sets = [] + + for i in arr_shape: + if i == nocc: + final_shape.append(nao) + active_sets.append(aocc) + elif i == nvirt: + final_shape.append(nav) + active_sets.append(avir) + else: + assert i == nocc + nvirt + final_shape.append(nao + nav) + active_sets.append(aocc + avir) + + final_shape = tuple(final_shape) + + def func(*args): + result = 1 + for i in range(len(args)): + result *= args[i] in active_sets[i] + return result + + c = numpy.fromfunction( + function=numpy.vectorize(func), + shape=arr_shape, dtype=numpy.int) + + return numpy.extract(condition=c, arr=arr).reshape(final_shape) + + #def compute_mp2_amplitudes(self, active_orbitals=None, *args, **kwargs) -> ClosedShellAmplitudes: + # return self._extract_active_space(super().compute_mp2_amplitudes(*args, **kwargs)) + +
+[docs] + def compute_amplitudes(self, method: str, + options: dict = None, + filename: str = None, + *args, + **kwargs) -> typing.Union[ + Amplitudes, ClosedShellAmplitudes]: + + if options is None: + options = {} + + options['basis'] = self.parameters.basis_set + + if method.lower() == "mp2": + return self.compute_mp2_amplitudes() + try: + psi4.core.clean_options() + psi4.core.clean_variables() + energy, wfn = self._run_psi4(method=method, + options=options, + point_group='c1', + ref_wfn=self.ref_wfn.c1_deep_copy(self.ref_wfn.basisset()), + filename=filename, + *args, + **kwargs) + all_amplitudes = wfn.get_amplitudes() + closed_shell = isinstance(wfn.reference_wavefunction(), psi4.core.RHF) + if closed_shell: + return self._extract_active_space( + ClosedShellAmplitudes(**{k: v.to_array() for k, v in all_amplitudes.items()})) + else: + assert (self.integral_manager.trivial_active_space()) # only for closed-shell currently + return Amplitudes(**{k: v.to_array() for k, v in all_amplitudes.items()}) + except Exception as err: + raise TequilaPsi4Exception("\nFailed to compute {} amplitudes.\n" \ + "Make sure that you don't read in previous wavefunctions." + "Active spaces might get you in trouble.".format(method))
+ + +
+[docs] + def compute_energy(self, method: str = "fci", options=None, recompute: bool = True, ignore_active_space=False, + *args, **kwargs): + if not recompute and method.lower() in self.energies and not "point_group" in kwargs: + return self.energies[method.lower()] + + if options is None: + options = {} + + options['basis'] = self.parameters.basis_set + if not ignore_active_space and not self.integral_manager.active_space_is_trivial() and self.active_space.psi4_representable: + options['frozen_docc'] = self.active_space.frozen_docc + if sum(self.active_space.frozen_uocc) > 0 and method.lower() not in ["hf", "fci", "detci"]: + print( + "There are known issues with some psi4 methods and frozen virtual orbitals. Proceed with fingers crossed for {}.".format( + method)) + options['frozen_uocc'] = self.active_space.frozen_uocc + if not ignore_active_space and not self.active_space.psi4_representable and not self.integral_manager.active_space_is_trivial(): + warnings.warn("Warning: Active space is not Psi4 representable", TequilaWarning) + return self._run_psi4(method=method, options=options, ignore_active_space=ignore_active_space, *args, **kwargs)[ + 0]
+ + + def __str__(self): + result = super().__str__() + result += "\nPsi4 Data\n" + result += "{key:15} : {value:15} \n".format(key="Point Group (full)", + value=self.psi4_mol.get_full_point_group().lower()) + result += "{key:15} : {value:15} \n".format(key="Point Group (used)", value=self.point_group) + result += "{key:15} : {value} \n".format(key="nirrep", value=self.nirrep) + result += "{key:15} : {value} \n".format(key="irreps", value=self.irreps) + result += "{key:15} : {value:15} \n".format(key="mos per irrep", value=str([len(self.orbital_energies(irrep=i)) for i in range(self.nirrep)])) + + return result + + @property + def rdm1(self) -> tuple: + return super().rdm1 + + @property + def rdm2(self) -> tuple: + return super().rdm2 + +
+[docs] + def compute_rdms(self, U: QCircuit = None, variables: Variables = None, spin_free: bool = True, + get_rdm1: bool = True, get_rdm2: bool = True, psi4_method: str = None, + psi4_options: dict = {}, *args, **kwargs): + """ + Same functionality as qc_base.compute_rdms (look there for more information), + plus the additional option to compute 1- and 2-RDM using psi4 by the keyword psi4_rdms + + Parameters + ---------- + U : + Quantum Circuit to achieve the desired state \\psi = U |0\\rangle, optional if psi4_rdms is set to True + variables : + If U is parametrized, then need to hand over a set of fixed variables + spin_free : + Set whether matrices should be spin-free (summation over spin) or defined by spin-orbitals + get_rdm1, get_rdm2 : + Set whether either one or both rdm1, rdm2 should be computed. If both are needed at some point, + it is recommended to compute them at once. + Note that whatever is specified in psi4_options has priority. + psi4_method: + Method to be run, currently only methods returning a CIWavefuntion are supported + (e.g. "detci" + ex_level in options, or "fci", "cisdt", "casscf", but NOT "cisd") + psi4_options: + Options to be handed over to psi4, containing e.g. excitation level of "detci"-method. + If "detci__opdm" for 1-RDM and "detci__tpdm" for 2-RDM are not included, the keywords get_rdm1, get_rdm2 are + used (if both are specified, prioritizing psi4_options). + + Returns + ------- + """ + if not psi4_method: + return super().compute_rdms(U=U, variables=variables, spin_free=spin_free, + get_rdm1=get_rdm1, get_rdm2=get_rdm2, *args, **kwargs) + else: + # Get 1- and 2-particle reduced density matrix via Psi4 CISD computation + # If "cisd" is chosen, change to "detci" (default is excitation level 2 anyhow) to obtain a CIWavefunction + if psi4_method.lower() == "cisd": + print("Changed psi4_method from 'cisd' to 'detci' with ex_level=2 s.th. psi4 returns a CIWavefunction.") + psi4_method = "detci" + # Set options if not handed over + psi4_options = {k.lower(): v for k, v in psi4_options.items()} # set to lower-case for string comparison + if "detci__opdm" not in psi4_options.keys(): + psi4_options.update({"detci__opdm": get_rdm1}) + if "detci__tpdm" not in psi4_options.keys(): + psi4_options.update({"detci__tpdm": get_rdm2}) + if psi4_method.lower() == "detci" and "detci__ex_level" not in psi4_options.keys(): + psi4_options.update({"detci__ex_level": 2}) # use CISD as default + print(psi4_options) + + # Compute and set matrices + self.compute_energy(psi4_method, options=psi4_options) + wfn = self.logs[psi4_method].wfn + if psi4_options["detci__opdm"]: + rdm1 = psi4.driver.p4util.numpy_helper._to_array(wfn.get_opdm(-1, -1, "SUM", False), dense=True) + self._rdm1 = rdm1 + if psi4_options["detci__tpdm"]: + rdm2 = psi4.driver.p4util.numpy_helper._to_array(wfn.get_tpdm("SUM", False), dense=True) + rdm2 = NBodyTensor(elems=rdm2, ordering='chem') + rdm2.reorder(to='phys') # RDMs in physics ordering (cp. to NBodyTensor in qc_base.py) + rdm2 = 2 * rdm2.elems # Factor 2 since psi4 normalizes 2-rdm by 1/2 + self._rdm2 = rdm2
+ + +
+[docs] + def perturbative_f12_correction(self, rdm1: numpy.ndarray = None, rdm2: numpy.ndarray = None, gamma: float = 1.4, + n_ri: int = None, cabs_type: str = "active", cabs_options: dict = None, + **kwargs) -> float: + """ + Computes the spin-free [2]_R12 correction, needing only the 1- and 2-RDM of a reference method + Requires either 1-RDM, 2-RDM or information to compute them in kwargs + + Parameters + ---------- + rdm1 : + 1-electron reduced density matrix + rdm2 : + 2-electron reduced density matrix + gamma : + f12-exponent, for a correlation factor f_12 = -1/gamma * exp[-gamma*r_12] + n_ri : + dimensionality of RI-basis; if None, then the maximum available via tensors / basis-set is used + cabs_type : + - either "active" for using a given basis set as is as approximative CBS (complete basis set), and specify + OBS (orbital basis) by an active space + - or "cabs+" for CABS+-approach as in + Valeev, E. F. (2004). Improving on the resolution of the identity in linear R12 ab initio theories. + Chemical Physics Letters, 395(4–6), 190–195. https://doi.org/10.1016/j.cplett.2004.07.061 + -> pass cabs_name in cabs_options + cabs_options : + dict, which needs at least {"cabs_name": some CABS basis set} if cabs_type=="cabs+" + kwargs : + e.g. RDM-information via {"U": QCircuit, "variables": optimal angles} if computation via VQE, + or {"rdm__psi4_method": some CI method, "rdm__psi4_options": dict with psi4 options} if computation via + psi4, compare to psi4_interface.compute_rdms + one of the above needs to be passed if rdm1,rdm2 not yet computed + + Returns + ------- + the f12 correction for the energy + """ + from .f12_corrections._f12_correction_psi4 import ExplicitCorrelationCorrectionPsi4 + correction = ExplicitCorrelationCorrectionPsi4(mol=self, rdm1=rdm1, rdm2=rdm2, gamma=gamma, + n_ri=n_ri, cabs_type=cabs_type, cabs_options=cabs_options, + **kwargs) + + return correction.compute()
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/quantumchemistry/pyscf_interface.html b/docs/sphinx/_modules/tequila_code/quantumchemistry/pyscf_interface.html new file mode 100644 index 0000000..9b5d6e2 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/quantumchemistry/pyscf_interface.html @@ -0,0 +1,298 @@ + + + + + + + + tequila_code.quantumchemistry.pyscf_interface — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.quantumchemistry.pyscf_interface

+from tequila import TequilaException
+from tequila.quantumchemistry.qc_base import QuantumChemistryBase
+from tequila.quantumchemistry import ParametersQC, NBodyTensor
+import pyscf
+
+import numpy, typing
+
+
+
+[docs] +class OpenVQEEPySCFException(TequilaException): + pass
+ + + +
+[docs] +class QuantumChemistryPySCF(QuantumChemistryBase): + def __init__(self, parameters: ParametersQC, + transformation: typing.Union[str, typing.Callable] = None, + *args, **kwargs): + + if "one_body_integrals" not in kwargs: + + geometry = parameters.get_geometry() + pyscf_geomstring = "" + for atom in geometry: + pyscf_geomstring += "{} {} {} {};".format(atom[0], atom[1][0], atom[1][1], atom[1][2]) + + if "point_group" in kwargs: + point_group = kwargs["point_group"] + else: + point_group = None + + mol = pyscf.gto.Mole() + mol.atom = pyscf_geomstring + mol.basis = parameters.basis_set + mol.charge = parameters.charge + + if point_group is not None: + if point_group.lower() != "c1": + mol.symmetry = True + mol.symmetry_subgroup = point_group + else: + mol.symmetry = False + else: + mol.symmetry = True + + mol.build(parse_arg=False) + + # solve restricted HF + mf = pyscf.scf.RHF(mol) + mf.verbose = False + if "verbose" in kwargs: + mf.verbose = kwargs["verbose"] + + mf.kernel() + + # only works if point_group is not C1 + # otherwise PySCF uses a different SCF object + # irrep information is however not critical to tequila + if hasattr(mf, "get_irrep_nelec"): + self.irreps = mf.get_irrep_nelec() + else: + self.irreps = None + + orbital_energies = mf.mo_energy + + # compute mo integrals + mo_coeff = mf.mo_coeff + h_ao = mol.intor('int1e_kin') + mol.intor('int1e_nuc') + g_ao = mol.intor('int2e', aosym='s1') + S = mol.intor_symmetric("int1e_ovlp") + g_ao = NBodyTensor(elems=g_ao, ordering="mulliken") + + self.pyscf_molecule = mol + self.point_group = mol.symmetry_subgroup + + kwargs["overlap_integrals"] = S + kwargs["two_body_integrals"] = g_ao + kwargs["one_body_integrals"] = h_ao + kwargs["orbital_coefficients"] = mo_coeff + kwargs["orbital_type"] = "hf" + + if "nuclear_repulsion" not in kwargs: + kwargs["nuclear_repulsion"] = mol.energy_nuc() + + super().__init__(parameters=parameters, transformation=transformation, *args, **kwargs) + +
+[docs] + def compute_fci(self, *args, **kwargs): + from pyscf import fci + c, h1, h2 = self.get_integrals(ordering="chem") + norb = self.n_orbitals + nelec = self.n_electrons + e, fcivec = fci.direct_spin1.kernel(h1, h2.elems, norb, nelec, **kwargs) + return e + c
+ + +
+[docs] + def compute_energy(self, method: str, *args, **kwargs) -> float: + method = method.lower() + + if method == "hf": + return self._get_hf(do_not_solve=False, **kwargs).e_tot + elif method == "mp2": + return self._run_mp2(**kwargs).e_tot + elif method == "cisd": + hf = self._get_hf(do_not_solve=False, **kwargs) + return self._run_cisd(hf=hf, **kwargs).e_tot + elif method == "ccsd": + return self._run_ccsd(**kwargs).e_tot + elif method == "ccsd(t)": + ccsd = self._run_ccsd(**kwargs) + return ccsd.e_tot + self._compute_perturbative_triples_correction(ccsd=ccsd, **kwargs) + elif method == "fci": + return self.compute_fci(**kwargs) + else: + raise TequilaException("unknown method: {}".format(method))
+ + + def _get_hf(self, do_not_solve=True, **kwargs): + c, h1, h2 = self.get_integrals(ordering="mulliken") + norb = self.n_orbitals + nelec = self.n_electrons + + mo_coeff = numpy.eye(norb) + mo_occ = numpy.zeros(norb) + mo_occ[:nelec // 2] = 2 + + pyscf_mol = pyscf.gto.M(verbose=0, parse_arg=False) + pyscf_mol.nelectron = nelec + pyscf_mol.incore_anyway = True # ensure that custom integrals are used + pyscf_mol.energy_nuc = lambda *args: c + + hf = pyscf.scf.RHF(pyscf_mol) + hf.get_hcore = lambda *args: h1 + hf.get_ovlp = lambda *args: numpy.eye(norb) + hf._eri = pyscf.ao2mo.restore(8, h2.elems, norb) + + if do_not_solve: + hf.mo_coeff = mo_coeff + hf.mo_occ = mo_occ + else: + hf.kernel(numpy.diag(mo_occ)) + + return hf + + def _run_ccsd(self, hf=None, **kwargs): + from pyscf import cc + if hf is None: + hf = self._get_hf() + ccsd = cc.RCCSD(hf) + ccsd.kernel() + return ccsd + + def _compute_perturbative_triples_correction(self, ccsd=None, **kwargs) -> float: + if ccsd is None: + ccsd = self._run_ccsd(**kwargs) + ecorr = ccsd.ccsd_t() + return ecorr + + def _run_cisd(self, hf=None, **kwargs): + from pyscf import ci + if hf is None: + hf = self._get_hf(**kwargs) + cisd = ci.RCISD(hf) + cisd.kernel() + return cisd + + def _run_mp2(self, hf=None, **kwargs): + from pyscf import mp + if hf is None: + hf = self._get_hf(**kwargs) + mp2 = mp.MP2(hf) + mp2.kernel() + return mp2 + + def __str__(self): + base = super().__str__() + try: + if hasattr(self, "pyscf_molecule"): + base += "{:15} : {} ({})\n".format("point_group", self.pyscf_molecule.groupname, + self.pyscf_molecule.topgroup) + if hasattr(self, "irreps"): + base += "{:15} : {}\n".format("irreps", self.irreps) + except: + return base + return base
+ + + +if __name__ == "__main__": + pass +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/quantumchemistry/qc_base.html b/docs/sphinx/_modules/tequila_code/quantumchemistry/qc_base.html new file mode 100644 index 0000000..9a313a6 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/quantumchemistry/qc_base.html @@ -0,0 +1,2662 @@ + + + + + + + + tequila_code.quantumchemistry.qc_base — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +

Source code for tequila_code.quantumchemistry.qc_base

+import copy
+from dataclasses import dataclass
+from tequila import TequilaException, BitString, TequilaWarning
+from tequila.hamiltonian import QubitHamiltonian
+
+from tequila.hamiltonian.paulis import Sp, Sm, Zero
+
+from tequila.circuit import QCircuit, gates
+from tequila.objective.objective import Variable, Variables, ExpectationValue
+
+from tequila.simulators.simulator_api import simulate
+from tequila.utils import to_float
+from .chemistry_tools import ActiveSpaceData, FermionicGateImpl, prepare_product_state, ClosedShellAmplitudes, \
+    Amplitudes, ParametersQC, NBodyTensor, IntegralManager
+
+from .encodings import known_encodings
+
+import typing, numpy, numbers
+from itertools import product
+import tequila.grouping.fermionic_functions as ff
+
+
+try:
+    # if you are experiencing import errors you need to update openfermion
+    # required is version >= 1.0
+    # otherwise replace with from openfermion.hamiltonians import MolecularData
+    import openfermion
+    from openfermion.chem import MolecularData
+except:
+    try:
+        from openfermion.hamiltonians import MolecularData
+    except Exception as E:
+        raise Exception("{}\nIssue with Tequila Chemistry: Please update openfermion".format(str(E)))
+import warnings
+OPTIMIZED_ORDERING = "Optimized"
+
+[docs] +class QuantumChemistryBase: + """ + Base Class for tequila chemistry functionality + This is what is initialized with tq.Molecule(...) + We try to define all main methods here and only implemented specializations in the derived classes + Derived classes interface specific backends (e.g. Psi4, PySCF and Madness). See PACKAGE_interface.py for more + """ + + def __init__(self, parameters: ParametersQC, + transformation: typing.Union[str, typing.Callable] = None, + active_orbitals: list = None, + frozen_orbitals: list = None, + orbital_type: str = None, + reference_orbitals: list = None, + orbitals: list = None, + *args, + **kwargs): + """ + Parameters + ---------- + parameters: the quantum chemistry parameters handed over as instance of the ParametersQC class (see there for content) + transformation: the fermion to qubit transformation (default is JordanWigner). See encodings.py for supported encodings or to extend + active_orbitals: list of active orbitals (others will be frozen, if we have N-electrons then the first N//2 orbitals will be considered occpied when creating the active space) + frozen_orbitals: convenience (will be removed from list of active orbitals) + reference_orbitals: give list of orbitals that shall be considered occupied when creating a possible active space (default is the first N//2). The indices are expected to be total indices (including possible frozen orbitals in the counting) + orbitals: information about the orbitals (should be in OrbitalData format, can be a dictionary) + args + kwargs + """ + + self.parameters = parameters + n_electrons = parameters.n_electrons + if "n_electrons" in kwargs: + n_electrons = kwargs["n_electrons"] + + if reference_orbitals is None: + reference_orbitals = [i for i in range(n_electrons // 2)] + self._reference_orbitals = reference_orbitals + + if orbital_type is None: + orbital_type = "unknown" + + # no frozen core with native orbitals (i.e. atomics) + overriding_freeze_instruction = orbital_type is not None and orbital_type.lower() == "native" + # determine frozen core automatically if set + # only if molecule is computed from scratch and not passed down from above + overriding_freeze_instruction = overriding_freeze_instruction or n_electrons != parameters.n_electrons + overriding_freeze_instruction = overriding_freeze_instruction or frozen_orbitals is not None + if not overriding_freeze_instruction and self.parameters.frozen_core: + n_core_electrons = self.parameters.get_number_of_core_electrons() + if frozen_orbitals is None: + frozen_orbitals = [i for i in range(n_core_electrons//2)] + + + # initialize integral manager + if "integral_manager" in kwargs: + self.integral_manager = kwargs["integral_manager"] + else: + self.integral_manager = self.initialize_integral_manager(active_orbitals=active_orbitals, + reference_orbitals=reference_orbitals, + orbitals=orbitals, frozen_orbitals=frozen_orbitals, orbital_type=orbital_type, basis_name=self.parameters.basis_set, *args, + **kwargs) + + if orbital_type is not None and orbital_type.lower() == "native": + self.integral_manager.transform_to_native_orbitals() + + + self.transformation = self._initialize_transformation(transformation=transformation, *args, **kwargs) + + self._rdm1 = None + self._rdm2 = None + + +
+[docs] + @classmethod + def from_tequila(cls, molecule, transformation=None, *args, **kwargs): + c = molecule.integral_manager.constant_term + h1 = molecule.integral_manager.one_body_integrals + h2 = molecule.integral_manager.two_body_integrals + S = molecule.integral_manager.overlap_integrals + if "active_orbitals" not in kwargs: + active_orbitals = [o.idx_total for o in molecule.integral_manager.active_orbitals] + else: + active_orbitals = kwargs["active_orbitals"] + kwargs.pop("active_orbitals") + if transformation is None: + transformation = molecule.transformation + parameters = molecule.parameters + return cls(nuclear_repulsion=c, + one_body_integrals=h1, + two_body_integrals=h2, + overlap_integrals = S, + orbital_coefficients = molecule.integral_manager.orbital_coefficients, + active_orbitals= active_orbitals, + transformation=transformation, + orbital_type=molecule.integral_manager._orbital_type, + parameters=parameters, + reference_orbitals= molecule.integral_manager.active_space.reference_orbitals,*args, **kwargs)
+ + +
+[docs] + def supports_ucc(self): + """ + check if the current molecule supports UCC operations + (e.g. mol.make_excitation_gate) + """ + return self.transformation.supports_ucc
+ + + def _initialize_transformation(self, transformation=None, *args, **kwargs): + """ + Helper Function to initialize the Fermion-to-Qubit Transformation + Parameters + ---------- + transformation: name of the transformation (passed down from __init__ + args + kwargs + + Returns + ------- + + """ + + if transformation is None: + transformation = "JordanWigner" + + # filter out arguments to the transformation + trafo_args = {k.split("__")[1]: v for k, v in kwargs.items() if + (hasattr(k, "lower") and "transformation__" in k.lower())} + + trafo_args["n_electrons"] = self.n_electrons + trafo_args["n_orbitals"] = self.n_orbitals + + if hasattr(transformation, "upper"): + # format to conventions + transformation = transformation.replace("_", "").replace("-", "").upper() + encodings = known_encodings() + if transformation in encodings: + transformation = encodings[transformation](**trafo_args) + else: + raise TequilaException( + "Unkown Fermion-to-Qubit encoding {}. Try something like: {}".format(transformation, + list(encodings.keys()))) + + return transformation + +
+[docs] + @classmethod + def from_openfermion(cls, molecule: openfermion.MolecularData, + transformation: typing.Union[str, typing.Callable] = None, + *args, + **kwargs): + """ + Initialize direclty from openfermion MolecularData object + + Parameters + ---------- + molecule + The openfermion molecule + Returns + ------- + The Tequila molecule + """ + parameters = ParametersQC(basis_set=molecule.basis, geometry=molecule.geometry, + description=molecule.description, multiplicity=molecule.multiplicity, + charge=molecule.charge) + return cls(parameters=parameters, transformation=transformation, molecule=molecule, *args, **kwargs)
+ + +
+[docs] + def make_excitation_generator(self, + indices: typing.Iterable[typing.Tuple[int, int]], + form: str = None, + remove_constant_term: bool = True) -> QubitHamiltonian: + """ + Notes + ---------- + Creates the transformed hermitian generator of UCC type unitaries: + M(a^\dagger_{a_0} a_{i_0} a^\dagger{a_1}a_{i_1} ... - h.c.) + where the qubit map M depends is self.transformation + + Parameters + ---------- + indices : typing.Iterable[typing.Tuple[int, int]] : + List of tuples [(a_0, i_0), (a_1, i_1), ... ] - recommended format, in spin-orbital notation (alpha odd numbers, beta even numbers) + can also be given as one big list: [a_0, i_0, a_1, i_1 ...] + form : str : (Default value None): + Manipulate the generator to involution or projector + set form='involution' or 'projector' + the default is no manipulation which gives the standard fermionic excitation operator back + remove_constant_term: bool: (Default value True): + by default the constant term in the qubit operator is removed since it has no effect on the unitary it generates + if the unitary is controlled this might not be true! + Returns + ------- + type + 1j*Transformed qubit excitation operator, depends on self.transformation + """ + + if not self.supports_ucc(): + raise TequilaException("Molecule with transformation {} does not support general UCC operations".format(self.transformation)) + + # check indices and convert to list of tuples if necessary + if len(indices) == 0: + raise TequilaException("make_excitation_operator: no indices given") + elif not isinstance(indices[0], typing.Iterable): + if len(indices) % 2 != 0: + raise TequilaException("make_excitation_generator: unexpected input format of indices\n" + "use list of tuples as [(a_0, i_0),(a_1, i_1) ...]\n" + "or list as [a_0, i_0, a_1, i_1, ... ]\n" + "you gave: {}".format(indices)) + converted = [(indices[2 * i], indices[2 * i + 1]) for i in range(len(indices) // 2)] + else: + converted = indices + + # convert everything to native python int + # otherwise openfermion will complain + converted = [(int(pair[0]), int(pair[1])) for pair in converted] + + # convert to openfermion input format + ofi = [] + dag = [] + for pair in converted: + assert (len(pair) == 2) + ofi += [(int(pair[0]), 1), + (int(pair[1]), 0)] # openfermion does not take other types of integers like numpy.int64 + dag += [(int(pair[0]), 0), (int(pair[1]), 1)] + + op = openfermion.FermionOperator(tuple(ofi), 1.j) # 1j makes it hermitian + op += openfermion.FermionOperator(tuple(reversed(dag)), -1.j) + + if isinstance(form, str) and form.lower() != 'fermionic': + # indices for all the Na operators + Na = [x for pair in converted for x in [(pair[0], 1), (pair[0], 0)]] + # indices for all the Ma operators (Ma = 1 - Na) + Ma = [x for pair in converted for x in [(pair[0], 0), (pair[0], 1)]] + # indices for all the Ni operators + Ni = [x for pair in converted for x in [(pair[1], 1), (pair[1], 0)]] + # indices for all the Mi operators + Mi = [x for pair in converted for x in [(pair[1], 0), (pair[1], 1)]] + + # can gaussianize as projector or as involution (last is default) + if form.lower() == "p+": + op *= 0.5 + op += openfermion.FermionOperator(Na + Mi, 0.5) + op += openfermion.FermionOperator(Ni + Ma, 0.5) + elif form.lower() == "p-": + op *= 0.5 + op += openfermion.FermionOperator(Na + Mi, -0.5) + op += openfermion.FermionOperator(Ni + Ma, -0.5) + + elif form.lower() == "g+": + op += openfermion.FermionOperator([], 1.0) # Just for clarity will be subtracted anyway + op += openfermion.FermionOperator(Na + Mi, -1.0) + op += openfermion.FermionOperator(Ni + Ma, -1.0) + elif form.lower() == "g-": + op += openfermion.FermionOperator([], -1.0) # Just for clarity will be subtracted anyway + op += openfermion.FermionOperator(Na + Mi, 1.0) + op += openfermion.FermionOperator(Ni + Ma, 1.0) + elif form.lower() == "p0": + # P0: we only construct P0 and don't keep the original generator + op = openfermion.FermionOperator([], 1.0) # Just for clarity will be subtracted anyway + op += openfermion.FermionOperator(Na + Mi, -1.0) + op += openfermion.FermionOperator(Ni + Ma, -1.0) + else: + raise TequilaException( + "Unknown generator form {}, supported are G, P+, P-, G+, G- and P0".format(form)) + + qop = self.transformation(op) + + # remove constant terms + # they have no effect in the unitary (if not controlled) + if remove_constant_term: + qop.qubit_operator.terms[tuple()] = 0.0 + + # check if the operator is hermitian and cast coefficients to floats + # in order to avoid trouble with the simulation backends + assert qop.is_hermitian() + for k, v in qop.qubit_operator.terms.items(): + qop.qubit_operator.terms[k] = to_float(v) + + qop = qop.simplify() + + if len(qop) == 0: + warnings.warn("Excitation generator is a unit operator.\n" + "Non-standard transformations might not work with general fermionic operators\n" + "indices = " + str(indices), category=TequilaWarning) + return qop
+ + +
+[docs] + def make_hardcore_boson_excitation_gate(self, indices, angle, control=None, assume_real=True, + compile_options="optimize"): + """ + Make excitation generator in the hardcore-boson approximation (all electrons are forced to spin-pairs) + use only in combination with make_hardcore_boson_hamiltonian() + + Parameters + ---------- + indices + angle + control + assume_real + compile_options + + Returns + ------- + + """ + target = [] + for pair in indices: + assert len(pair) == 2 + target += [self.transformation.up(pair[0]), self.transformation.up(pair[1])] + if self.transformation.up_then_down: + consistency = [x < self.n_orbitals for x in target] + else: + consistency = [x % 2 == 0 for x in target] + if not all(consistency): + raise TequilaException( + "make_hardcore_boson_excitation_gate: Inconsistencies in indices={} for encoding: {}".format( + indices, self.transformation)) + return gates.QubitExcitation(angle=angle, target=target, assume_real=assume_real, control=control, + compile_options=compile_options)
+ + +
+[docs] + def UR(self,i,j,angle=None, label=None, control=None, assume_real=True, *args, **kwargs): + """ + Convenience function for orbital rotation circuit (rotating spatial orbital i and j) with standard naming of variables + See arXiv:2207.12421 Eq.6 for UR(0,1) + Parameters: + ---------- + indices: + tuple of two spatial(!) orbital indices + angle: + Numeric or hashable type or tequila objective. Default is None and results + in automatic naming as ("R",i,j) + label: + can be passed instead of angle to have auto-naming with label ("R",i,j,label) + useful for repreating gates with individual variables + control: + List of possible control qubits + assume_real: + Assume that the wavefunction will always stay real. + Will reduce potential gradient costs by a factor of 2 + """ + i,j = self.format_excitation_indices([(i,j)])[0] + if angle is None: + if label is None: + angle = Variable(name=("R",i,j))*numpy.pi + else: + angle = Variable(name=("R",i,j,label))*numpy.pi + + circuit = self.make_excitation_gate(indices=[(2*i,2*j)], angle=angle, assume_real=assume_real, control=control, *args, **kwargs) + circuit+= self.make_excitation_gate(indices=[(2*i+1,2*j+1)], angle=angle, assume_real=assume_real, control=control, *args, **kwargs) + return circuit
+ + +
+[docs] + def UC(self,i,j,angle=None, label=None, control=None, assume_real=True, *args, **kwargs): + """ + Convenience function for orbital correlator circuit (correlating spatial orbital i and j through a spin-paired double excitation) with standard naming of variables + See arXiv:2207.12421 Eq.22 for UC(1,2) + + Parameters: + ---------- + indices: + tuple of two spatial(!) orbital indices + angle: + Numeric or hashable type or tequila objective. Default is None and results + in automatic naming as ("R",i,j) + label: + can be passed instead of angle to have auto-naming with label ("R",i,j,label) + useful for repreating gates with individual variables + control: + List of possible control qubits + assume_real: + Assume that the wavefunction will always stay real. + Will reduce potential gradient costs by a factor of 2 + """ + i,j = self.format_excitation_indices([(i,j)])[0] + if angle is None: + if label is None: + angle = Variable(name=("C",i,j))*numpy.pi + else: + angle = Variable(name=("C",i,j,label))*numpy.pi + if "jordanwigner" in self.transformation.name.lower() and not self.transformation.up_then_down: + # for JW we can use the optimized form shown in arXiv:2207.12421 Eq.22 + return gates.QubitExcitation(target=[2*i,2*j,2*i+1,2*j+1], angle=angle, control=control, assume_real=assume_real, *args, **kwargs) + else: + return self.make_excitation_gate(indices=[(2*i,2*j),(2*i+1,2*j+1)], angle=angle, control=control, assume_real=assume_real, *args, **kwargs)
+ + +
+[docs] + def make_orbital_rotation_gate(self, indices:tuple, *args, **kwargs): + # backward compatibility + return self.UR(indices[0],indices[1], *args, **kwargs)
+ + + +
+[docs] + def make_excitation_gate(self, indices, angle, control=None, assume_real=True, **kwargs): + """ + Initialize a fermionic excitation gate defined as + + .. math:: + e^{-i\\frac{a}{2} G} + with generator defines by the indices [(p0,q0),(p1,q1),...] + .. math:: + G = i(\\prod_{k} a_{p_k}^\\dagger a_{q_k} - h.c.) + + Parameters + ---------- + indices: + List of tuples that define the generator + angle: + Numeric or hashable type or tequila objective + control: + List of possible control qubits + assume_real: + Assume that the wavefunction will always stay real. + Will reduce potential gradient costs by a factor of 2 + """ + + if not self.supports_ucc(): + raise TequilaException("Molecule with transformation {} does not support general UCC operations".format(self.transformation)) + + generator = self.make_excitation_generator(indices=indices, remove_constant_term=control is None) + p0 = self.make_excitation_generator(indices=indices, form="P0", remove_constant_term=control is None) + if self.transformation.up_then_down: + idx = [] + for pair in indices: + idx.append((pair[0]//2+(pair[0]%2)*self.n_orbitals,pair[1]//2+(pair[1]%2)*self.n_orbitals)) + else:idx = indices + return QCircuit.wrap_gate( + FermionicGateImpl(angle=angle, generator=generator, p0=p0, + transformation=type(self.transformation).__name__.lower(), indices=idx, + assume_real=assume_real, + control=control, **kwargs))
+ + +
+[docs] + def make_molecule(self, *args, **kwargs) -> MolecularData: + """Creates a molecule in openfermion format by running psi4 and extracting the data + Will check for previous outputfiles before running + Will not recompute if a file was found + + Parameters + ---------- + parameters : + An instance of ParametersQC, which also holds an instance of ParametersPsi4 via parameters.psi4 + The molecule will be saved in parameters.filename, if this file exists before the call the molecule will be imported from the file + + Returns + ------- + type + the molecule in openfermion.MolecularData format + + """ + molecule = MolecularData(**self.parameters.molecular_data_param) + + do_compute = True + # try: + # import os + # if os.path.exists(self.parameters.filename): + # molecule.load() + # do_compute = False + # except OSError: + # do_compute = True + + if do_compute: + molecule = self.do_make_molecule(*args, **kwargs) + + #molecule.save() + return molecule
+ + +
+[docs] + def initialize_integral_manager(self, *args, **kwargs): + """ + Called by self.__init__() with args and kwargs passed through + Override this in derived class such that it returns an intitialized instance of the integral manager + + In the BaseClass it is required to pass the following with kwargs on init: + - one_body_integrals as matrix + - two_body_integrals as NBTensor of numpy.ndarray (four indices, openfermion ordering) + - nuclear_repulsion (constant part of hamiltonian - optional) + + Method sets: + - result of self.get_integrals() + """ + + n_electrons = self.parameters.n_electrons + if "n_electrons" in kwargs: + n_electrons = kwargs["n_electrons"] + + assert ("one_body_integrals" in kwargs) + assert ("two_body_integrals" in kwargs) + one_body_integrals = kwargs["one_body_integrals"] + kwargs.pop("one_body_integrals") + two_body_integrals = kwargs["two_body_integrals"] + kwargs.pop("two_body_integrals") + + if not isinstance(two_body_integrals, NBodyTensor): + # assuming two_body_integrals are given in openfermion ordering + ordering = None # will be auto-detected + if "ordering" in kwargs: + ordering = kwargs["ordering"] + kwargs.pop("ordering") # let's not confuse the IntegralManager + two_body_integrals = NBodyTensor(two_body_integrals, ordering=ordering) + + two_body_integrals = two_body_integrals.reorder(to="chem") + + constant_part = 0.0 + if "constant_term" in kwargs: + constant_part += kwargs["constant_term"] + kwargs.pop("constant_term") + if "nuclear_repulsion" in kwargs: + constant_part += kwargs["nuclear_repulsion"] + kwargs.pop("nuclear_repulsion") + + if "active_space" not in kwargs: + + active_orbitals = [i for i in range(one_body_integrals.shape[0])] + if "active_orbitals" in kwargs and kwargs["active_orbitals"] is not None: + active_orbitals = kwargs["active_orbitals"] + if "frozen_orbitals" in kwargs and kwargs["frozen_orbitals"] is not None: + for fo in kwargs["frozen_orbitals"]: + if fo in active_orbitals: + active_orbitals.remove(fo) + + reference_orbitals = [i for i in range(n_electrons // 2)] + if "reference_orbitals" in kwargs and kwargs["reference_orbitals"] is not None: + reference_orbitals = kwargs["reference_orbitals"] + + active_space = ActiveSpaceData(active_orbitals=sorted(active_orbitals), + reference_orbitals=sorted(reference_orbitals)) + kwargs["active_space"] = active_space + + if "basis_name" not in kwargs: + kwargs["basis_name"] = self.parameters.basis_set + + manager = IntegralManager(one_body_integrals=one_body_integrals, two_body_integrals=two_body_integrals, + constant_term=constant_part, *args, **kwargs) + + return manager
+ + +
+[docs] + def transform_orbitals(self, orbital_coefficients, ignore_active_space=False, name=None, *args, **kwargs): + """ + Parameters + ---------- + orbital_coefficients: second index is new orbital indes, first is old orbital index (summed over), indices are assumed to be defined on the active space + ignore_active_space: if true orbital_coefficients are not assumed to be given in the active space + name: str, name the new orbitals + args + kwargs + + Returns + ------- + New molecule with transformed orbitals + """ + + U = numpy.eye(self.integral_manager.orbital_coefficients.shape[0]) + # mo_coeff by default only acts on the active space + active_indices = [o.idx_total for o in self.integral_manager.active_orbitals] + + if ignore_active_space: + U = orbital_coefficients + else: + for kk,k in enumerate(active_indices): + for ll,l in enumerate(active_indices): + U[k][l] = orbital_coefficients[kk][ll] + + # can not be an instance of a specific backend (otherwise we get inconsistencies with classical methods in the backend) + integral_manager = copy.deepcopy(self.integral_manager) + integral_manager.transform_orbitals(U=U, name=name) + result = QuantumChemistryBase(parameters=self.parameters, integral_manager=integral_manager, transformation=self.transformation) + return result
+ + +
+[docs] + def orthonormalize_basis_orbitals(self): + # backward compatibility + return self.use_native_orbitals()
+ + +
+[docs] + def use_native_orbitals(self, inplace=False): + """ + Returns + ------- + New molecule in the native (orthonormalized) basis given + e.g. for standard basis sets the orbitals are orthonormalized Gaussian Basis Functions + """ + if not self.integral_manager.active_space_is_trivial(): + warnings.warn("orthonormalize_basis_orbitals: active space is set and might lead to inconsistent behaviour", TequilaWarning) + + # can not be an instance of a specific backend (otherwise we get inconsistencies with classical methods in the backend) + if inplace: + self.integral_manager.transform_to_native_orbitals() + return self + else: + integral_manager = copy.deepcopy(self.integral_manager) + integral_manager.transform_to_native_orbitals() + result = QuantumChemistryBase(parameters=self.parameters, integral_manager=integral_manager, transformation=self.transformation) + return result
+ + + +
+[docs] + def do_make_molecule(self, *args, **kwargs): + """ + Called by self.make_molecule with args and kwargs passed through + Override this in derived class if needed + """ + + assert hasattr(self, "integral_manager") and self.integral_manager is not None + constant_term, one_body_integrals, two_body_integrals = self.integral_manager.get_integrals(ordering="of") + two_body_integrals = two_body_integrals.reorder(to="of") + + if ("n_orbitals" in kwargs): + n_orbitals = kwargs["n_orbitals"] + else: + n_orbitals = one_body_integrals.shape[0] + for i in [0, 1, 2, 3]: + assert n_orbitals == two_body_integrals.shape[i] + + molecule = MolecularData(**self.parameters.molecular_data_param) + + molecule.one_body_integrals = one_body_integrals + molecule.two_body_integrals = two_body_integrals.elems + molecule.nuclear_repulsion = constant_term + molecule.n_orbitals = n_orbitals + if "n_electrons" in kwargs: + molecule.n_electrons = kwargs["n_electrons"] + molecule.save() + return molecule
+ + + @property + def orbitals(self): + return self.integral_manager.active_orbitals + + @property + def reference_orbitals(self): + return self.integral_manager.active_reference_orbitals + + @property + def n_orbitals(self) -> int: + """ + Returns + ------- + The number of active orbitals in this Molecule + """ + return len(self.integral_manager.active_orbitals) + + @property + def active_space(self): + return self.integral_manager.active_space + + @property + def n_electrons(self) -> int: + """ + Returns + ------- + The number of active electrons in this molecule + """ + return 2 * len(self.integral_manager.active_reference_orbitals) + +
+[docs] + def make_annihilation_op(self, orbital, coefficient=1.0): + """ + Compute annihilation operator on spin-orbital in qubit representation + Spin-orbital order is always (up,down,up,down,...) + """ + assert orbital<=self.n_orbitals*2 + aop = openfermion.ops.FermionOperator(f'{orbital}', coefficient) + return self.transformation(aop)
+ + +
+[docs] + def make_creation_op(self, orbital, coefficient=1.0): + """ + Compute creation operator on spin-orbital in qubit representation + Spin-orbital order is always (up,down,up,down,...) + """ + assert orbital<=self.n_orbitals*2 + cop = openfermion.ops.FermionOperator(f'{orbital}^', coefficient) + return self.transformation(cop)
+ + +
+[docs] + def make_number_op(self, orbital): + """ + Compute number operator on spin-orbital in qubit representation + Spin-orbital order is always (up,down,up,down,...) + """ + num_op = self.make_creation_op(orbital) * self.make_annihilation_op(orbital) + return num_op
+ + +
+[docs] + def make_sz_op(self): + """ + Compute the spin_z operator of the molecule in qubit representation + """ + sz = QubitHamiltonian() + for i in range(0, self.n_orbitals * 2, 2): + one = 0.5 * self.make_creation_op(i) * self.make_annihilation_op(i) + two = 0.5 * self.make_creation_op(i+1) * self.make_annihilation_op(i+1) + sz += (one - two) + return sz
+ + +
+[docs] + def make_sp_op(self): + """ + Compute the spin+ operator of the molecule in qubit representation + """ + sp = QubitHamiltonian() + for i in range(self.n_orbitals): + sp += self.make_creation_op(i*2) * self.make_annihilation_op(i*2 + 1) + return sp
+ + +
+[docs] + def make_sm_op(self): + """ + Compute the spin- operator of the molecule in qubit representation + """ + sm = QubitHamiltonian() + for i in range(self.n_orbitals): + sm += self.make_creation_op(i*2 + 1) * self.make_annihilation_op(i*2) + return sm
+ + +
+[docs] + def make_s2_op(self): + """ + Compute the spin^2 operator of the molecule in qubit representation + """ + s2_op = self.make_sm_op() * self.make_sp_op() + self.make_sz_op() * (self.make_sz_op() + 1) + return s2_op
+ + +
+[docs] + def make_hamiltonian(self, *args, **kwargs) -> QubitHamiltonian: + """ + Parameters + ---------- + occupied_indices: will be auto-assigned according to specified active space. Can be overridden by passing specific lists (same as in open fermion) + active_indices: will be auto-assigned according to specified active space. Can be overridden by passing specific lists (same as in open fermion) + + Returns + ------- + Qubit Hamiltonian in the Fermion-to-Qubit transformation defined in self.parameters + """ + + # warnings for backward comp + if "active_indices" in kwargs: + warnings.warn( + "active space can't be changed in molecule. Will ignore active_orbitals passed to make_hamiltonian") + + of_molecule = self.make_molecule() + fop = of_molecule.get_molecular_hamiltonian() + fop = openfermion.transforms.get_fermion_operator(fop) + try: + qop = self.transformation(fop) + except TypeError: + qop = self.transformation(openfermion.transforms.get_interaction_operator(fop)) + qop.is_hermitian() + return qop
+ + +
+[docs] + def make_hardcore_boson_hamiltonian(self, condensed=False): + """ + Returns + ------- + Hamiltonian in Hardcore-Boson approximation (electrons are forced into spin-pairs) + Indepdent of Fermion-to-Qubit mapping + condensed: always give Hamiltonian back from qubit 0 to N where N is the number of orbitals + if condensed=False then JordanWigner would give back the Hamiltonian defined on even qubits between 0 to 2N + """ + + # integrate with QubitEncoding at some point + n_orbitals = self.n_orbitals + c, obt, tbt = self.get_integrals() + h = numpy.zeros(shape=[n_orbitals] * 2) + g = numpy.zeros(shape=[n_orbitals] * 2) + for p in range(n_orbitals): + h[p, p] += 2 * obt[p, p] + for q in range(n_orbitals): + h[p, q] += + tbt.elems[p, p, q, q] + if p != q: + g[p, q] += 2 * tbt.elems[p, q, q, p] - tbt.elems[p, q, p, q] + + H = c + for p in range(n_orbitals): + for q in range(n_orbitals): + up = p + uq = q + H += h[p, q] * Sm(up) * Sp(uq) + g[p, q] * Sm(up) * Sp(up) * Sm(uq) * Sp(uq) + + if not self.transformation.up_then_down and not condensed: + alpha_map = {k.idx:self.transformation.up(k.idx) for k in self.orbitals} + H = H.map_qubits(alpha_map) + return H
+ + +
+[docs] + def make_molecular_hamiltonian(self, occupied_indices=None, active_indices=None): + """ + Returns + ------- + Create a MolecularHamiltonian as openfermion Class + (used internally here, not used in tequila) + """ + return self.make_molecule().get_molecular_hamiltonian(occupied_indices=occupied_indices, active_indices=active_indices)
+ + +
+[docs] + def get_integrals(self, *args, **kwargs): + """ + Returns + + options for kwargs: "ordering = ["openfermion", "chem", "phys"], ignore_active_space = [True, False]" + ------- + Tuple with: + constant part (nuclear_repulsion + possible integrated parts from active-spaces) + one_body_integrals + two_body_integrals + """ + + # backward compatibility + if "two_body_ordering" in kwargs: + kwargs["ordering"] = kwargs["two_body_ordering"] + + return self.integral_manager.get_integrals(*args, **kwargs)
+ + +
+[docs] + def compute_one_body_integrals(self): + """ convenience function """ + c, h1, h2 = self.get_integrals() + return h1
+ + +
+[docs] + def compute_two_body_integrals(self, ordering="openfermion"): + """ """ + c, h1, h2 = self.get_integrals(ordering=ordering) + return h2
+ + +
+[docs] + def compute_constant_part(self): + c, h1, h2 = self.get_integrals() + return c
+ + +
+[docs] + def compute_ccsd_amplitudes(self) -> ClosedShellAmplitudes: + """ """ + raise Exception("BaseClass Method")
+ + + def _reference_state(self): + """ + used internally + gives back reference state occupation vector (in second quantization or JW notation) + transformation to current encoding is done in def prepare_reference + """ + assert self.n_electrons % 2 == 0 + state = [0] * (self.n_orbitals * 2) + for i in self.reference_orbitals: + state[2 * i.idx] = 1 + state[2 * i.idx + 1] = 1 + return state + +
+[docs] + def prepare_reference(self, state=None, *args, **kwargs): + """ + Returns + ------- + A tequila circuit object which prepares the reference of this molecule in the chosen transformation + """ + if state is None: + state = self._reference_state() + + reference_state = BitString.from_array(self.transformation.map_state(state=state)) + U = prepare_product_state(reference_state) + # prevent trace out in direct wfn simulation + U.n_qubits = self.n_orbitals * 2 # adapt when tapered transformations work + return U
+ + +
+[docs] + def prepare_hardcore_boson_reference(self): + """ + Prepare reference state in the Hardcore-Boson approximation (eqch qubit represents two spin-paired electrons) + Returns + ------- + tq.QCircuit that prepares the HCB reference + """ + U = gates.X(target=[self.transformation.up(i.idx) for i in self.reference_orbitals]) + U.n_qubits = self.n_orbitals + return U
+ + +
+[docs] + def hcb_to_me(self, U=None, condensed=False): + """ + Transform a circuit in the hardcore-boson encoding (HCB) + to the encoding of this molecule + HCB is supposed to be encoded on the first n_orbitals qubits + Parameters + ---------- + U: HCB circuit (using the alpha qubits) + condensed: assume that incoming U is condensed (HCB on the first n_orbitals; and not, as for example in JW on the first n even orbitals) + Returns + ------- + + """ + if U is None: + U = QCircuit() + else: + ups = [self.transformation.up(i.idx) for i in self.orbitals] + consistency = [x in ups for x in U.qubits] + if not all(consistency): + warnings.warn( + "hcb_to_me: given circuit is not defined on all first {} qubits. Is this a HCB circuit?".format( + self.n_orbitals)) + + # map to alpha qubits + if condensed: + alpha_map = {k: self.transformation.up(k) for k in range(self.n_orbitals)} + alpha_U = U.map_qubits(qubit_map=alpha_map) + else: + alpha_U = U + + UX = self.transformation.hcb_to_me() + if UX is None: + raise TequilaException( + "transformation={} has no hcb_to_me function implemented".format(self.transformation)) + return alpha_U + UX
+ + +
+[docs] + def get_pair_specific_indices(self, + pair_info: str = None, + include_singles: bool = True, + general_excitations: bool = True) -> list: + """ + Assuming a pair-specific model, create a pair-specific index list + to be used in make_upccgsd_ansatz(indices = ... ) + Excite from a set of references (i) to any pair coming from (i), + i.e. any (i,j)/(j,i). If general excitations are allowed, also + allow excitations from pairs to appendant pairs and reference. + + Parameters + ---------- + pair_info + file or list including information about pair structure + references single number, pair double + example: as file: "0,1,11,11,00,10" (hand over file name) + in file, skip first row assuming some text with information + as list:['0','1`','11','11','00','10'] + ~> two reference orbitals 0 and 1, + then two orbitals from pair 11, one from 00, one mixed 10 + include_singles + include single excitations + general_excitations + allow general excitations + Returns + ------- + list of indices with pair-specific ansatz + """ + + if pair_info is None: + raise TequilaException("Need to provide some pair information.") + # If pair-information given on file, load (layout see above) + if isinstance(pair_info, str): + pairs = numpy.loadtxt(pair_info, dtype=str, delimiter=",", skiprows=1) + elif isinstance(pair_info, list): + pairs = pair_info + elif not isinstance(pair_info, list): + raise TequilaException("Pair information needs to be contained in a list or filename.") + + connect = [[]] * len(pairs) + # determine "connectivity" + generalized = 0 + for idx, p in enumerate(pairs): + if len(p) == 1: + connect[idx] = [i for i in range(len(pairs)) + if ((len(pairs[i]) == 2) and (str(idx) in pairs[i]))] + elif (len(p) == 2) and general_excitations: + connect[idx] = [i for i in range(len(pairs)) + if (((p[0] in pairs[i]) or (p[1] in pairs[i]) or str(i) in p) + and not (i == idx))] + elif len(p) > 2: + raise TequilaException("Invalid reference of pair id.") + + # create generating indices from connectivity + indices = [] + for i, to in enumerate(connect): + for a in to: + indices.append(((2 * i, 2 * a), (2 * i + 1, 2 * a + 1))) + if include_singles: + indices.append(((2 * i, 2 * a))) + indices.append(((2 * i + 1, 2 * a + 1))) + + return indices
+ + +
+[docs] + def format_excitation_indices(self, idx): + """ + Consistent formatting of excitation indices + idx = [(p0,q0),(p1,q1),...,(pn,qn)] + sorted as: p0<p1<pn and pi<qi + :param idx: list of index tuples describing a single(!) fermionic excitation + :return: tuple-list of index tuples + """ + + idx = [tuple(sorted(x)) for x in idx] + idx = sorted(idx, key=lambda x: x[0]) + return tuple(idx)
+ + +
+[docs] + def make_upccgsd_indices(self, key, reference_orbitals=None, *args, **kwargs): + + if reference_orbitals is None: + reference_orbitals = [x.idx for x in self.reference_orbitals] + indices = [] + # add doubles in hcb encoding + if hasattr(key, "lower") and key.lower() == "ladder": + # ladder structure of the pair excitations + # ensures local connectivity + indices = [[(n, n + 1)] for n in range(self.n_orbitals - 1)] + elif hasattr(key, "lower") and "g" not in key.lower(): + indices = [[(n, m)] for n in reference_orbitals for m in range(self.n_orbitals) if + n < m and m not in reference_orbitals] + elif hasattr(key, "lower") and "g" in key.lower(): + indices = [[(n, m)] for n in range(self.n_orbitals) for m in range(self.n_orbitals) if n < m] + else: + raise TequilaException("Unknown recipe: {}".format(key)) + indices = [self.format_excitation_indices(idx) for idx in indices] + + return indices
+ + +
+[docs] + def make_hardcore_boson_upccgd_layer(self, + indices: list = "UpCCGD", + label: str = None, + assume_real: bool = True, + *args, **kwargs): + + if hasattr(indices, "lower"): + indices = self.make_upccgsd_indices(key=indices.lower()) + + UD = QCircuit() + for idx in indices: + UD += self.make_hardcore_boson_excitation_gate(indices=idx, angle=(idx, "D", label), + assume_real=assume_real) + + return UD
+ + +
+[docs] + def make_spa_ansatz(self, edges, hcb=False, use_units_of_pi=False, label=None, optimize=None, ladder=True): + """ + Separable Pair Ansatz (SPA) for general molecules + see arxiv: + edges: a list of tuples that contain the orbital indices for the specific pairs + one example: edges=[(0,), (1,2,3), (4,5)] are three pairs, one with a single orbital [0], one with three orbitals [1,2,3] and one with two orbitals [4,5] + hcb: spa ansatz in the hcb (hardcore-boson) space without transforming to current transformation (e.g. JordanWigner), use this for example in combination with the self.make_hardcore_boson_hamiltonian() and see the article above for more info + use_units_of_pi: circuit angles in units of pi + label: label the variables in the circuit + optimize: optimize the circuit construction (see article). Results in shallow circuit from Ry and CNOT gates + ladder: if true the excitation pattern will be local. E.g. in the pair from orbitals (1,2,3) we will have the excitations 1->2 and 2->3, if set to false we will have standard coupled-cluster style excitations - in this case this would be 1->2 and 1->3 + """ + if edges is None: + raise TequilaException("SPA ansatz within a standard orbital basis needs edges. Please provide with the keyword edges.\nExample: edges=[(0,1,2),(3,4)] would correspond to two edges created from orbitals (0,1,2) and (3,4), note that orbitals can only be assigned to a single edge") + + # sanity checks + # current SPA implementation needs even number of electrons + if self.n_electrons % 2 != 0: + raise TequilaException("need even number of electrons for SPA ansatz.\n{} active electrons".format(self.n_electrons)) + # making sure that enough edges are assigned + n_edges = len(edges) + if len(edges) != self.n_electrons//2: + raise TequilaException("number of edges need to be equal to number of active electrons//2\n{} edges given\n{} active electrons\nfrozen core is {}".format(len(edges), self.n_electrons, self.parameters.frozen_core)) + # making sure that orbitals are uniquely assigned to edges + for edge_qubits in edges: + for q1 in edge_qubits: + for edge2 in edges: + if edge2==edge_qubits: + continue + elif q1 in edge2: + raise TequilaException("make_spa_ansatz: faulty list of edges, orbitals are overlapping e.g. orbital {} is in edge {} and edge {}".format(q1, edge_qubits, edge2)) + + # auto assign if the circuit construction is optimized + # depending on the current qubit encoding (if hcb_to_me is implemnented we can optimize) + if optimize is None: + try: + have_hcb_to_me = self.hcb_to_me() is not None + except: + have_hcb_to_me = False + if have_hcb_to_me: + optimize=True + else: + optimize=False + + U = QCircuit() + + # construction of the optimized circuit + if optimize: + # circuit in HCB representation + # depends a bit on the ordering of the spin-orbitals in the encoding + # here we transform it to the qubits representing the up-spins + # the hcb_to_me sequence will then transfer to the actual encoding later + for edge_orbitals in edges: + edge_qubits = [self.transformation.up(i) for i in edge_orbitals] + U += gates.X(edge_qubits[0]) + if len(edge_qubits)==1: + continue + for i in range(1,len(edge_qubits)): + q1=edge_qubits[i] + c=edge_qubits[i-1] + if not ladder: + c=edge_qubits[0] + angle=Variable(name=((edge_orbitals[i-1], edge_orbitals[i]), "D" ,label)) + if use_units_of_pi: + angle=angle*numpy.pi + if i-1 == 0: + U += gates.Ry(angle=angle, target=q1, control=None) + else: + U += gates.Ry(angle=angle, target=q1, control=c) + U += gates.CNOT(q1,c) + + + if not hcb: + U += self.hcb_to_me() + else: + # construction of the non-optimized circuit (UpCCD with paired doubles according to edges) + if hcb: + U = self.prepare_hardcore_boson_reference() + else: + U = self.prepare_reference() + # will only work if the first orbitals in the edges are the reference orbitals + sane = True + reference_orbitals = self.reference_orbitals + for edge_qubits in edges: + if self.orbitals[edge_qubits[0]] not in reference_orbitals: + sane=False + if len(edge_qubits)>1: + for q1 in edge_qubits[1:]: + if self.orbitals[q1] in reference_orbitals: + sane=False + if not sane: + raise TequilaException("Non-Optimized SPA (e.g. with encodings that are not JW) will only work if the first orbitals of all SPA edges are occupied reference orbitals and all others are not. You gave edges={} and reference_orbitals are {}".format(edges, reference_orbitals)) + + for edge_qubits in edges: + previous = edge_qubits[0] + if len(edge_qubits)>1: + for q1 in edge_qubits[1:]: + c = previous + if not ladder: + c = edge_qubits[0] + angle = Variable(name=((c,q1), "D" ,label)) + if use_units_of_pi: + angle=angle*numpy.pi + if hcb: + U += self.make_hardcore_boson_excitation_gate(indices=[(q1,c)],angle=angle) + else: + U += self.make_excitation_gate(indices=[(2*c,2*q1),(2*c+1,2*q1+1)], angle=angle) + previous = q1 + return U
+ + +
+[docs] + def make_ansatz(self, name: str, *args, **kwargs): + """ + Automatically calls the right subroutines to construct ansatze implemented in tequila.chemistry + name: namne of the ansatz, examples are: UpCCGSD, UpCCD, SPA, UCCSD, SPA+UpCCD, SPA+GS + """ + name = name.lower() + if name.strip() == "": + return QCircuit() + + if "+" in name: + U = QCircuit() + subparts = name.split("+") + U = self.make_ansatz(name=subparts[0], *args, **kwargs) + # making sure the there are is no undesired behaviour in layers after + + # reference should not be included since we are not starting from |00...0> anymore + if "include_reference" in kwargs: + kwargs.pop("include_reference") + # hcb optimization can also not be used (in almost all cases) + if "hcb_optimization" in kwargs: + kwargs.pop("hcb_optimization") + # making sure that we have no repeating variable names + label = None + if "label" in kwargs: + label = kwargs["label"] + kwargs.pop("label") + for i,subpart in enumerate(subparts[1:]): + U += self.make_ansatz(name=subpart, *args, label=(label,i), include_reference=False, hcb_optimization=False, **kwargs) + return U + + if name == "uccsd": + return self.make_uccsd_ansatz(*args, **kwargs) + elif "spa" in name.lower(): + if "hcb" not in kwargs: + hcb = False + if "hcb" in name.lower(): + hcb = True + kwargs["hcb"]=hcb + return self.make_spa_ansatz(*args, **kwargs) + elif "d" in name or "s" in name: + return self.make_upccgsd_ansatz(name=name, *args, **kwargs) + else: + raise TequilaException("unknown ansatz with name={}".format(name))
+ + +
+[docs] + def make_upccgsd_ansatz(self, + include_reference: bool = True, + name: str = "UpCCGSD", + label: str = None, + order: int = None, + assume_real: bool = True, + hcb_optimization: bool = None, + spin_adapt_singles: bool = True, + neglect_z: bool = False, + mix_sd: bool = False, + *args, **kwargs): + """ + UpGCCSD Ansatz similar as described by Lee et. al. + + Parameters + ---------- + include_reference + include the HF reference state as initial state + indices + pass custom defined set of indices from which the ansatz will be created + List of tuples of tuples spin-indices e.g. [((2*p,2*q),(2*p+1,2*q+1)), ...] + label + An additional label that is set with the variables + default is None and no label will be set: variables names will be + (x, (p,q)) for x in range(order) + with a label the variables will be named + (label, (x, (p,q))) + order + Order of the ansatz (default is 1) + determines how often the ordering gets repeated + parameters of repeating layers are independent + assume_real + assume a real wavefunction (that is always the case if the reference state is real) + reduces potential gradient costs from 4 to 2 + mix_sd + Changes the ordering from first all doubles and then all singles excitations (DDDDD....SSSS....) to + a mixed order (DS-DS-DS-DS-...) where one DS pair acts on the same MOs. Useful to consider when systems + with high electronic correlation and system high error associated with the no Trotterized UCC. + Returns + ------- + UpGCCSD ansatz + """ + + name = name.upper() + + if ("A" in name) and neglect_z is None: + neglect_z = True + else: + neglect_z = False + + if order is None: + try: + if "-" in name: + order = int(name.split("-")[0]) + else: + order = 1 + except: + order = 1 + + indices = self.make_upccgsd_indices(key=name) + + # check if the used qubit encoding has a hcb transformation + have_hcb_trafo = True + try: + if self.transformation.hcb_to_me() is None: + have_hcb_trafo = False + except: + have_hcb_trafo = False + + + # consistency checks for optimization + if have_hcb_trafo and hcb_optimization is None and include_reference: + hcb_optimization = True + if "HCB" in name: + hcb_optimization = True + if hcb_optimization and not have_hcb_trafo and "HCB" not in name: + raise TequilaException( + "use_hcb={} but transformation={} has no \'hcb_to_me\' function. Try transformation=\'ReorderedJordanWigner\'".format( + hcb_optimization, self.transformation)) + if "S" in name and "HCB" in name: + if "HCB" in name and "S" in name: + raise Exception( + "name={}, Singles can't be realized without mapping back to the standard encoding leave S or HCB out of the name".format( + name)) + if hcb_optimization and mix_sd: + raise TequilaException("Mixed SD can not be employed together with HCB Optimization") + # convenience + S = "S" in name.upper() + D = "D" in name.upper() + + # first layer + if not hcb_optimization: + U = QCircuit() + if include_reference: + U = self.prepare_reference() + U += self.make_upccgsd_layer(include_singles=S, include_doubles=D, indices=indices, assume_real=assume_real, + label=(label, 0), mix_sd=mix_sd, spin_adapt_singles=spin_adapt_singles, *args, + **kwargs) + else: + U = QCircuit() + if include_reference: + U = self.prepare_hardcore_boson_reference() + if D: + U += self.make_hardcore_boson_upccgd_layer(indices=indices, assume_real=assume_real, label=(label, 0), + *args, **kwargs) + + if "HCB" not in name and (include_reference or D): + U = self.hcb_to_me(U=U) + + if S: + U += self.make_upccgsd_singles(indices=indices, assume_real=assume_real, label=(label, 0), + spin_adapt_singles=spin_adapt_singles, neglect_z=neglect_z, *args, + **kwargs) + + for k in range(1, order): + U += self.make_upccgsd_layer(include_singles=S, include_doubles=D, indices=indices, label=(label, k), + spin_adapt_singles=spin_adapt_singles, neglect_z=neglect_z, mix_sd=mix_sd) + + return U
+ + +
+[docs] + def make_upccgsd_layer(self, indices, include_singles: bool = True, include_doubles: bool = True, + assume_real: bool = True, label=None, + spin_adapt_singles: bool = True, angle_transform=None, mix_sd: bool = False, + neglect_z: bool = False, *args, + **kwargs): + U = QCircuit() + for idx in indices: + assert len(idx) == 1 + idx = idx[0] + angle = (tuple([idx]), "D", label) + if include_doubles: + if "jordanwigner" in self.transformation.name.lower() and not self.transformation.up_then_down: + # we can optimize with qubit excitations for the JW representation + target = [self.transformation.up(idx[0]), self.transformation.up(idx[1]), + self.transformation.down(idx[0]), self.transformation.down(idx[1])] + U += gates.QubitExcitation(angle=angle, target=target, assume_real=assume_real, **kwargs) + else: + U += self.make_excitation_gate(angle=angle, + indices=((2 * idx[0], 2 * idx[1]), (2 * idx[0] + 1, 2 * idx[1] + 1)), + assume_real=assume_real, **kwargs) + if include_singles and mix_sd: + U += self.make_upccgsd_singles(indices=[(idx,)], assume_real=assume_real, label=label, + spin_adapt_singles=spin_adapt_singles, angle_transform=angle_transform, + neglect_z=neglect_z) + + if include_singles and not mix_sd: + U += self.make_upccgsd_singles(indices=indices, assume_real=assume_real, label=label, + spin_adapt_singles=spin_adapt_singles, angle_transform=angle_transform, + neglect_z=neglect_z) + return U
+ + +
+[docs] + def make_upccgsd_singles(self, indices="UpCCGSD", spin_adapt_singles=True, label=None, angle_transform=None, + assume_real=True, neglect_z=False, *args, **kwargs): + if neglect_z and "jordanwigner" not in self.transformation.name.lower(): + raise TequilaException( + "neglegt-z approximation in UpCCGSD singles needs the (Reversed)JordanWigner representation") + if hasattr(indices, "lower"): + indices = self.make_upccgsd_indices(key=indices) + + U = QCircuit() + for idx in indices: + assert len(idx) == 1 + idx = idx[0] + if spin_adapt_singles: + angle = (idx, "S", label) + if angle_transform is not None: + angle = angle_transform(angle) + if neglect_z: + targeta = [self.transformation.up(idx[0]), self.transformation.up(idx[1])] + targetb = [self.transformation.down(idx[0]), self.transformation.down(idx[1])] + U += gates.QubitExcitation(angle=angle, target=targeta, assume_real=assume_real, **kwargs) + U += gates.QubitExcitation(angle=angle, target=targetb, assume_real=assume_real, **kwargs) + else: + U += self.make_excitation_gate(angle=angle, indices=[(2 * idx[0], 2 * idx[1])], + assume_real=assume_real, **kwargs) + U += self.make_excitation_gate(angle=angle, indices=[(2 * idx[0] + 1, 2 * idx[1] + 1)], + assume_real=assume_real, **kwargs) + else: + angle1 = (idx, "SU", label) + angle2 = (idx, "SD", label) + if angle_transform is not None: + angle1 = angle_transform(angle1) + angle2 = angle_transform(angle2) + if neglect_z: + targeta = [self.transformation.up(idx[0]), self.transformation.up(idx[1])] + targetb = [self.transformation.down(idx[0]), self.transformation.down(idx[1])] + U += gates.QubitExcitation(angle=angle1, target=targeta, assume_real=assume_real, *kwargs) + U += gates.QubitExcitation(angle=angle2, target=targetb, assume_real=assume_real, *kwargs) + else: + U += self.make_excitation_gate(angle=angle1, indices=[(2 * idx[0], 2 * idx[1])], + assume_real=assume_real, **kwargs) + U += self.make_excitation_gate(angle=angle2, indices=[(2 * idx[0] + 1, 2 * idx[1] + 1)], + assume_real=assume_real, **kwargs) + + return U
+ + +
+[docs] + def make_uccsd_ansatz(self, trotter_steps: int = 1, + initial_amplitudes: typing.Union[str, Amplitudes, ClosedShellAmplitudes] = None, + include_reference_ansatz=True, + parametrized=True, + threshold=1.e-8, + add_singles=None, + screening=True, + *args, **kwargs) -> QCircuit: + """ + + Parameters + ---------- + initial_amplitudes : + initial amplitudes given as ManyBodyAmplitudes structure or as string + where 'mp2', 'cc2' or 'ccsd' are possible initializations + include_reference_ansatz : + Also do the reference ansatz (prepare closed-shell Hartree-Fock) (Default value = True) + parametrized : + Initialize with variables, otherwise with static numbers (Default value = True) + trotter_steps: int : + + initial_amplitudes: typing.Union[str : + + Amplitudes : + + ClosedShellAmplitudes] : + (Default value = "cc2") + + Returns + ------- + type + Parametrized QCircuit + + """ + + if hasattr(initial_amplitudes, "lower"): + if initial_amplitudes.lower() == "mp2" and add_singles is None: + add_singles = True + elif initial_amplitudes is not None and add_singles is not None: + warnings.warn("make_uccsd_anstatz: add_singles has no effect when explicit amplitudes are passed down", + TequilaWarning) + elif add_singles is None: + add_singles = True + + if self.n_electrons % 2 != 0: + raise TequilaException("make_uccsd_ansatz currently only for closed shell systems") + + nocc = self.n_electrons // 2 + nvirt = self.n_orbitals - nocc + + Uref = QCircuit() + if include_reference_ansatz: + Uref = self.prepare_reference() + + amplitudes = initial_amplitudes + if hasattr(initial_amplitudes, "lower"): + if initial_amplitudes.lower() == "mp2": + amplitudes = self.compute_mp2_amplitudes() + elif initial_amplitudes.lower() == "ccsd": + amplitudes = self.compute_ccsd_amplitudes() + else: + try: + amplitudes = self.compute_amplitudes(method=initial_amplitudes.lower()) + except Exception as exc: + raise TequilaException( + "{}\nDon't know how to initialize \'{}\' amplitudes".format(exc, initial_amplitudes)) + if amplitudes is None: + tia = None + if add_singles: tia = numpy.zeros(shape=[nocc, nvirt]) + amplitudes = ClosedShellAmplitudes( + tIjAb=numpy.zeros(shape=[nocc, nocc, nvirt, nvirt]), + tIA=tia) + screening = False + + closed_shell = isinstance(amplitudes, ClosedShellAmplitudes) + indices = {} + + if not screening: + threshold = 0.0 + + if not isinstance(amplitudes, dict): + amplitudes = amplitudes.make_parameter_dictionary(threshold=threshold, screening=screening) + amplitudes = dict(sorted(amplitudes.items(), key=lambda x: numpy.fabs(x[1]), reverse=True)) + for key, t in amplitudes.items(): + assert (len(key) % 2 == 0) + if not numpy.isclose(t, 0.0, atol=threshold) or not screening: + if closed_shell: + + if len(key) == 2 and add_singles: + # singles + angle = 2.0 * t + if parametrized: + angle = 2.0 * Variable(name=key) + idx_a = (2 * key[0], 2 * key[1]) + idx_b = (2 * key[0] + 1, 2 * key[1] + 1) + indices[idx_a] = angle + indices[idx_b] = angle + else: + assert len(key) == 4 + angle = 2.0 * t + if parametrized: + angle = 2.0 * Variable(name=key) + idx_abab = (2 * key[0] + 1, 2 * key[1] + 1, 2 * key[2], 2 * key[3]) + indices[idx_abab] = angle + if key[0] != key[2] and key[1] != key[3]: + idx_aaaa = (2 * key[0], 2 * key[1], 2 * key[2], 2 * key[3]) + idx_bbbb = (2 * key[0] + 1, 2 * key[1] + 1, 2 * key[2] + 1, 2 * key[3] + 1) + partner = tuple([key[2], key[1], key[0], key[3]]) + anglex = 2.0 * (t - amplitudes[partner]) + if parametrized: + anglex = 2.0 * (Variable(name=key) - Variable(partner)) + indices[idx_aaaa] = anglex + indices[idx_bbbb] = anglex + else: + raise Exception("only closed-shell supported, please assemble yourself .... sorry :-)") + + UCCSD = QCircuit() + factor = 1.0 / trotter_steps + for step in range(trotter_steps): + for idx, angle in indices.items(): + converted = [(idx[2 * i], idx[2 * i + 1]) for i in range(len(idx) // 2)] + UCCSD += self.make_excitation_gate(indices=converted, angle=factor * angle) + if hasattr(initial_amplitudes, + "lower") and initial_amplitudes.lower() == "mp2" and parametrized and add_singles: + # mp2 has no singles, need to initialize them here (if not parametrized initializling as 0.0 makes no sense though) + UCCSD += self.make_upccgsd_layer(indices="upccsd", include_singles=True, include_doubles=False) + return Uref + UCCSD
+ + +
+[docs] + def compute_amplitudes(self, method: str, *args, **kwargs): + """ + Compute closed-shell CC amplitudes + + Parameters + ---------- + method : + coupled-cluster methods like cc2, ccsd, cc3, ccsd(t) + Success might depend on backend + got an extra function for MP2 + *args : + + **kwargs : + + + Returns + ------- + + """ + raise TequilaException("compute amplitudes: Needs to be overwritten by backend")
+ + +
+[docs] + def compute_energy(self, method, *args, **kwargs): + """ + Call classical methods over PySCF (needs to be installed) or + use as a shortcut to calculate quantum energies (see make_upccgsd_ansatz) + + Parameters + ---------- + method: method name + classical: HF, MP2, CCSD, CCSD(T), FCI -- with pyscf + quantum: UpCCD, UpCCSD, UpCCGSD, k-UpCCGSD, UCCSD, + see make_upccgsd_ansatz of the this class for more information + args + kwargs: for quantum methods, keyword arguments for minimizer + + Returns + ------- + + """ + if any([x in method.upper() for x in ["U"]]): + # simulate entirely in HCB representation if no singles are involved + if "S" not in method.upper().split("-")[-1] and "HCB" not in method.upper(): + method = "HCB-" + method + U = self.make_ansatz(name=method) + if "hcb" in method.lower(): + H = self.make_hardcore_boson_hamiltonian() + else: + H = self.make_hamiltonian() + E = ExpectationValue(H=H, U=U) + from tequila import minimize + return minimize(objective=E, *args, **kwargs).energy + else: + from tequila.quantumchemistry import INSTALLED_QCHEMISTRY_BACKENDS + if "pyscf" not in INSTALLED_QCHEMISTRY_BACKENDS: + raise TequilaException( + "PySCF needs to be installed to compute {}/{}".format(method, self.parameters.basis_set)) + else: + from tequila.quantumchemistry import QuantumChemistryPySCF + molx = QuantumChemistryPySCF.from_tequila(self) + return molx.compute_energy(method=method)
+ + +
+[docs] + def compute_fock_matrix(self): + c, h, g = self.get_integrals() + g = g.reorder(to="phys") + + # fock matrix is: + # Fkl = hkl + 2.0 <k|J|l> - <k|K|l> = hkl + 2.0* <ki|g|li> - <ki|g|il> + F = numpy.zeros(shape=h.shape) + for k in range(F.shape[0]): + for l in range(F.shape[1]): + tmp = h[k,l] + for ii in self.reference_orbitals: + i = ii.idx + tmp += (2.0*g.elems[k, i, l, i] - g.elems[k, i, i, l]) + F[k, l] = tmp + return F
+ + +
+[docs] + def compute_mp2_amplitudes(self, hf_energy=None, return_energy=False) -> ClosedShellAmplitudes: + """ + + Compute closed-shell mp2 amplitudes (canonical amplitudes only) + + .. math:: + t(a,i,b,j) = 0.25 * g(a,i,b,j)/(e(i) + e(j) -a(i) - b(j) ) + + :return: + + Parameters + ---------- + + Returns + ------- + + """ + c,h,g = self.get_integrals() + fi = self.compute_fock_matrix() + self.is_canonical(verify=True, fock_matrix=fi) + fi = numpy.diag(fi) + self.is_closed_shell(verify=True) + nocc = len(self.reference_orbitals) + ei = fi[:nocc] + ai = fi[nocc:] + abgij = g.elems[nocc:, nocc:, :nocc, :nocc] + amplitudes = abgij * 1.0 / ( + ei.reshape(1, 1, -1, 1) + ei.reshape(1, 1, 1, -1) - ai.reshape(-1, 1, 1, 1) - ai.reshape(1, -1, 1, 1)) + + result = ClosedShellAmplitudes(tIjAb=numpy.einsum('abij -> ijab', amplitudes, optimize='greedy')) + + if return_energy: + E = 2.0 * numpy.einsum('abij,abij->', amplitudes, abgij) - numpy.einsum('abji,abij', amplitudes, abgij,optimize='greedy') + return result, E + else: + return result
+ + +
+[docs] + def compute_cis_amplitudes(self): + """ + Compute the CIS amplitudes of the molecule + Warning: Not field tested! + """ + + @dataclass + class ResultCIS: + """ """ + omegas: typing.List[numbers.Real] # excitation energies [omega0, ...] + amplitudes: typing.List[ClosedShellAmplitudes] # corresponding amplitudes [x_{ai}_0, ...] + + def __getitem__(self, item): + return (self.omegas[item], self.amplitudes[item]) + + def __len__(self): + return len(self.omegas) + + self.is_closed_shell(verify=True) + c, h, g = self.get_integrals() + g.reorder(to="openfermion") + g = g.elems + fij = self.compute_fock_matrix() + self.is_canonical(verify=True, fock_matrix=fij) + fij = numpy.diag(fij) + + nocc = self.n_electrons // 2 + nvirt = self.n_orbitals - nocc + + pairs = [] + for i in range(nocc): + for a in range(nocc, nocc + nvirt): + pairs.append((a, i)) + M = numpy.ndarray(shape=[len(pairs), len(pairs)]) + + for xx, x in enumerate(pairs): + eia = fij[x[0]] - fij[x[1]] + a, i = x + for yy, y in enumerate(pairs): + b, j = y + delta = float(y == x) + gpart = 2.0 * g[a, i, b, j] - g[a, i, j, b] + M[xx, yy] = eia * delta + gpart + + omega, xvecs = numpy.linalg.eigh(M) + + # convert amplitudes to ndarray sorted by excitation energy + nex = len(omega) + amplitudes = [] + for ex in range(nex): + t = numpy.ndarray(shape=[nvirt, nocc]) + exvec = xvecs[ex] + for xx, x in enumerate(pairs): + a, i = x + t[a - nocc, i] = exvec[xx] + amplitudes.append(ClosedShellAmplitudes(tIA=t)) + + return ResultCIS(omegas=list(omega), amplitudes=amplitudes)
+ + +
+[docs] + def is_closed_shell(self, verify=False): + cs = self.n_electrons % 2 == 0 + if verify and not cs: + raise TequilaException("not a closed shell molecule: having {} electrons".format(self.n_electrons)) + return cs
+ + +
+[docs] + def is_canonical(self, verify=False, fock_matrix=None): + canonical = True + if fock_matrix is None: + fock_matrix = self.compute_fock_matrix() + + is_diagonal = numpy.isclose(numpy.linalg.norm(fock_matrix - numpy.diag(numpy.diag(fock_matrix))), 0.0, atol=1.e-4) + + if not is_diagonal: + canonical = False + + refo = self.reference_orbitals + + if refo[0].idx != 0: + canonical = False + for i in range(len(refo) - 1): + if refo[i].idx_total + 1 != refo[i + 1].idx_total: + canonical = False + + if verify and not canonical: + data={"reference_orbitals":refo, "fock_matrix":fock_matrix} + raise TequilaException( + "orbitals are not canonical or can not be verified as such -> implemented method only works for standard orbitals (preferably from psi4)\n{}".format(data)) + return canonical
+ + + @property + def rdm1(self): + """ + Returns RMD1 if computed with compute_rdms function before + """ + if self._rdm1 is not None: + return self._rdm1 + else: + print("1-RDM has not been computed. Return None for 1-RDM.") + return None + + @property + def rdm2(self): + """ + Returns RMD2 if computed with compute_rdms function before + This is returned in Dirac (physics) notation by default (can be changed in compute_rdms with keyword)! + """ + if self._rdm2 is not None: + return self._rdm2 + else: + print("2-RDM has not been computed. Return None for 2-RDM.") + return None + +
+[docs] + def compute_rdms(self, U: QCircuit = None, variables: Variables = None, spin_free: bool = True, + get_rdm1: bool = True, get_rdm2: bool = True, ordering="dirac", use_hcb: bool = False, + rdm_trafo: QubitHamiltonian = None, evaluate=True): + """ + Computes the one- and two-particle reduced density matrices (rdm1 and rdm2) given + a unitary U. This method uses the standard ordering in physics as denoted below. + Note, that the representation of the density matrices depends on the qubit transformation + used. The Jordan-Wigner encoding corresponds to 'classical' second quantized density + matrices in the occupation picture. + + We only consider real orbitals and thus real-valued RDMs. + The matrices are set as private members _rdm1, _rdm2 and can be accessed via the properties rdm1, rdm2. + + .. math : + \\text{rdm1: } \\gamma^p_q = \\langle \\psi | a^p a_q | \\psi \\rangle + = \\langle U 0 | a^p a_q | U 0 \\rangle + \\text{rdm2: } \\gamma^{pq}_{rs} = \\langle \\psi | a^p a^q a_s a_r | \\psi \\rangle + = \\langle U 0 | a^p a^q a_s a_r | U 0 \\rangle + + Parameters + ---------- + U : + Quantum Circuit to achieve the desired state \\psi = U |0\\rangle, non-optional + variables : + If U is parametrized, then need to hand over a set of fixed variables + spin_free : + Set whether matrices should be spin-free (summation over spin) or defined by spin-orbitals + get_rdm1, get_rdm2 : + Set whether either one or both rdm1, rdm2 should be computed. If both are needed at some point, + it is recommended to compute them at once. + rdm_trafo : + The rdm operators can be transformed, e.g., a^dagger_i a_j -> U^dagger a^dagger_i a_j U, + where U represents the transformation. The default is set to None, implying that U equas the identity. + evaluate : + if true, the tequila expectation values are evaluated directly via the tq.simulate command. + the protocol is optimized to avoid repetation of wavefunction simulation + if false, the rdms are returned as tq.QTensors + Returns + ------- + """ + # Check whether unitary circuit is not 0 + if U is None: + raise TequilaException('Need to specify a Quantum Circuit.') + # Check whether transformation is BKSF. + # Issue here: when a single operator acts only on a subset of qubits, BKSF might not yield the correct + # transformation, because it computes the number of qubits incorrectly in this case. + # A hotfix such as for symmetry_conserving_bravyi_kitaev would require deeper changes, thus omitted for now + if type(self.transformation).__name__ == "BravyiKitaevFast": + raise TequilaException( + "The Bravyi-Kitaev-Superfast transformation does not support general FermionOperators yet.") + # Set up number of spin-orbitals and molecular orbitals respectively + n_SOs = 2 * self.n_orbitals + n_MOs = self.n_orbitals + + # Check whether unitary circuit is not 0 + if U is None: + raise TequilaException('Need to specify a Quantum Circuit.') + + def _get_hcb_op(op_tuple): + '''Build the hardcore boson operators: b^\dagger_ib_j + h.c. in qubit encoding ''' + if (len(op_tuple) == 2): + return 2 * Sm(op_tuple[0][0]) * Sp(op_tuple[1][0]) + elif (len(op_tuple) == 4): + if ((op_tuple[0][0] == op_tuple[1][0]) and (op_tuple[2][0] == op_tuple[3][0])): # iijj uddu+duud + return Sm(op_tuple[0][0]) * Sp(op_tuple[2][0]) + Sm(op_tuple[2][0]) * Sp(op_tuple[0][0]) + if ((op_tuple[0][0] == op_tuple[2][0]) and (op_tuple[1][0] == op_tuple[3][0]) and ( + op_tuple[0][0] != op_tuple[1][0]) and (op_tuple[2][0] != op_tuple[3][0])): # ijij uuuu+dddd + return 4 * Sm(op_tuple[0][0]) * Sm(op_tuple[1][0]) * Sp(op_tuple[2][0]) * Sp(op_tuple[3][0]) + if ((op_tuple[0][0] == op_tuple[3][0]) and (op_tuple[1][0] == op_tuple[2][0]) and ( + op_tuple[0][0] != op_tuple[1][0]) and (op_tuple[2][0] != op_tuple[3][0])): # ijji abba + return -2 * Sm(op_tuple[0][0]) * Sm(op_tuple[1][0]) * Sp(op_tuple[2][0]) * Sp(op_tuple[3][0]) + else: + return Zero() + + def _get_of_op(operator_tuple): + """ Returns operator given by a operator tuple as OpenFermion - Fermion operator """ + op = openfermion.FermionOperator(operator_tuple) + return op + + def _get_qop_hermitian(of_operator) -> QubitHamiltonian: + """ Returns Hermitian part of Fermion operator as QubitHamiltonian """ + qop = self.transformation(of_operator) + # qop = QubitHamiltonian(self.transformation(of_operator)) + real, imag = qop.split(hermitian=True) + if real: + return real + elif not real: + raise TequilaException( + "Qubit Hamiltonian does not have a Hermitian part. Operator ={}".format(of_operator)) + + def _build_1bdy_operators_spinful() -> list: + """ Returns spinful one-body operators as a symmetry-reduced list of QubitHamiltonians """ + # Exploit symmetry pq = qp + ops = [] + for p in range(n_SOs): + for q in range(p + 1): + op_tuple = ((p, 1), (q, 0)) + op = _get_of_op(op_tuple) + ops += [op] + + return ops + + def _build_2bdy_operators_spinful() -> list: + """ Returns spinful two-body operators as a symmetry-reduced list of QubitHamiltonians """ + # Exploit symmetries pqrs = -pqsr = -qprs = qpsr + # and = rspq + ops = [] + for p in range(n_SOs): + for q in range(p): + for r in range(n_SOs): + for s in range(r): + if p * n_SOs + q >= r * n_SOs + s: + op_tuple = ((p, 1), (q, 1), (s, 0), (r, 0)) + op = _get_of_op(op_tuple) + ops += [op] + + return ops + + def _build_1bdy_operators_spinfree() -> list: + """ Returns spinfree one-body operators as a symmetry-reduced list of QubitHamiltonians """ + # Exploit symmetry pq = qp (not changed by spin-summation) + ops = [] + for p in range(n_MOs): + for q in range(p + 1): + # Spin aa + op_tuple = ((2 * p, 1), (2 * q, 0)) + op = _get_of_op(op_tuple) + # Spin bb + op_tuple = ((2 * p + 1, 1), (2 * q + 1, 0)) + op += _get_of_op(op_tuple) + ops += [op] + + return ops + + def _build_2bdy_operators_spinfree() -> list: + """ Returns spinfree two-body operators as a symmetry-reduced list of QubitHamiltonians """ + # Exploit symmetries pqrs = qpsr (due to spin summation, '-pqsr = -qprs' drops out) + # and = rspq + ops = [] + for p, q, r, s in product(range(n_MOs), repeat=4): + if p * n_MOs + q >= r * n_MOs + s and (p >= q or r >= s): + # Spin aaaa + op_tuple = ((2 * p, 1), (2 * q, 1), (2 * s, 0), (2 * r, 0)) if (p != q and r != s) else '0.0 []' + op = _get_of_op(op_tuple) + # Spin abab + op_tuple = ((2 * p, 1), (2 * q + 1, 1), (2 * s + 1, 0), (2 * r, 0)) if ( + 2 * p != 2 * q + 1 and 2 * r != 2 * s + 1) else '0.0 []' + op += _get_of_op(op_tuple) + # Spin baba + op_tuple = ((2 * p + 1, 1), (2 * q, 1), (2 * s, 0), (2 * r + 1, 0)) if ( + 2 * p + 1 != 2 * q and 2 * r + 1 != 2 * s) else '0.0 []' + op += _get_of_op(op_tuple) + # Spin bbbb + op_tuple = ((2 * p + 1, 1), (2 * q + 1, 1), (2 * s + 1, 0), (2 * r + 1, 0)) if ( + p != q and r != s) else '0.0 []' + op += _get_of_op(op_tuple) + ops += [op] + return ops + + def _assemble_rdm1(evals, rdm1=None) -> numpy.ndarray: + """ + Returns spin-ful or spin-free one-particle RDM built by symmetry conditions + Same symmetry with or without spin, so we can use the same function + """ + N = n_MOs if spin_free else n_SOs + if rdm1 is None: + rdm1 = numpy.zeros([N, N]) + ctr: int = 0 + for p in range(N): + for q in range(p + 1): + rdm1[p, q] = evals[ctr] + # Symmetry pq = qp + rdm1[q, p] = rdm1[p, q] + ctr += 1 + + return rdm1 + + def _assemble_rdm2_spinful(evals, rdm2=None) -> numpy.ndarray: + """ Returns spin-ful two-particle RDM built by symmetry conditions """ + ctr: int = 0 + if rdm2 is None: + rdm2 = numpy.zeros([n_SOs, n_SOs, n_SOs, n_SOs]) + for p in range(n_SOs): + for q in range(p): + for r in range(n_SOs): + for s in range(r): + if p * n_SOs + q >= r * n_SOs + s: + rdm2[p, q, r, s] = evals[ctr] + # Symmetry pqrs = rspq + rdm2[r, s, p, q] = rdm2[p, q, r, s] + ctr += 1 + + # Further permutational symmetries due to anticommutation relations + for p in range(n_SOs): + for q in range(p): + for r in range(n_SOs): + for s in range(r): + rdm2[p, q, s, r] = -1 * rdm2[p, q, r, s] # pqrs = -pqsr + rdm2[q, p, r, s] = -1 * rdm2[p, q, r, s] # pqrs = -qprs + rdm2[q, p, s, r] = rdm2[p, q, r, s] # pqrs = qpsr + + return rdm2 + + def _assemble_rdm2_spinfree(evals, rdm2=None) -> numpy.ndarray: + """ Returns spin-free two-particle RDM built by symmetry conditions """ + ctr: int = 0 + if rdm2 is None: + rdm2 = numpy.zeros([n_MOs, n_MOs, n_MOs, n_MOs]) + for p, q, r, s in product(range(n_MOs), repeat=4): + if p * n_MOs + q >= r * n_MOs + s and (p >= q or r >= s): + rdm2[p, q, r, s] = evals[ctr] + # Symmetry pqrs = rspq + rdm2[r, s, p, q] = rdm2[p, q, r, s] + ctr += 1 + + # Further permutational symmetry: pqrs = qpsr + for p, q, r, s in product(range(n_MOs), repeat=4): + if p >= q or r >= s: + rdm2[q, p, s, r] = rdm2[p, q, r, s] + + return rdm2 + + def _build_1bdy_operators_hcb() -> list: + """ Returns hcb one-body operators as a symmetry-reduced list of QubitHamiltonians """ + # Exploit symmetry pq = qp (not changed by spin-summation) + ops = [] + for p in range(n_MOs): + for q in range(p + 1): + if (p == q): + if (self.transformation.up_then_down): + op_tuple = ((p, 1), (p, 0)) + op = _get_hcb_op(op_tuple) + else: + op_tuple = ((2 * p, 1), (2 * p, 0)) + op = _get_hcb_op(op_tuple) + ops += [op] + else: + ops += [Zero()] + return ops + + def _build_2bdy_operators_hcb() -> list: + """ Returns hcb two-body operators as a symmetry-reduced list of QubitHamiltonians """ + # Exploit symmetries pqrs = qpsr (due to spin summation, '-pqsr = -qprs' drops out) + # and = rspq + ops = [] + scale = 2 + if self.transformation.up_then_down: + scale = 1 + for p, q, r, s in product(range(n_MOs), repeat=4): + if p * n_MOs + q >= r * n_MOs + s and (p >= q or r >= s): + # Spin abba+ baab allow p=q=r=s orb iijj + op_tuple = ((scale * p, 1), (scale * q, 1), (scale * r, 0), (scale * s, 0)) if ( + p == q and s == r) else '0.0 []' + op = _get_hcb_op(op_tuple) + # Spin abba+ baab dont allow p=q=r=s orb ijij + op_tuple = ((scale * p, 1), (scale * q, 1), (scale * r, 0), (scale * s, 0)) if ( + p != q and r != s and p == r and s == q) else '0.0 []' + op += _get_hcb_op(op_tuple) + # Spin aaaa+ bbbb dont allow p=q=r=s orb ijji + op_tuple = ((scale * p, 1), (scale * q, 1), (scale * r, 0), (scale * s, 0)) if ( + p != q and r != s and p == s and q == r) else '0.0 []' + op += _get_hcb_op(op_tuple) + ops += [op] + return ops + + # Build operator lists + qops = [] + if spin_free and not use_hcb: + qops += _build_1bdy_operators_spinfree() if get_rdm1 else [] + qops += _build_2bdy_operators_spinfree() if get_rdm2 else [] + elif use_hcb: + qops += _build_1bdy_operators_hcb() if get_rdm1 else [] + qops += _build_2bdy_operators_hcb() if get_rdm2 else [] + else: + if use_hcb: + raise TequilaException( + "compute_rdms: spin_free={} and use_hcb={} are not compatible".format(spin_free, use_hcb)) + qops += _build_1bdy_operators_spinful() if get_rdm1 else [] + qops += _build_2bdy_operators_spinful() if get_rdm2 else [] + + # Transform operator lists to QubitHamiltonians + if (not use_hcb): + qops = [_get_qop_hermitian(op) for op in qops] + + # Compute expected values + rdm1 = None + rdm2 = None + from tequila import QTensor + if evaluate: + if rdm_trafo is None: + evals = simulate(ExpectationValue(H=qops, U=U, shape=[len(qops)]), variables=variables) + else: + qops = [rdm_trafo.dagger()*qops[i]*rdm_trafo for i in range(len(qops))] + evals = simulate(ExpectationValue(H=qops, U=U, shape=[len(qops)]), variables=variables) + else: + if rdm_trafo is None: + evals = [ExpectationValue(H=x, U=U) for x in qops] + N = n_MOs if spin_free else n_SOs + rdm1 = QTensor(shape=[N,N]) + rdm2 = QTensor(shape=[N, N, N, N]) + else: + raise TequilaException("compute_rdms: rdm_trafo was set but evaluate flag is False (not supported)") + + # Assemble density matrices + # If self._rdm1, self._rdm2 exist, reset them if they are of the other spin-type + def _reset_rdm(rdm): + if rdm is not None: + if (spin_free or use_hcb) and rdm.shape[0] != n_MOs: + return None + if not spin_free and rdm.shape[0] != n_SOs: + return None + return rdm + + self._rdm1 = _reset_rdm(self._rdm1) + self._rdm2 = _reset_rdm(self._rdm2) + # Split expectation values in 1- and 2-particle expectation values + if get_rdm1: + len_1 = n_MOs * (n_MOs + 1) // 2 if (spin_free or use_hcb) else n_SOs * (n_SOs + 1) // 2 + else: + len_1 = 0 + evals_1, evals_2 = evals[:len_1], evals[len_1:] + # Build matrices using the expectation values + self._rdm1 = _assemble_rdm1(evals_1, rdm1=rdm1) if get_rdm1 else self._rdm1 + if spin_free or use_hcb: + self._rdm2 = _assemble_rdm2_spinfree(evals_2, rdm2=rdm2) if get_rdm2 else self._rdm2 + else: + self._rdm2 = _assemble_rdm2_spinful(evals_2, rdm2=rdm2) if get_rdm2 else self._rdm2 + + if get_rdm2: + rdm2 = NBodyTensor(elems=self.rdm2, ordering="dirac", verify=False) + rdm2.reorder(to=ordering) + rdm2 = rdm2.elems + self._rdm2 = rdm2 + + if get_rdm1: + if get_rdm2: + return self.rdm1, self.rdm2 + else: + return self.rdm1 + elif get_rdm2: + return self.rdm2 + else: + warnings.warn("compute_rdms called with instruction to not compute?", TequilaWarning)
+ + +
+[docs] + def rdm_spinsum(self, sum_rdm1: bool = True, sum_rdm2: bool = True) -> tuple: + """ + Given the spin-ful 1- and 2-particle reduced density matrices, compute the spin-free RDMs by spin summation. + + Parameters + ---------- + sum_rdm1, sum_rdm2 : + If set to true, perform spin summation on rdm1, rdm2 + + Returns + ------- + rdm1_spinsum, rdm2_spinsum : + The desired spin-free matrices + """ + n_MOs = self.n_orbitals + rdm1_spinsum = None + rdm2_spinsum = None + + # Spin summation on rdm1 + if sum_rdm1: + # Check whether spin-rdm2 exists + if self._rdm1 is None: + raise TequilaException("The spin-RDM for the 1-RDM does not exist!") + # Check whether existing rdm1 is in spin-orbital basis + if self._rdm1.shape[0] != 2 * n_MOs: + raise TequilaException("The existing RDM needs to be in spin-orbital basis, it is already spin-free!") + # Do summation + rdm1_spinsum = numpy.zeros([n_MOs, n_MOs]) + for p in range(n_MOs): + for q in range(p + 1): + rdm1_spinsum[p, q] += self._rdm1[2 * p, 2 * q] + rdm1_spinsum[p, q] += self._rdm1[2 * p + 1, 2 * q + 1] + for p in range(n_MOs): + for q in range(p): + rdm1_spinsum[q, p] = rdm1_spinsum[p, q] + + # Spin summation on rdm2 + if sum_rdm2: + # Check whether spin-rdm2 exists + if self._rdm2 is None: + raise TequilaException("The spin-RDM for the 2-RDM does not exist!") + # Check whether existing rdm2 is in spin-orbital basis + if self._rdm2.shape[0] != 2 * n_MOs: + raise TequilaException("The existing RDM needs to be in spin-orbital basis, it is already spin-free!") + # Do summation + rdm2_spinsum = numpy.zeros([n_MOs, n_MOs, n_MOs, n_MOs]) + for p, q, r, s in product(range(n_MOs), repeat=4): + rdm2_spinsum[p, q, r, s] += self._rdm2[2 * p, 2 * q, 2 * r, 2 * s] + rdm2_spinsum[p, q, r, s] += self._rdm2[2 * p + 1, 2 * q, 2 * r + 1, 2 * s] + rdm2_spinsum[p, q, r, s] += self._rdm2[2 * p, 2 * q + 1, 2 * r, 2 * s + 1] + rdm2_spinsum[p, q, r, s] += self._rdm2[2 * p + 1, 2 * q + 1, 2 * r + 1, 2 * s + 1] + + return rdm1_spinsum, rdm2_spinsum
+ + +
+[docs] + def perturbative_f12_correction(self, rdm1: numpy.ndarray = None, rdm2: numpy.ndarray = None, + gamma: float = 1.4, n_ri: int = None, + external_info: dict = None, **kwargs) -> float: + """ + Computes the spin-free [2]_R12 correction, needing only the 1- and 2-RDM of a reference method + Requires either 1-RDM, 2-RDM or information to compute them in kwargs + + Parameters + ---------- + rdm1 : + 1-electron reduced density matrix + rdm2 : + 2-electron reduced density matrix + gamma : + f12-exponent, for a correlation factor f_12 = -1/gamma * exp[-gamma*r_12] + n_ri : + dimensionality of RI-basis; specify only, if want to truncate available RI-basis + if None, then the maximum available via tensors / basis-set is used + must not be larger than size of available RI-basis, and not smaller than size of OBS + for n_ri==dim(OBS), the correction returns zero + external_info : + for usage in qc_base, need to provide information where to find one-body tensor f12-tensor <rs|f_12|pq>; + pass dictionary with {"f12_filename": where to find f12-tensor, "scheme": ordering scheme of tensor} + kwargs : + e.g. RDM-information via {"U": QCircuit, "variables": optimal angles}, needs to be passed if rdm1,rdm2 not + yet computed + + Returns + ------- + the f12 correction for the energy + """ + from .f12_corrections._f12_correction_base import ExplicitCorrelationCorrection + correction = ExplicitCorrelationCorrection(mol=self, rdm1=rdm1, rdm2=rdm2, gamma=gamma, + n_ri=n_ri, external_info=external_info, **kwargs) + return correction.compute()
+ + +
+[docs] + def n_rotation(self, i, phi): + ''' + Creates a quantum circuit that applies a phase rotation based on phi to both components (up and down) of a given qubit. + + Parameters: + - i (int): The index of the qubit to which the rotation will be applied. + - phi (float): The rotation angle. The actual rotation applied will be multiplied with -2 for both components. + + Returns: + - QCircuit: A quantum circuit object containing the sequence of rotations applied to the up and down components of the specified qubit. + ''' + + # Generate number operators for the up and down components of the qubit. + n_up = self.make_number_op(2*i) + n_down = self.make_number_op(2*i+1) + + # Start a new circuit and apply rotations to each component. + circuit = gates.GeneralizedRotation(generator = n_up, angle=-2*phi) + circuit += gates.GeneralizedRotation(generator = n_down, angle=-2*phi) + return circuit
+ + +
+[docs] + def get_givens_circuit(self, unitary, tol = 1e-12, ordering = OPTIMIZED_ORDERING): + ''' + Constructs a quantum circuit from a given real unitary matrix using Givens rotations. + + This method decomposes a unitary matrix into a series of Givens and Rz (phase) rotations, + then constructs and returns a quantum circuit that implements this sequence of rotations. + + Parameters: + - unitary (numpy.array): A real unitary matrix representing the transformation to implement. + - tol (float): A tolerance threshold below which matrix elements are considered zero. + - ordering (list of tuples or 'Optimized'): Custom ordering of indices for Givens rotations or 'Optimized' to generate them automatically. + + Returns: + - QCircuit: A quantum circuit implementing the series of rotations decomposed from the unitary. + ''' + # Decompose the unitary matrix into Givens and phase (Rz) rotations. + theta_list, phi_list = get_givens_decomposition(unitary, tol, ordering) + + # Initialize an empty quantum circuit. + circuit = QCircuit() + + # Add all Rz (phase) rotations to the circuit. + for phi in phi_list: + circuit += self.n_rotation(phi[1], phi[0]) + + # Add all Givens rotations to the circuit. + for theta in reversed(theta_list): + circuit += self.UR(theta[1], theta[2], theta[0]*2) + + return circuit
+ + + +
+[docs] + def print_basis_info(self): + return self.integral_manager.print_basis_info()
+ + + def __str__(self) -> str: + result = str(type(self)) + "\n" + result += "Qubit Encoding\n" + result += str(self.transformation) + "\n\n" + result += "Parameters\n" + for k, v in self.parameters.__dict__.items(): + result += "{key:15} : {value:15} \n".format(key=str(k), value=str(v)) + + result += "{key:15} : {value:15} \n".format(key="n_qubits", value=str(self.n_orbitals * 2)) + result += "{key:15} : {value:15} \n".format(key="reference state", value=str(self._reference_state())) + + result += "\nBasis\n" + result += str(self.integral_manager) + result += "\nmore information with: self.print_basis_info()\n" + + return result
+ + +
+[docs] +def givens_matrix(n, p, q, theta): + ''' + Construct a complex Givens rotation matrix of dimension n by theta between rows/columns p and q. + ''' + ''' + Generates a Givens rotation matrix of size n x n to rotate by angle theta in the (p, q) plane. This matrix can be complex + + Parameters: + - n (int): The size of the Givens rotation matrix. + - p (int): The first index for the rotation plane. + - q (int): The second index for the rotation plane. + - theta (float): The rotation angle. + + Returns: + - numpy.array: The Givens rotation matrix. + ''' + matrix = numpy.eye(n) # Matrix to hold complex numbers + cos_theta = numpy.cos(theta) + sin_theta = numpy.sin(theta) + + # Directly assign cosine and sine without complex phase adjustment + matrix[p, p] = cos_theta + matrix[q, q] = cos_theta + matrix[p, q] = sin_theta + matrix[q, p] = -sin_theta + + return matrix
+ + +
+[docs] +def get_givens_decomposition(unitary, tol = 1e-12, ordering = OPTIMIZED_ORDERING, return_diagonal = False): + ''' + Decomposes a real unitary matrix into Givens rotations (theta) and Rz rotations (phi). + + Parameters: + - unitary (numpy.array): A real unitary matrix to decompose. It cannot be complex. + - tol (float): Tolerance for considering matrix elements as zero. Elements with absolute value less than tol are treated as zero. + - ordering (list of tuples or 'Optimized'): Custom ordering of indices for Givens rotations or 'Optimized' to generate them automatically. + - return_diagonal (bool): If True, the function also returns the diagonal matrix as part of the output. + + Returns: + - list: A list of tuples, each representing a Givens rotation. Each tuple contains the rotation angle theta and indices (i,j) of the rotation. + - list: A list of tuples, each representing an Rz rotation. Each tuple contains the rotation angle phi and the index (i) of the rotation. + - numpy.array (optional): The diagonal matrix after applying all Givens rotations, returned if return_diagonal is True. + ''' + U = unitary # no need to copy as we don't modify the original + U[abs(U) < tol] = 0 # Zeroing out the small elements as per the tolerance level. + n = U.shape[0] + + # Determine optimized ordering if specified. + if ordering == OPTIMIZED_ORDERING: + ordering = ff.depth_eff_order_mf(n) + + theta_list = [] + phi_list = [] + + def calcTheta(U, c, r): + '''Calculate and apply the Givens rotation for a specific matrix element.''' + t = numpy.arctan2(-U[r,c], U[r-1,c]) + theta_list.append((t, r, r-1)) + g = givens_matrix(n,r,r-1,t) + U = numpy.dot(g, U) + + return U + + # Apply and store Givens rotations as per the given or computed ordering. + if ordering is None: + for c in range(n): + for r in range(n-1, c, -1): + U = calcTheta(U, c, r) + else: + for r, c in ordering: + U = calcTheta(U, c, r) + + # Calculating the Rz rotations based on the phases of the diagonal elements. + # For real elements this means a 180 degree shift, i.e. a sign change. + for i in range(n): + ph = numpy.angle(U[i,i]) + phi_list.append((ph, i)) + + # Filtering out rotations without significance. + theta_list_new = [] + for i, theta in enumerate(theta_list): + if abs(theta[0] % (2*numpy.pi)) > tol: + theta_list_new.append(theta) + + phi_list_new = [] + for i, phi in enumerate(phi_list): + if abs(phi[0]) > tol: + phi_list_new.append(phi) + + if return_diagonal: + # Optionally return the resulting diagonal + return theta_list_new, phi_list_new, U + else: + return theta_list_new, phi_list_new
+ + +
+[docs] +def reconstruct_matrix_from_givens(n, theta_list, phi_list, to_real_if_possible = True, tol = 1e-12): + ''' + Reconstructs a matrix from given Givens rotations and Rz diagonal rotations. + This function is effectively an inverse of get_givens_decomposition, and therefore only works with data in the same format as its output. + + Parameters: + - n (int): The size of the unitary matrix to be reconstructed. + - theta_list (list of tuples): Each tuple contains (angle, i, j) representing a Givens rotation of `angle` radians, applied to rows/columns `i` and `j`. + - phi_list (list of tuples): Each tuple contains (angle, i), representing an Rz rotation by `angle` radians applied to the `i`th diagonal element. + - to_real_if_possible (bool): If True, converts the matrix to real if its imaginary part is effectively zero. + - tol (float): The tolerance whether to swap a complex rotation for a sign change. + + Returns: + - numpy.ndarray: The reconstructed complex or real matrix, depending on the `to_real_if_possible` flag and matrix composition. + ''' + # Start with an identity matrix + reconstructed = numpy.eye(n, dtype=complex) + + # Apply Rz rotations for diagonal elements + for phi in phi_list: + angle, i = phi + # Directly apply a sign flip if the rotation angle is π + if numpy.isclose(angle, numpy.pi, atol=tol): + reconstructed[i, i] *= -1 + else: + reconstructed[i, i] *= numpy.exp(1j * angle) + + # Apply Givens rotations in reverse order + for theta in reversed(theta_list): + angle, i, j = theta + g = givens_matrix(n, i, j, angle) + reconstructed = numpy.dot(g.conj().T, reconstructed) # Transpose of Givens matrix applied to the left + + # Convert matrix to real if its imaginary part is negligible unless disabled via to_real_if_possible + if to_real_if_possible: + # Directly apply a sign flip if the rotation angle is π + if numpy.all(reconstructed.imag == 0): + # Convert to real by taking the real part + reconstructed = reconstructed.real + + return reconstructed
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/simulators/simulator_api.html b/docs/sphinx/_modules/tequila_code/simulators/simulator_api.html new file mode 100644 index 0000000..f535b56 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/simulators/simulator_api.html @@ -0,0 +1,703 @@ + + + + + + + + tequila_code.simulators.simulator_api — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for tequila_code.simulators.simulator_api

+from collections import namedtuple
+import typing, warnings, numpy
+from numbers import Real as RealNumber
+from typing import Dict, Union, Hashable
+import pkg_resources
+from pkg_resources import DistributionNotFound
+
+from tequila.objective import Objective, Variable, assign_variable, format_variable_dictionary, QTensor
+from tequila.utils.exceptions import TequilaException, TequilaWarning
+from tequila.simulators.simulator_base import BackendCircuit, BackendExpectationValue
+from tequila.circuit.noise import NoiseModel
+
+SUPPORTED_BACKENDS = ["qulacs_gpu", "qulacs",'qibo', "qiskit", "cirq", "pyquil", "symbolic", "qlm"]
+SUPPORTED_NOISE_BACKENDS = ["qiskit", 'cirq', 'pyquil'] # qulacs removed in v.1.9
+BackendTypes = namedtuple('BackendTypes', 'CircType ExpValueType')
+INSTALLED_SIMULATORS = {}
+INSTALLED_SAMPLERS = {}
+
+HAS_QULACS = True
+INSTALLED_NOISE_SAMPLERS = {}
+if typing.TYPE_CHECKING:
+    from tequila.objective import Objective, Variable
+    from tequila.circuit.gates import QCircuit
+    import numbers.Real as RealNumber
+    from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
+
+"""
+Check which simulators are installed
+We are distinguishing two classes of simulators: Samplers and full wavefunction simulators
+"""
+
+
+HAS_QISKIT = True
+try:
+    from tequila.simulators.simulator_qiskit import BackendCircuitQiskit, BackendExpectationValueQiskit
+    HAS_QISKIT = True
+    INSTALLED_SIMULATORS["qiskit"] = BackendTypes(BackendCircuitQiskit, BackendExpectationValueQiskit)
+    INSTALLED_SAMPLERS["qiskit"] = BackendTypes(BackendCircuitQiskit, BackendExpectationValueQiskit)
+    from tequila.simulators.simulator_qiskit import HAS_NOISE as HAS_QISKIT_NOISE
+    if HAS_QISKIT_NOISE:
+        INSTALLED_NOISE_SAMPLERS["qiskit"] = BackendTypes(BackendCircuitQiskit, BackendExpectationValueQiskit)
+except ImportError:
+    HAS_QISKIT = False
+    HAS_QISKIT_NOISE = False
+
+HAS_QIBO = True
+try:
+    from tequila.simulators.simulator_qibo import BackendCircuitQibo, BackendExpectationValueQibo
+    HAS_QIBO = True
+    INSTALLED_SIMULATORS["qibo"] = BackendTypes(BackendCircuitQibo, BackendExpectationValueQibo)
+    INSTALLED_SAMPLERS["qibo"] = BackendTypes(BackendCircuitQibo, BackendExpectationValueQibo)
+    INSTALLED_NOISE_SAMPLERS["qibo"] = BackendTypes(BackendCircuitQibo, BackendExpectationValueQibo)
+except ImportError:
+    HAS_QIBO = False
+
+HAS_CIRQ = True
+try:
+    from tequila.simulators.simulator_cirq import BackendCircuitCirq, BackendExpectationValueCirq
+
+    HAS_CIRQ = True
+    INSTALLED_SIMULATORS["cirq"] = BackendTypes(CircType=BackendCircuitCirq, ExpValueType=BackendExpectationValueCirq)
+    INSTALLED_SAMPLERS["cirq"] = BackendTypes(CircType=BackendCircuitCirq, ExpValueType=BackendExpectationValueCirq)
+    INSTALLED_NOISE_SAMPLERS["cirq"] = BackendTypes(CircType=BackendCircuitCirq,
+                                                    ExpValueType=BackendExpectationValueCirq)
+
+except ImportError:
+    HAS_CIRQ = False
+
+try:
+    pkg_resources.require("qulacs")
+    import qulacs
+    from tequila.simulators.simulator_qulacs import BackendCircuitQulacs, BackendExpectationValueQulacs
+
+    HAS_QULACS = True
+    INSTALLED_SIMULATORS["qulacs"] = BackendTypes(CircType=BackendCircuitQulacs,
+                                                  ExpValueType=BackendExpectationValueQulacs)
+    INSTALLED_SAMPLERS["qulacs"] = BackendTypes(CircType=BackendCircuitQulacs,
+                                                ExpValueType=BackendExpectationValueQulacs)
+    INSTALLED_NOISE_SAMPLERS["qulacs"] = BackendTypes(CircType=BackendCircuitQulacs,
+                                                      ExpValueType=BackendExpectationValueQulacs)
+except (ImportError, DistributionNotFound):
+    HAS_QULACS = False
+
+try:
+    pkg_resources.require("qulacs-gpu")
+    import qulacs
+    from tequila.simulators.simulator_qulacs_gpu import BackendCircuitQulacsGpu, BackendExpectationValueQulacsGpu
+
+    HAS_QULACS_GPU = True
+    INSTALLED_SIMULATORS["qulacs_gpu"] = BackendTypes(CircType=BackendCircuitQulacsGpu,
+                                                  ExpValueType=BackendExpectationValueQulacsGpu)
+    INSTALLED_SAMPLERS["qulacs_gpu"] = BackendTypes(CircType=BackendCircuitQulacsGpu,
+                                                ExpValueType=BackendExpectationValueQulacsGpu)
+    INSTALLED_NOISE_SAMPLERS["qulacs_gpu"] = BackendTypes(CircType=BackendCircuitQulacsGpu,
+                                                      ExpValueType=BackendExpectationValueQulacsGpu)
+except (ImportError, DistributionNotFound):
+    HAS_QULACS_GPU = False
+
+
+HAS_PYQUIL = True
+
+try:
+    from tequila.simulators.simulator_pyquil import BackendCircuitPyquil, BackendExpectationValuePyquil
+
+    HAS_PYQUIL = True
+    INSTALLED_SIMULATORS["pyquil"] = BackendTypes(BackendCircuitPyquil, BackendExpectationValuePyquil)
+    INSTALLED_SAMPLERS["pyquil"] = BackendTypes(BackendCircuitPyquil, BackendExpectationValuePyquil)
+    INSTALLED_NOISE_SAMPLERS["pyquil"] = BackendTypes(BackendCircuitPyquil, BackendExpectationValuePyquil)
+except ImportError:
+    HAS_PYQUIL = False
+
+
+HAS_QLM = True
+try:
+    from tequila.simulators.simulator_qlm import BackendCircuitQLM, BackendExpectationValueQLM
+
+    INSTALLED_SIMULATORS["qlm"] = BackendTypes(BackendCircuitQLM, BackendExpectationValueQLM)
+    INSTALLED_SAMPLERS["qlm"] = BackendTypes(BackendCircuitQLM, BackendExpectationValueQLM)
+except ImportError:
+    HAS_QLM = False
+
+from tequila.simulators.simulator_symbolic import BackendCircuitSymbolic, BackendExpectationValueSymbolic
+
+INSTALLED_SIMULATORS["symbolic"] = BackendTypes(CircType=BackendCircuitSymbolic,
+                                                ExpValueType=BackendExpectationValueSymbolic)
+HAS_SYMBOLIC = True
+
+
+
+[docs] +def show_available_simulators(): + """ """ + print("{:15} | {:10} | {:10} | {:10} | {:10}".format("backend", "wfn", "sampling", "noise", "installed")) + print("--------------------------------------------------------------------") + for k in SUPPORTED_BACKENDS: + print("{:15} | {:10} | {:10} | {:10} | {:10}".format(k, + str(k in INSTALLED_SIMULATORS), + str(k in INSTALLED_SAMPLERS), + str(k in INSTALLED_NOISE_SAMPLERS), + str(k in INSTALLED_BACKENDS))) + if HAS_QISKIT and not HAS_QISKIT_NOISE: + print("missing qiskit_aer: no noisy simulation")
+ + + +
+[docs] +def pick_backend(backend: str = None, samples: int = None, noise: NoiseModel = None, device=None, + exclude_symbolic: bool = True) -> str: + + """ + choose, or verify, a backend for the user. + Parameters + ---------- + backend: str, optional: + what backend to choose or verify. if None: choose for the user. + samples: int, optional: + if int and not None, choose (verify) a simulator which supports sampling. + noise: str or NoiseModel, optional: + if not None, choose (verify) a simulator supports the specified noise. + device: optional: + verify that a given backend supports the specified device. MUST specify backend, if not None. + if None: do not emulate or use real device. + exclude_symbolic: bool, optional: + whether or not to exclude the tequila debugging simulator from the available simulators, when choosing. + + Returns + ------- + str: + the name of the chosen (or verified) backend. + """ + + if len(INSTALLED_SIMULATORS) == 0: + raise TequilaException("No simulators installed on your system") + + if backend is None and device is not None: + raise TequilaException('device use requires backend specification!') + + if backend is None: + if noise is None: + if samples is None: + for f in SUPPORTED_BACKENDS: + if f in INSTALLED_SIMULATORS: + return f + else: + for f in INSTALLED_SAMPLERS.keys(): + return f + else: + if samples is None: + raise TequilaException( + "Noise requires sampling; please provide a positive, integer value for samples") + for f in SUPPORTED_NOISE_BACKENDS: + return f + raise TequilaException( + 'Could not find any installed sampler!') + + + if hasattr(backend, "lower"): + backend = backend.lower() + + if backend == "random": + if device is not None: + raise TequilaException('cannot ask for a random backend and a specific device!') + from numpy import random as random + import time + state = random.RandomState(int(str(time.process_time()).split('.')[-1]) % 2 ** 32) + if samples is None: + backend = state.choice(list(INSTALLED_SIMULATORS.keys()), 1)[0] + else: + backend = state.choice(list(INSTALLED_SAMPLERS.keys()), 1)[0] + + if exclude_symbolic: + while (backend == "symbolic"): + backend = state.choice(list(INSTALLED_SIMULATORS.keys()), 1)[0] + return backend + + if backend not in SUPPORTED_BACKENDS: + raise TequilaException("Backend {backend} not supported ".format(backend=backend)) + + elif noise is None and samples is None and backend not in INSTALLED_SIMULATORS.keys(): + raise TequilaException("Backend {backend} not installed ".format(backend=backend)) + elif noise is None and samples is not None and backend not in INSTALLED_SAMPLERS.keys(): + raise TequilaException("Backend {backend} not installed or sampling not supported".format(backend=backend)) + elif noise is not None and samples is not None and backend not in INSTALLED_NOISE_SAMPLERS.keys(): + raise TequilaException( + "Backend {backend} not installed or else Noise has not been implemented".format(backend=backend)) + + return backend
+ + + +
+[docs] +def compile_objective(objective: typing.Union['Objective'], + variables: typing.Dict['Variable', 'RealNumber'] = None, + backend: str = None, + samples: int = None, + device: str = None, + noise: NoiseModel = None, + *args, + **kwargs) -> Objective: + """ + compile an objective to render it callable and return it. + Parameters + ---------- + objective: Objective: + the objective to compile + variables: dict, optional: + the variables to compile the objective with. Will autogenerate zeros for all variables if not supplied. + backend: str, optional: + the backend to compile the objective to. + samples: int, optional: + only matters if not None; compile the objective for sampling/verify backend can do so + device: optional: + the device on which the objective should (perhaps emulatedly) sample. + noise: str or NoiseModel, optional: + the noise to apply to all circuits in the objective. + args + kwargs + + Returns + ------- + Objective: + the compiled objective. + """ + + backend = pick_backend(backend=backend, samples=samples, noise=noise, device=device) + + # dummy variables + if variables is None: + variables = {k: 0.0 for k in objective.extract_variables()} + + ExpValueType = INSTALLED_SIMULATORS[pick_backend(backend=backend)].ExpValueType + all_compiled = True + # check if compiling is necessary + for arg in objective.args: + if hasattr(arg, "U") and isinstance(arg, BackendExpectationValue): + if not isinstance(arg, ExpValueType): + warnings.warn( + "Looks like part the objective was already compiled for another backend.\nFound ExpectationValue of type {} and {}\n... proceeding with hybrid\n".format( + type(arg), ExpValueType), TequilaWarning) + elif hasattr(arg, "U") and not isinstance(arg, BackendExpectationValue): + all_compiled = False + + if all_compiled: + return objective + + argsets = objective.argsets + compiled_sets = [] + for argset in argsets: + compiled_args = [] + # avoid double compilations + expectationvalues = {} + for arg in argset: + if hasattr(arg, "H") and hasattr(arg, "U") and not isinstance(arg, BackendExpectationValue): + if arg not in expectationvalues: + compiled_expval = ExpValueType(arg, variables=variables, noise=noise, device=device, *args, **kwargs) + expectationvalues[arg] = compiled_expval + else: + compiled_expval = expectationvalues[arg] + compiled_args.append(compiled_expval) + else: + compiled_args.append(arg) + compiled_sets.append(compiled_args) + if isinstance(objective, Objective): + return type(objective)(args=compiled_sets[0], transformation=objective.transformation)
+ + + +
+[docs] +def compile_circuit(abstract_circuit: 'QCircuit', + variables: typing.Dict['Variable', 'RealNumber'] = None, + backend: str = None, + samples: int = None, + noise: NoiseModel = None, + device: str = None, + *args, + **kwargs) -> BackendCircuit: + """ + compile a circuit to render it callable and return it. + Parameters + ---------- + abstract_circuit: QCircuit: + the circuit to compile + variables: dict, optional: + the variables to compile the circuit with. + backend: str, optional: + the backend to compile the circuit to. + samples: int, optional: + only matters if not None; compile the circuit for sampling/verify backend can do so + device: optional: + the device on which the circuit should (perhaps emulatedly) sample. + noise: str or NoiseModel, optional: + the noise to apply to the circuit + args + kwargs + + Returns + ------- + BackendCircuit: + the compiled circuit. + """ + + CircType = INSTALLED_SIMULATORS[ + pick_backend(backend=backend, samples=samples, noise=noise, device=device)].CircType + + # dummy variables + if variables is None: + variables = {k: 0.0 for k in abstract_circuit.extract_variables()} + + if hasattr(abstract_circuit, "simulate"): + if not isinstance(abstract_circuit, CircType): + abstract_circuit = abstract_circuit.abstract_circuit + warnings.warn( + "Looks like the circuit was already compiled for another backend.\nChanging from {} to {}\n".format( + type(abstract_circuit), CircType), TequilaWarning) + else: + return abstract_circuit + + return CircType(abstract_circuit=abstract_circuit, variables=variables, noise=noise, device=device, *args, **kwargs)
+ + + +
+[docs] +def simulate(objective: typing.Union['Objective', 'QCircuit','QTensor'], + variables: Dict[Union[Variable, Hashable], RealNumber] = None, + samples: int = None, + backend: str = None, + noise: NoiseModel = None, + device: str = None, + *args, + **kwargs) -> Union[RealNumber, 'QubitWaveFunction']: + """Simulate a tequila objective or circuit + + Parameters + ---------- + objective: Objective: + tequila objective or circuit + variables: Dict: + The variables of the objective given as dictionary + with keys as tequila Variables/hashable types and values the corresponding real numbers + samples : int, optional: + if None a full wavefunction simulation is performed, otherwise a fixed number of samples is simulated + backend : str, optional: + specify the backend or give None for automatic assignment + noise: NoiseModel, optional: + specify a noise model to apply to simulation/sampling + device: + a device upon which (or in emulation of which) to sample + *args : + + **kwargs : + read_out_qubits = list[int] (define the qubits which shall be measured, has only effect on pure QCircuit simulation with samples) + + Returns + ------- + float or QubitWaveFunction + the result of simulation. + """ + + variables = format_variable_dictionary(variables) + + if variables is None and not (len(objective.extract_variables()) == 0): + raise TequilaException( + "You called simulate for a parametrized type but forgot to pass down the variables: {}".format( + objective.extract_variables())) + + compiled_objective = compile(objective=objective, samples=samples, variables=variables, backend=backend, + noise=noise,device=device, *args, **kwargs) + + return compiled_objective(variables=variables, samples=samples, *args, **kwargs)
+ + + +
+[docs] +def draw(objective, variables=None, backend: str = None, name=None, *args, **kwargs): + """ + Pretty output (depends on installed backends) for jupyter notebooks + or similar HTML environments + + Parameters + ---------- + objective : + the tequila objective to print out + variables : optional: + Give variables if the objective is parametrized (not necesarry for displaying) + name: optional: + Name the objective (changes circuit filenames for qpic backend) + backend: str, optional: + chose preferred backend (of None or not found it will be automatically picked) + """ + if backend not in INSTALLED_SIMULATORS: + backend = None + if name is None: + name = abs(hash("tmp")) + + if backend is None: + from tequila.circuit.qpic import system_has_qpic + if system_has_qpic: + backend = "qpic" + elif "cirq" in INSTALLED_SIMULATORS: + backend = "cirq" + elif "qiskit" in INSTALLED_SIMULATORS: + backend = "qiskit" + + if isinstance(objective, QTensor): + print("won't draw out all objectives in a tensor") + print(objective) + + if isinstance(objective, Objective): + print(objective) + drawn = {} + for i, E in enumerate(objective.get_expectationvalues()): + if E in drawn: + print("\nExpectation Value {} is the same as {}".format(i, drawn[E])) + else: + print("\nExpectation Value {}:".format(i)) + measurements = E.count_measurements() + print("total measurements = {}".format(measurements)) + variables = E.U.extract_variables() + print("variables = {}".format(len(variables))) + filename = "{}_{}.png".format(name,i) + print("circuit = {}".format(filename)) + draw(E.U, backend=backend, filename=filename) + drawn[E] = i + else: + if backend is None: + print(objective) + elif backend.lower() in ["qpic", "html"]: + try: + import IPython + import qpic + from tequila.circuit.qpic import export_to + if "filename" not in kwargs: + kwargs["filename"] = "tmp_{}.png".format(hash(backend)) + + circuit = objective + if hasattr(circuit, "U"): + circuit = circuit.U + if hasattr(circuit, "abstract_circuit"): + circuit = objective.abstract_circuit + + export_to(circuit=circuit, *args, **kwargs) + width=None # full size + height=200 + if "width" in kwargs: + width=kwargs["width"] + if "height" in kwargs: + height=kwargs["height"] # this is buggy in jupyter and will be ignored + image=IPython.display.Image(filename=kwargs["filename"], height=height, width=width) + IPython.display.display(image) + + except ImportError as E: + raise Exception("Original Error Message:{}\nYou are missing dependencies for drawing: You need IPython, qpic and pdfatex.\n".format(E)) + else: + compiled = compile_circuit(abstract_circuit=objective, backend=backend) + if backend == "qiskit": + return compiled.circuit.draw(*args, **kwargs) + else: + print(compiled.circuit) + return ""
+ + +
+[docs] +def compile(objective: typing.Union['Objective', 'QCircuit', 'QTensor'], + variables: Dict[Union['Variable', Hashable], RealNumber] = None, + samples: int = None, + backend: str = None, + noise: NoiseModel = None, + device: str = None, + *args, + **kwargs) -> typing.Union['BackendCircuit', 'Objective']: + """Compile a tequila objective or circuit to a backend + + Parameters + ---------- + objective: Objective: + tequila objective or circuit + variables: dict, optional: + The variables of the objective given as dictionary + with keys as tequila Variables and values the corresponding real numbers + samples: int, optional: + if None a full wavefunction simulation is performed, otherwise a fixed number of samples is simulated + backend : str, optional: + specify the backend or give None for automatic assignment + noise: NoiseModel, optional: + the noise model to apply to the objective or QCircuit. + device: optional: + a device on which (or in emulation of which) to sample the circuit. + Returns + ------- + simulators.BackendCircuit or Objective + the compiled object. + + """ + + backend = pick_backend(backend=backend, noise=noise, samples=samples, device=device) + + if variables is not None: + # allow hashable types as keys without casting it to variables + variables = {assign_variable(k): v for k, v in variables.items()} + + if isinstance(objective, QTensor): + ff = numpy.vectorize(compile_objective) + return ff(objective=objective, samples=samples, variables=variables, backend=backend, noise=noise, device=device, *args, **kwargs) + + if isinstance(objective, Objective) or hasattr(objective, "args"): + return compile_objective(objective=objective, samples=samples, variables=variables, backend=backend, noise=noise, device=device, *args, **kwargs) + elif hasattr(objective, "gates") or hasattr(objective, "abstract_circuit"): + return compile_circuit(abstract_circuit=objective, variables=variables, backend=backend,samples=samples, + noise=noise, device=device, *args, **kwargs) + else: + raise TequilaException( + "Don't know how to compile object of type: {type}, \n{object}".format(type=type(objective), + object=objective))
+ + + +
+[docs] +def compile_to_function(objective: typing.Union['Objective', 'QCircuit'], *args, + **kwargs) -> typing.Union['BackendCircuit', 'Objective']: + """ + Notes + ---------- + Same as compile but gives back callable wrapper + where parameters are passed down as arguments instead of dictionaries + the order of those arguments is the order of the parameter dictionary + given here. If not given it is the order returned by objective.extract_variables() + + See compile for more information on the parameters of this function + + Returns + ------- + BackendCircuit or Objective: + wrapper over a compiled objective/circuit + can be called like: function(0.0,1.0,...,samples=None) + """ + + compiled_objective = compile(objective, *args, **kwargs) + if 'variables' in kwargs: + varnames = list(kwargs['variables'].keys()) + else: + varnames = objective.extract_variables() + + def objective_function(*fargs, **fkwargs): + if len(fargs) != len(varnames): + raise Exception("Compiled function takes {} variables. You passed down {} arguments." + "Use keywords for samples and other instructions\n" + "like function(a,b,c, samples=10)".format(len(varnames), len(fargs))) + vars = {varnames[i]: fargs[i] for i, v in enumerate(fargs)} + return compiled_objective(variables=vars, **fkwargs) + + return objective_function
+ + + +INSTALLED_BACKENDS = {**INSTALLED_SIMULATORS, **INSTALLED_SAMPLERS} +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/simulators/simulator_base.html b/docs/sphinx/_modules/tequila_code/simulators/simulator_base.html new file mode 100644 index 0000000..fe6113a --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/simulators/simulator_base.html @@ -0,0 +1,1096 @@ + + + + + + + + tequila_code.simulators.simulator_base — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for tequila_code.simulators.simulator_base

+from tequila.utils import TequilaException, to_float, TequilaWarning
+from tequila.circuit.circuit import QCircuit
+from tequila.utils.keymap import KeyMapSubregisterToRegister
+from tequila.utils.misc import to_float
+from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
+from tequila.circuit.compiler import change_basis
+from tequila import BitString
+from tequila.objective.objective import Variable, format_variable_dictionary
+from tequila.circuit import compiler
+
+import numbers, typing, numpy, copy, warnings
+
+from dataclasses import dataclass
+
+"""
+Todo: Classes are now immutable: 
+       - Add additional features from Skylars project
+       - Maybe only keep paulistrings and not full hamiltonian types
+"""
+
+
+
+[docs] +class BackendCircuit(): + """ + Base class for circuits compiled to run on specific backends. + + Attributes + ---------- + no_translation: + set this attribute in the derived __init__ to prevent translation of abstract_circuits + needed for simulators that use native tequila types. + Default is false + abstract_circuit: + the tequila circuit from which the backend circuit is built. + circuit: + the compiled circuit in the backend language. + compiler_arguments: + dictionary of arguments for compilation needed for chosen backend. Overwritten by inheritors. + device: + instantiated device (or None) for executing circuits. + n_qubits: + the number of qubits this circuit operates on. + noise: + the NoiseModel applied to this circuit when sampled. + qubit_map: + the mapping from tequila qubits to the qubits of the backend circuit. + Dicationary with keys being integers that enumerate the abstract qubits of the abstract_circuit + and values being data-structures holding `number` and `instance` where number enumerates the + backend qubits and instance is the instance of a backend qubit + qubits: + a list of the qubits operated on by the circuit. + + Methods + ------- + create_circuit + generate a backend circuit from an abstract tequila circuit + check_device: + see if a given device is valid for the backend. + retrieve_device: + get an instance of or necessary informaton about a device, for emulation or use. + add_parametrized_gate + add a parametrized gate to a backend circuit. + add_basic_gate + add an unparametrized gate to a backend circuit. + add_measurement + add a measurement gate to a backend circuit. + initialize_circuit: + generate an empty circuit object for the backend. + update_variables: + overwrite the saved values of variables for backend execution. + simulate: + perform simulation, simulated sampling, or execute the circuit, e.g. with some hamiltonian for measurement. + sample_paulistring: + sample a circuit with one paulistring of a larger hamiltonian + sample: + sample a circuit, measuring an entire hamiltonian. + do_sample: + subroutine for sampling. must be overwritten by inheritors. + do_simulate: + subroutine for wavefunction simulation. must be overwritten by inheritors. + convert_measurements: + transform the result of simulation from the backend return type. + make_qubit_map: + create a dictionary to map the tequila qubit ordering to the backend qubits. + optimize_circuit: + use backend features to improve circuit depth. + extract_variables: + return a list of the variables in the abstract tequila circuit this backend circuit corresponds to. + """ + + # compiler instructions, override in backends + # try to reduce True statements as much as possible for new backends + compiler_arguments = { + "trotterized": True, + "swap": True, + "multitarget": True, + "controlled_rotation": True, + "generalized_rotation": True, + "exponential_pauli": True, + "controlled_exponential_pauli": True, + "phase": True, + "power": True, + "hadamard_power": True, + "controlled_power": True, + "controlled_phase": True, + "toffoli": True, + "phase_to_z": True, + "cc_max": True + } + + @property + def n_qubits(self) -> numbers.Integral: + return len(self.qubit_map) + + @property + def abstract_qubits(self) -> typing.Iterable[numbers.Integral]: + return tuple(list(self.qubit_map.keys())) + +
+[docs] + def qubit(self, abstract_qubit): + """ + Convenience. Gives back a qubit instance of the corresponding backend + Parameters + ---------- + abstract_qubit + the abstract tequila qubit + + Returns + ------- + instance of backend qubit + """ + return self.qubit_map[abstract_qubit].instance
+ + + def __init__(self, abstract_circuit: QCircuit, variables, noise=None, device=None, + qubit_map=None, optimize_circuit=True, *args, **kwargs): + """ + + Parameters + ---------- + abstract_circuit: QCircuit: + the circuit which is to be rendered in the backend language. + variables: + values for the variables of abstract_circuit + noise: optional: + noise to apply to abstract circuit. + device: optional: + device on which to sample (or emulate sampling) abstract circuit. + qubit_map: dictionary: + a qubit map which maps the abstract qubits in the abstract_circuit to the qubits on the backend + there is no need to initialize the corresponding backend types + the dictionary should simply be {int:int} (preferred) or {int:name} + if None the default will map to qubits 0 ... n_qubits -1 in the backend + optimize_circuit: bool: + whether or not to attempt backend depth optimization. Defaults to true. + args + kwargs + """ + + self._input_args = {"abstract_circuit": abstract_circuit, "variables": variables, "noise": noise, + "qubit_map": qubit_map, "optimize_circuits": optimize_circuit, "device": device, **kwargs} + + self.no_translation = False + self._variables = tuple(abstract_circuit.extract_variables()) + + compiler_arguments = self.compiler_arguments + if noise is not None: + compiler_arguments["cc_max"] = True + compiler_arguments["controlled_phase"] = True + compiler_arguments["controlled_rotation"] = True + compiler_arguments["hadamard_power"] = True + + # compile the abstract_circuit + c = compiler.CircuitCompiler(**compiler_arguments) + + if qubit_map is None: + qubit_map = {q: i for i, q in enumerate(abstract_circuit.qubits)} + elif not qubit_map == {q: i for i, q in enumerate(abstract_circuit.qubits)}: + warnings.warn("reveived custom qubit_map = {}\n" + "This is not fully integrated and might result in unexpected behaviour!" + .format(qubit_map), TequilaWarning) + + if len(qubit_map) > abstract_circuit.max_qubit()+1: + raise TequilaException("Custom qubit_map has too many qubits {} vs {}".format(len(qubit_map), abstract_circuit.max_qubit()+1)) + if max(qubit_map.keys()) > abstract_circuit.max_qubit(): + raise TequilaException("Custom qubit_map tries to assign qubit {} but we only have {}".format(max(qubit_map.keys()), abstract_circuit.max_qubit())) + + # qubit map is initialized to have BackendQubits as values (they carry number and instance attributes) + self.qubit_map = self.make_qubit_map(qubit_map) + + # pre-compilation (still an abstract ciruit, but with gates decomposed depending on backend requirements) + compiled = c(abstract_circuit) + self.abstract_circuit = compiled + + self.noise = noise + self.check_device(device) + self.device = self.retrieve_device(device) + + # translate into the backend object + self.circuit = self.create_circuit(abstract_circuit=compiled, variables=variables) + + if optimize_circuit and noise is None: + self.circuit = self.optimize_circuit(circuit=self.circuit) + + def __call__(self, + variables: typing.Dict[Variable, numbers.Real] = None, + samples: int = None, + *args, + **kwargs): + """ + Simulate or sample the backend circuit. + + Parameters + ---------- + variables: dict: + dictionary assigning values to the variables of the circuit. + samples: int, optional: + how many shots to sample with. If None, perform full wavefunction simulation. + args + kwargs + + Returns + ------- + Float: + the result of simulating or sampling the circuit. + """ + + variables = format_variable_dictionary(variables=variables) + if self._variables is not None and len(self._variables) > 0: + if variables is None or set(self._variables) > set(variables.keys()): + raise TequilaException( + "BackendCircuit received not all variables. Circuit depends on variables {}, you gave {}".format( + self._variables, variables)) + + self.update_variables(variables) + if samples is None: + return self.simulate(variables=variables, noise=self.noise, *args, **kwargs) + else: + return self.sample(variables=variables, samples=samples, noise=self.noise, *args, **kwargs) + +
+[docs] + def create_circuit(self, abstract_circuit: QCircuit, circuit=None, *args, **kwargs): + """ + build the backend specific circuit from the abstract tequila circuit. + + Parameters + ---------- + abstract_circuit: QCircuit: + the circuit to build in the backend + circuit: BackendCircuitType (optional): + Add to this already initialized circuit (not all backends support + operation) + args + kwargs + + Returns + ------- + type varies + The circuit, compiled to the backend. + """ + + # Backend uses native tequila structures + if self.no_translation: + return abstract_circuit + + result = circuit + if result is None: + result = self.initialize_circuit(*args, **kwargs) + + for g in abstract_circuit.gates: + if g.is_parametrized(): + self.add_parametrized_gate(g, result, *args, **kwargs) + else: + self.add_basic_gate(g, result, *args, **kwargs) + + return result
+ + +
+[docs] + def check_device(self, device): + """ + Verify if a device can be used in the selected backend. Overwritten by inheritors. + Parameters + ---------- + device: + the device to verify. + + Returns + ------- + + Raises + ------ + TequilaException + """ + if device is not None: + raise TequilaException('Devices not enabled for {}'.format(str(type(self))))
+ + +
+[docs] + def retrieve_device(self, device): + """ + get the instantiated backend device object, from user provided object (e.g, a string). + + Must be overwritten by inheritors, to use devices. + + Parameters + ---------- + device: + object which points to the device in question, to be returned. + + Returns + ------- + Type: + varies by backend. + """ + if device is None: + return device + else: + raise TequilaException('Devices not enabled for {}'.format(str(type(self))))
+ + +
+[docs] + def add_parametrized_gate(self, gate, circuit, *args, **kwargs): + raise TequilaException("Backend Handler needs to be overwritten for supported simulators")
+ + +
+[docs] + def add_basic_gate(self, gate, circuit, *args, **kwargs): + raise TequilaException("Backend Handler needs to be overwritten for supported simulators")
+ + +
+[docs] + def add_measurement(self, circuit, target_qubits, *args, **kwargs): + raise TequilaException("Backend Handler needs to be overwritten for supported simulators")
+ + +
+[docs] + def initialize_circuit(self, *args, **kwargs): + raise TequilaException("Backend Handler needs to be overwritten for supported simulators")
+ + +
+[docs] + def update_variables(self, variables): + """ + This is the default, which just translates the circuit again. + Overwrite in inheritors if parametrized circuits are supported. + """ + self.circuit = self.create_circuit(abstract_circuit=self.abstract_circuit, variables=variables)
+ + +
+[docs] + def simulate(self, variables, initial_state=0, *args, **kwargs) -> QubitWaveFunction: + """ + simulate the circuit via the backend. + + Parameters + ---------- + variables: + the parameters with which to simulate the circuit. + initial_state: Default = 0: + one of several types; determines the base state onto which the circuit is applied. + Default: the circuit is applied to the all-zero state. + args + kwargs + + Returns + ------- + QubitWaveFunction: + the wavefunction of the system produced by the action of the circuit on the initial state. + + """ + self.update_variables(variables) + if isinstance(initial_state, BitString): + initial_state = initial_state.integer + if isinstance(initial_state, QubitWaveFunction): + if len(initial_state.keys()) != 1: + raise TequilaException("only product states as initial states accepted") + initial_state = list(initial_state.keys())[0].integer + + all_qubits = list(range(self.abstract_circuit.n_qubits)) + active_qubits = self.qubit_map.keys() + + # Keymap is only necessary if not all qubits are active + keymap_required = sorted(active_qubits) != all_qubits + + if keymap_required: + # maps from reduced register to full register + keymap = KeyMapSubregisterToRegister(subregister=active_qubits, register=all_qubits) + + mapped_initial_state = keymap.inverted(initial_state).integer if keymap_required else int(initial_state) + result = self.do_simulate(variables=variables, initial_state=mapped_initial_state, *args, + **kwargs) + + if keymap_required: + result.apply_keymap(keymap=keymap, initial_state=initial_state) + + return result
+ + +
+[docs] + def sample(self, variables, samples, read_out_qubits=None, circuit=None, *args, **kwargs): + """ + Sample the circuit. If circuit natively equips paulistrings, sample therefrom. + Parameters + ---------- + variables: + the variables with which to sample the circuit. + samples: int: + the number of samples to take. + read_out_qubits: int: + target qubits to measure (default is all) + args + kwargs + + Returns + ------- + QubitWaveFunction + The result of sampling, a recreated QubitWaveFunction in the sampled basis. + + """ + self.update_variables(variables) + if read_out_qubits is None: + read_out_qubits = self.abstract_qubits + + if len(read_out_qubits) == 0: + raise Exception("read_out_qubits are empty") + + if circuit is None: + circuit = self.add_measurement(circuit=self.circuit, target_qubits=read_out_qubits) + else: + circuit = self.add_measurement(circuit=circuit, target_qubits=read_out_qubits) + return self.do_sample(samples=samples, circuit=circuit, read_out_qubits=read_out_qubits, *args, **kwargs)
+ + +
+[docs] + def sample_all_z_hamiltonian(self, samples: int, hamiltonian, variables, *args, **kwargs): + """ + Sample from a Hamiltonian which only consists of Pauli-Z and unit operators + Parameters + ---------- + samples + number of samples to take + hamiltonian + the tequila hamiltonian + args + arguments for do_sample + kwargs + keyword arguments for do_sample + Returns + ------- + samples, evaluated and summed Hamiltonian expectationvalue + """ + # make measurement instruction (measure all qubits in the Hamiltonian that are also in the circuit) + abstract_qubits_H = hamiltonian.qubits + assert len(abstract_qubits_H) != 0 # this case should be filtered out before + # assert that the Hamiltonian was mapped before + if not all(q in self.qubit_map.keys() for q in abstract_qubits_H): + raise TequilaException( + "Qubits in {}-qubit Hamiltonian were not traced out for {}-qubit circuit".format(hamiltonian.n_qubits, + self.n_qubits)) + + # run simulators + counts = self.sample(samples=samples, read_out_qubits=abstract_qubits_H, variables=variables, *args, **kwargs) + read_out_map = {q: i for i, q in enumerate(abstract_qubits_H)} + + # compute energy + E = 0.0 + for paulistring in hamiltonian.paulistrings: + n_samples = 0 + Etmp = 0.0 + for key, count in counts.items(): + # get all the non-trivial qubits of the current PauliString (meaning all Z operators) + # and mapp them to the backend qubits + mapped_ps_support = [read_out_map[i] for i in paulistring._data.keys()] + # count all measurements that resulted in |1> for those qubits + parity = [k for i, k in enumerate(key.array) if i in mapped_ps_support].count(1) + # evaluate the PauliString + sign = (-1) ** parity + Etmp += sign * count + n_samples += count + E += (Etmp / samples) * paulistring.coeff + # small failsafe + assert n_samples == samples + return E
+ + +
+[docs] + def sample_paulistring(self, samples: int, paulistring, variables, *args, + **kwargs) -> numbers.Real: + """ + Sample an individual pauli word (pauli string) and return the average result thereof. + Parameters + ---------- + samples: int: + how many samples to evaluate. + paulistring: + the paulistring to be sampled. + args + kwargs + + Returns + ------- + float: + the average result of sampling the chosen paulistring + """ + + not_in_u = [q for q in paulistring.qubits if q not in self.abstract_qubits] + reduced_ps = paulistring.trace_out_qubits(qubits=not_in_u) + if reduced_ps.coeff == 0.0: + return 0.0 + if len(reduced_ps._data.keys()) == 0: + return reduced_ps.coeff + + # make basis change and translate to backend + basis_change = QCircuit() + qubits = [] + for idx, p in reduced_ps.items(): + qubits.append(idx) + basis_change += change_basis(target=idx, axis=p) + + # add basis change to the circuit + # deepcopy is necessary to avoid changing the circuits + # can be circumvented by optimizing the measurements + # on construction: tq.ExpectationValue(H=H, U=U, optimize_measurements=True) + circuit = self.create_circuit(circuit=copy.deepcopy(self.circuit), abstract_circuit=basis_change) + # run simulators + counts = self.sample(samples=samples, circuit=circuit, read_out_qubits=qubits, variables=variables, *args, + **kwargs) + # compute energy + E = 0.0 + n_samples = 0 + for key, count in counts.items(): + parity = key.array.count(1) + sign = (-1) ** parity + E += sign * count + n_samples += count + assert n_samples == samples + E = E / samples * paulistring.coeff + return E
+ + +
+[docs] + def do_sample(self, samples, circuit, noise, abstract_qubits=None, *args, **kwargs) -> QubitWaveFunction: + """ + helper function for sampling. MUST be overwritten by inheritors. + + Parameters + ---------- + samples: int: + the number of samples to take + circuit: + the circuit to sample from. + Note: + Not necessarily self.circuit! + noise: + the noise to apply to the sampled circuit. + abstract_qubits: + specify which qubits to measure. Default is all + args + kwargs + + Returns + ------- + QubitWaveFunction: + the result of sampling. + + """ + raise TequilaException("Backend Handler needs to be overwritten for supported simulators")
+ + +
+[docs] + def do_simulate(self, variables, initial_state, *args, **kwargs) -> QubitWaveFunction: + """ + helper for simulation. MUST be overwritten by inheritors. + + Parameters + ---------- + variables: + the variables with which the circuit may be simulated. + initial_state: + the initial state in which the system is in prior to the application of the circuit. + args + kwargs + + Returns + ------- + QubitWaveFunction + the result of simulating the circuit. + + """ + raise TequilaException("Backend Handler needs to be overwritten for supported simulators")
+ + +
+[docs] + def convert_measurements(self, backend_result) -> QubitWaveFunction: + raise TequilaException("Backend Handler needs to be overwritten for supported simulators")
+ + +
+[docs] + def initialize_qubit(self, number: int): + """ + + In case the backend has its own Qubit Types, + this function should be overwritten by inheritors. + + Parameters + ---------- + number + the qubit number + + Returns + ------- + Initialized backend qubit type + + """ + return number
+ + +
+[docs] + def make_qubit_map(self, qubits: dict): + """ + Build the mapping between abstract qubits. + + Must be overwritten by inheritors to do anything other than check the validity of the map. + Parameters + ---------- + qubits: + the qubits to map onto. + If given as a dictionary, the map is already defined + If given as a list the map will be those qubits mapped to 0 .... n_qubit-1 of the backend + Returns + ------- + Dict + the dictionary that maps the qubits of the abstract circuits to an ordered sequence of integers. + keys are the abstract qubit integers + values are the backend qubits + those are data structures which contain name and instance + where number is the qubit identifier and instance the instance of the backend qubit + if the backend does not require a special object for qubits the instance should be the same as number + """ + + @dataclass + class BackendQubit: + number: int = None + instance: object = None + + if qubits is None: + qubits = range(self.abstract_circuit.n_qubits) + + abstract_map = qubits + if not hasattr(qubits, "keys") or not hasattr(qubits, "values"): + abstract_map = {q: i for i, q in enumerate(qubits)} + + if all([hasattr(i, "number") and hasattr(i, "instance") for i in abstract_map.values()]): + # qubit_map already initialized backend_types + return qubits + + return {k: BackendQubit(number=v, instance=self.initialize_qubit(v)) for k, v in abstract_map.items()}
+ + +
+[docs] + def optimize_circuit(self, circuit, *args, **kwargs): + """ + Optimize a circuit using backend tools. Should be overwritten by inheritors. + Parameters + ---------- + circuit: + the circuit to optimize + args + kwargs + + Returns + ------- + Type + Optimized version of the circuit. + """ + return circuit
+ + +
+[docs] + def extract_variables(self) -> typing.Dict[str, numbers.Real]: + """ + extract the tequila variables from the circuit. + Returns + ------- + dict: + the variables of the circuit. + """ + result = self.abstract_circuit.extract_variables() + return result
+ + + @staticmethod + def _name_variable_objective(objective): + """ + Name variables in backend consistently for easier readout + """ + variables = objective.extract_variables() + if len(variables) == 0: + if hasattr(variables[0], "transformation"): + return str("f({})".format(variables[0])) + else: + return str(variables[0]) + else: + variables = tuple(variables) + return "f({})".format(variables) + + def __copy__(self): + return self.__deepcopy__() + + def __deepcopy__(self, memodict={}): + return type(self)(**self._input_args)
+ + + +
+[docs] +class BackendExpectationValue: + """ + Class representing an ExpectationValue for evaluation by some backend. + + Attributes + ---------- + H: + the reduced tequila Hamiltonian(s) of the expectationvalue + reduction procedure is tracing out all qubits that are not part of the unitary U + stored as a tuple to evaluate multiple Hamiltonians over the same circuit faster in pure simulations + abstract_H: + the original (non-reduced) Hamiltonian(s) + n_qubits: + how many qubits appear in the expectationvalue. + U: + the underlying BackendCircuit of the expectationvalue. + + Methods + ------- + extract_variables: + return the underlying tequila variables of the circuit + initialize_hamiltonian + prepare the hamiltonian for iteration over as a tuple + initialize_unitary + compile the abstract circuit to a backend circuit. + simulate: + simulate the unitary to measure H + sample: + sample the unitary to measure H + sample_paulistring + sample a single term from H + update_variables + wrapper over the update_variables of BackendCircuit. + + """ + BackendCircuitType = BackendCircuit + + # map to smaller subsystem if there are qubits which are not touched by the circuits, + # should be deactivated if expectationvalues are computed by the backend since the hamiltonians are currently not mapped + use_mapping = True + + @property + def n_qubits(self): + return self.U.n_qubits + + @property + def H(self): + return self._H + + @property + def U(self): + return self._U + +
+[docs] + def count_measurements(self): + return self.abstract_expectationvalue.count_measurements()
+ + +
+[docs] + def extract_variables(self) -> typing.Dict[str, numbers.Real]: + """ + wrapper over circuit extract variables + Returns + ------- + Dict + Todo: is it really a dict? + """ + result = [] + if self.U is not None: + result = self.U.extract_variables() + return result
+ + + def __init__(self, E, variables, noise, device, *args, **kwargs): + """ + + Parameters + ---------- + E: + the uncompiled expectationvalue + variables: + variables for compilation of circuit + noise: + noisemodel for compilation of circuit + device: + device for compilation of circuit + """ + self.abstract_expectationvalue = E + self._input_args = {"variables": variables, "device": device, "noise": noise, **kwargs} + self._U = self.initialize_unitary(E.U, variables=variables, noise=noise, device=device, **kwargs) + self._reduced_hamiltonians = self.reduce_hamiltonians(self.abstract_expectationvalue.H) + self._H = self.initialize_hamiltonian(self._reduced_hamiltonians) + + self._variables = E.extract_variables() + self._contraction = E._contraction + self._shape = E._shape + + def __copy__(self): + return self.__deepcopy__() + + def __deepcopy__(self, memodict={}): + return type(self)(self.abstract_expectationvalue, **self._input_args) + + def __call__(self, variables, samples: int = None, *args, **kwargs): + + variables = format_variable_dictionary(variables=variables) + if self._variables is not None and len(self._variables) > 0: + if variables is None or (not set(self._variables) <= set(variables.keys())): + raise TequilaException( + "BackendExpectationValue received not all variables. Circuit depends on variables {}, you gave {}".format( + self._variables, variables)) + + if samples is None: + data = self.simulate(variables=variables, *args, **kwargs) + else: + data = self.sample(variables=variables, samples=samples, *args, **kwargs) + + if self._shape is None and self._contraction is None: + # this is the default + return numpy.sum(data) + + if self._shape is not None: + data = data.reshape(self._shape) + else: + data = float(data) + if self._contraction is None: + return data + else: + return self._contraction(data) + +
+[docs] + def reduce_hamiltonians(self, abstract_hamiltonians: tuple) -> tuple: + """ + + Parameters + ---------- + abstract_hamiltonians + tuple of abstract tequila Hamiltonians + Returns + ------- + reduces Hamiltonians where the qubits that are not defined in self.U are traced out + """ + abstract_qubits_of_u = self.U.qubit_map.keys() + reduced = [] + for H in abstract_hamiltonians: + abstract_qubits_of_h = H.qubits + not_in_u = [q for q in abstract_qubits_of_h if q not in abstract_qubits_of_u] + reduced.append(H.trace_out_qubits(qubits=not_in_u)) + + return tuple(reduced)
+ + +
+[docs] + def initialize_hamiltonian(self, hamiltonians: tuple) -> tuple: + return hamiltonians
+ + +
+[docs] + def initialize_unitary(self, U, variables, noise, device, *args, **kwargs): + """return a compiled unitary""" + return self.BackendCircuitType(abstract_circuit=U, variables=variables, device=device, + use_mapping=self.use_mapping, + noise=noise, *args, **kwargs)
+ + +
+[docs] + def update_variables(self, variables): + """wrapper over circuit update_variables""" + self._U.update_variables(variables=variables)
+ + +
+[docs] + def sample(self, variables, samples, *args, **kwargs) -> numpy.array: + """ + sample the expectationvalue. + + Parameters + ---------- + variables: dict: + variables to supply to the unitary. + samples: int: + number of samples to perform. + args + kwargs + + Returns + ------- + numpy.ndarray: + a numpy array, the result of sampling. + """ + + suggested = None + if hasattr(samples, "lower") and samples.lower()[:4] == "auto": + if self.abstract_expectationvalue.samples is None: + raise TequilaException("samples='auto' requested but no samples where set in individual expectation values") + total_samples = int(samples[5:]) + samples = max(1, int(self.abstract_expectationvalue.samples * total_samples)) + suggested = samples + # samples are not necessarily set (either the user has to set it or some functions like optimize_measurements) + + if suggested is not None and suggested != samples: + warnings.warn("simulating with samples={}, but expectationvalue carries suggested samples={}\nTry calling with samples='auto-total#ofsamples'".format(samples, suggested), TequilaWarning) + + self.update_variables(variables) + + result = [] + for H in self._reduced_hamiltonians: + E = 0.0 + if len(H.qubits) == 0: + E = sum([ps.coeff for ps in H.paulistrings]) + elif H.is_all_z(): + E = self.U.sample_all_z_hamiltonian(samples=samples, hamiltonian=H, variables=variables, *args, + **kwargs) + else: + for ps in H.paulistrings: + E += self.U.sample_paulistring(samples=samples, paulistring=ps, variables=variables, *args, + **kwargs) + result.append(to_float(E)) + return numpy.asarray(result)
+ + +
+[docs] + def simulate(self, variables, *args, **kwargs): + """ + Simulate the expectationvalue. + + Parameters + ---------- + variables: + variables to supply to the unitary. + args + kwargs + + Returns + ------- + numpy array: + the result of simulation. + """ + self.update_variables(variables) + result = [] + for H in self.H: + final_E = 0.0 + # TODO inefficient, + # Always better to overwrite this function + wfn = self.U.simulate(variables=variables, *args, **kwargs) + final_E += wfn.compute_expectationvalue(operator=H) + result.append(to_float(final_E)) + return numpy.asarray(result)
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/simulators/simulator_qulacs.html b/docs/sphinx/_modules/tequila_code/simulators/simulator_qulacs.html new file mode 100644 index 0000000..4fc5846 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/simulators/simulator_qulacs.html @@ -0,0 +1,704 @@ + + + + + + + + tequila_code.simulators.simulator_qulacs — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for tequila_code.simulators.simulator_qulacs

+import qulacs
+import numbers, numpy
+import warnings
+
+from tequila import TequilaException, TequilaWarning
+from tequila.utils.bitstrings import BitNumbering, BitString, BitStringLSB
+from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
+from tequila.simulators.simulator_base import BackendCircuit, BackendExpectationValue, QCircuit, change_basis
+from tequila.utils.keymap import KeyMapRegisterToSubregister
+
+"""
+Developer Note:
+    Qulacs uses different Rotational Gate conventions: Rx(angle) = exp(i angle/2 X) instead of exp(-i angle/2 X)
+    And the same for MultiPauli rotational gates
+    The angles are scaled with -1.0 to keep things consistent with the rest of tequila
+"""
+
+
+[docs] +class TequilaQulacsException(TequilaException): + def __str__(self): + return "Error in qulacs backend:" + self.message
+ + +
+[docs] +class BackendCircuitQulacs(BackendCircuit): + """ + Class representing circuits compiled to qulacs. + See BackendCircuit for documentation of features and methods inherited therefrom + + Attributes + ---------- + counter: + counts how many distinct sympy.Symbol objects are employed in the circuit. + has_noise: + whether or not the circuit is noisy. needed by the expectationvalue to do sampling properly. + noise_lookup: dict: + dict mapping strings to lists of constructors for cirq noise channel objects. + op_lookup: dict: + dictionary mapping strings (tequila gate names) to cirq.ops objects. + variables: list: + a list of the qulacs variables of the circuit. + + Methods + ------- + add_noise_to_circuit: + apply a tequila NoiseModel to a qulacs circuit, by translating the NoiseModel's instructions into noise gates. + """ + + compiler_arguments = { + "trotterized": True, + "swap": False, + "multitarget": True, + "controlled_rotation": True, # needed for gates depending on variables + "generalized_rotation": True, + "exponential_pauli": False, + "controlled_exponential_pauli": True, + "phase": True, + "power": True, + "hadamard_power": True, + "controlled_power": True, + "controlled_phase": True, + "toffoli": False, + "phase_to_z": True, + "cc_max": False + } + + numbering = BitNumbering.LSB + + def __init__(self, abstract_circuit, noise=None, *args, **kwargs): + """ + + Parameters + ---------- + abstract_circuit: QCircuit: + the circuit to compile to qulacs + noise: optional: + noise to apply to the circuit. + args + kwargs + """ + self.op_lookup = { + 'I': qulacs.gate.Identity, + 'X': qulacs.gate.X, + 'Y': qulacs.gate.Y, + 'Z': qulacs.gate.Z, + 'H': qulacs.gate.H, + 'Rx': (lambda c: c.add_parametric_RX_gate, qulacs.gate.RX), + 'Ry': (lambda c: c.add_parametric_RY_gate, qulacs.gate.RY), + 'Rz': (lambda c: c.add_parametric_RZ_gate, qulacs.gate.RZ), + 'SWAP': qulacs.gate.SWAP, + 'Measure': qulacs.gate.Measurement, + 'Exp-Pauli': None + } + self.measurements = None + self.variables = [] + super().__init__(abstract_circuit=abstract_circuit, noise=noise, *args, **kwargs) + self.has_noise=False + if noise is not None: + + warnings.warn("Warning: noise in qulacs module will be dropped. Currently only works for qulacs version 0.5 or lower", TequilaWarning) + + self.has_noise=True + self.noise_lookup = { + 'bit flip': [qulacs.gate.BitFlipNoise], + 'phase flip': [lambda target, prob: qulacs.gate.Probabilistic([prob],[qulacs.gate.Z(target)])], + 'phase damp': [lambda target, prob: qulacs.gate.DephasingNoise(target,(1/2)*(1-numpy.sqrt(1-prob)))], + 'amplitude damp': [qulacs.gate.AmplitudeDampingNoise], + 'phase-amplitude damp': [qulacs.gate.AmplitudeDampingNoise, + lambda target, prob: qulacs.gate.DephasingNoise(target,(1/2)*(1-numpy.sqrt(1-prob))) + ], + 'depolarizing': [lambda target,prob: qulacs.gate.DepolarizingNoise(target,3*prob/4)] + } + + self.circuit=self.add_noise_to_circuit(noise) + +
+[docs] + def initialize_state(self, n_qubits:int=None) -> qulacs.QuantumState: + if n_qubits is None: + n_qubits = self.n_qubits + return qulacs.QuantumState(n_qubits)
+ + +
+[docs] + def update_variables(self, variables): + """ + set new variable values for the circuit. + Parameters + ---------- + variables: dict: + the variables to supply to the circuit. + + Returns + ------- + None + """ + for k, angle in enumerate(self.variables): + self.circuit.set_parameter(k, angle(variables))
+ + +
+[docs] + def do_simulate(self, variables, initial_state, *args, **kwargs): + """ + Helper function to perform simulation. + + Parameters + ---------- + variables: dict: + variables to supply to the circuit. + initial_state: + information indicating the initial state on which the circuit should act. + args + kwargs + + Returns + ------- + QubitWaveFunction: + QubitWaveFunction representing result of the simulation. + """ + state = self.initialize_state(self.n_qubits) + lsb = BitStringLSB.from_int(initial_state, nbits=self.n_qubits) + state.set_computational_basis(BitString.from_binary(lsb.binary).integer) + self.circuit.update_quantum_state(state) + + wfn = QubitWaveFunction.from_array(arr=state.get_vector(), numbering=self.numbering) + return wfn
+ + +
+[docs] + def convert_measurements(self, backend_result, target_qubits=None) -> QubitWaveFunction: + """ + Transform backend evaluation results into QubitWaveFunction + Parameters + ---------- + backend_result: + the return value of backend simulation. + + Returns + ------- + QubitWaveFunction + results transformed to tequila native QubitWaveFunction + """ + + result = QubitWaveFunction() + # todo there are faster ways + + + for k in backend_result: + converted_key = BitString.from_binary(BitStringLSB.from_int(integer=k, nbits=self.n_qubits).binary) + if converted_key in result._state: + result._state[converted_key] += 1 + else: + result._state[converted_key] = 1 + + if target_qubits is not None: + mapped_target = [self.qubit_map[q].number for q in target_qubits] + mapped_full = [self.qubit_map[q].number for q in self.abstract_qubits] + keymap = KeyMapRegisterToSubregister(subregister=mapped_target, register=mapped_full) + result = result.apply_keymap(keymap=keymap) + + return result
+ + +
+[docs] + def do_sample(self, samples, circuit, noise_model=None, initial_state=0, *args, **kwargs) -> QubitWaveFunction: + """ + Helper function for performing sampling. + + Parameters + ---------- + samples: int: + the number of samples to be taken. + circuit: + the circuit to sample from. + noise_model: optional: + noise model to be applied to the circuit. + initial_state: + sampling supports initial states for qulacs. Indicates the initial state to which circuit is applied. + args + kwargs + + Returns + ------- + QubitWaveFunction: + the results of sampling, as a Qubit Wave Function. + """ + state = self.initialize_state(self.n_qubits) + lsb = BitStringLSB.from_int(initial_state, nbits=self.n_qubits) + state.set_computational_basis(BitString.from_binary(lsb.binary).integer) + circuit.update_quantum_state(state) + sampled = state.sampling(samples) + return self.convert_measurements(backend_result=sampled, target_qubits=self.measurements)
+ + +
+[docs] + def no_translation(self, abstract_circuit): + """ + Todo: what is this for? + Parameters + ---------- + abstract_circuit + + Returns + ------- + + """ + return False
+ + +
+[docs] + def initialize_circuit(self, *args, **kwargs): + """ + return an empty circuit. + Parameters + ---------- + args + kwargs + + Returns + ------- + qulacs.ParametricQuantumCircuit + """ + return qulacs.ParametricQuantumCircuit(self.n_qubits)
+ + +
+[docs] + def add_exponential_pauli_gate(self, gate, circuit, variables, *args, **kwargs): + """ + Add a native qulacs Exponential Pauli gate to a circuit. + Parameters + ---------- + gate: ExpPauliGateImpl: + the gate to add + circuit: + the qulacs circuit, to which the gate is to be added. + variables: + dict containing values of the parameters appearing in the pauli gate. + args + kwargs + + Returns + ------- + None + """ + assert not gate.is_controlled() + convert = {'x': 1, 'y': 2, 'z': 3} + pind = [convert[x.lower()] for x in gate.paulistring.values()] + qind = [self.qubit(x) for x in gate.paulistring.keys()] + if len(gate.extract_variables()) > 0: + self.variables.append(-gate.parameter * gate.paulistring.coeff) + circuit.add_parametric_multi_Pauli_rotation_gate(qind, pind, + -gate.parameter(variables) * gate.paulistring.coeff) + else: + circuit.add_multi_Pauli_rotation_gate(qind, pind, -gate.parameter(variables) * gate.paulistring.coeff)
+ + +
+[docs] + def add_parametrized_gate(self, gate, circuit, variables, *args, **kwargs): + """ + add a parametrized gate. + Parameters + ---------- + gate: QGateImpl: + the gate to add to the circuit. + circuit: + the circuit to which the gate is to be added + variables: + dict that tells values of variables; needed IFF the gate is an ExpPauli gate. + args + kwargs + + Returns + ------- + None + """ + op = self.op_lookup[gate.name] + if gate.name == 'Exp-Pauli': + self.add_exponential_pauli_gate(gate, circuit, variables) + return + else: + if len(gate.extract_variables()) > 0: + op = op[0] + self.variables.append(-gate.parameter) + op(circuit)(self.qubit(gate.target[0]), -gate.parameter(variables=variables)) + if gate.is_controlled(): + raise TequilaQulacsException("Gates which depend on variables can not be controlled! Gate was:\n{}".format(gate)) + return + else: + op = op[1] + qulacs_gate = op(self.qubit(gate.target[0]), -gate.parameter(variables=variables)) + if gate.is_controlled(): + qulacs_gate = qulacs.gate.to_matrix_gate(qulacs_gate) + for c in gate.control: + qulacs_gate.add_control_qubit(self.qubit(c), 1) + circuit.add_gate(qulacs_gate)
+ + +
+[docs] + def add_basic_gate(self, gate, circuit, *args, **kwargs): + """ + add an unparametrized gate to the circuit. + Parameters + ---------- + gate: QGateImpl: + the gate to be added to the circuit. + circuit: + the circuit, to which a gate is to be added. + args + kwargs + + Returns + ------- + None + """ + op = self.op_lookup[gate.name] + qulacs_gate = op(*[self.qubit(t) for t in gate.target]) + if gate.is_controlled(): + qulacs_gate = qulacs.gate.to_matrix_gate(qulacs_gate) + for c in gate.control: + qulacs_gate.add_control_qubit(self.qubit(c), 1) + + circuit.add_gate(qulacs_gate)
+ + +
+[docs] + def add_measurement(self, circuit, target_qubits, *args, **kwargs): + """ + Add a measurement operation to a circuit. + Parameters + ---------- + circuit: + a circuit, to which the measurement is to be added. + target_qubits: List[int] + abstract target qubits + args + kwargs + + Returns + ------- + None + """ + self.measurements = sorted(target_qubits) + return circuit
+ + + +
+[docs] + def add_noise_to_circuit(self,noise_model): + """ + Apply noise from a NoiseModel to a circuit. + Parameters + ---------- + noise_model: NoiseModel: + the noisemodel to apply to the circuit. + + Returns + ------- + qulacs.ParametrizedQuantumCircuit: + self.circuit, with noise added on. + """ + c=self.circuit + n=noise_model + g_count=c.get_gate_count() + new=self.initialize_circuit() + for i in range(g_count): + g=c.get_gate(i) + new.add_gate(g) + qubits=g.get_target_index_list() + g.get_control_index_list() + for noise in n.noises: + if len(qubits) == noise.level: + for j,channel in enumerate(self.noise_lookup[noise.name]): + for q in qubits: + chan=channel(q,noise.probs[j]) + new.add_gate(chan) + return new
+ + +
+[docs] + def optimize_circuit(self, circuit, max_block_size: int = 4, silent: bool = True, *args, **kwargs): + """ + reduce circuit depth using the native qulacs optimizer. + Parameters + ---------- + circuit + max_block_size: int: Default = 4: + the maximum block size for use by the qulacs internal optimizer. + silent: bool: + whether or not to print the resullt of having optimized. + args + kwargs + + Returns + ------- + qulacs.QuantumCircuit: + optimized qulacs circuit. + + """ + old = circuit.calculate_depth() + opt = qulacs.circuit.QuantumCircuitOptimizer() + opt.optimize(circuit, max_block_size) + if not silent: + print("qulacs: optimized circuit depth from {} to {} with max_block_size {}".format(old, + circuit.calculate_depth(), + max_block_size)) + return circuit
+
+ + +
+[docs] +class BackendExpectationValueQulacs(BackendExpectationValue): + """ + Class representing Expectation Values compiled for Qulacs. + + Ovverrides some methods of BackendExpectationValue, which should be seen for details. + """ + use_mapping = True + BackendCircuitType = BackendCircuitQulacs + +
+[docs] + def simulate(self, variables, *args, **kwargs) -> numpy.array: + """ + Perform simulation of this expectationvalue. + Parameters + ---------- + variables: + variables, to be supplied to the underlying circuit. + args + kwargs + + Returns + ------- + numpy.array: + the result of simulation as an array. + """ + # fast return if possible + if self.H is None: + return numpy.asarray([0.0]) + elif len(self.H) == 0: + return numpy.asarray([0.0]) + elif isinstance(self.H, numbers.Number): + return numpy.asarray[self.H] + + self.U.update_variables(variables) + state = self.U.initialize_state(self.n_qubits) + self.U.circuit.update_quantum_state(state) + result = [] + for H in self.H: + if isinstance(H, numbers.Number): + result.append(H) # those are accumulated unit strings, e.g 0.1*X(3) in wfn on qubits 0,1 + else: + result.append(H.get_expectation_value(state)) + + return numpy.asarray(result)
+ + +
+[docs] + def initialize_hamiltonian(self, hamiltonians): + """ + Convert reduced hamiltonians to native Qulacs types for efficient expectation value evaluation. + Parameters + ---------- + hamiltonians: + an interable set of hamiltonian objects. + + Returns + ------- + list: + initialized hamiltonian objects. + + """ + + # map the reduced operators to the potentially smaller qubit system + qubit_map = {} + for i,q in enumerate(self.U.abstract_circuit.qubits): + qubit_map[q] = i + + result = [] + for H in hamiltonians: + qulacs_H = qulacs.Observable(self.n_qubits) + for ps in H.paulistrings: + string = "" + for k, v in ps.items(): + string += v.upper() + " " + str(qubit_map[k]) + qulacs_H.add_operator(ps.coeff, string) + result.append(qulacs_H) + return result
+ + +
+[docs] + def sample(self, variables, samples, *args, **kwargs) -> numpy.array: + """ + Sample this Expectation Value. + Parameters + ---------- + variables: + variables, to supply to the underlying circuit. + samples: int: + the number of samples to take. + args + kwargs + + Returns + ------- + numpy.ndarray: + the result of sampling as a number. + """ + self.update_variables(variables) + state = self.U.initialize_state(self.n_qubits) + self.U.circuit.update_quantum_state(state) + result = [] + for H in self._reduced_hamiltonians: # those are the hamiltonians which where non-used qubits are already traced out + E = 0.0 + if H.is_all_z() and not self.U.has_noise: + E = super().sample(samples=samples, variables=variables, *args, **kwargs) + else: + for ps in H.paulistrings: + # change basis, measurement is destructive so the state will be copied + # to avoid recomputation (except when noise was required) + bc = QCircuit() + for idx, p in ps.items(): + bc += change_basis(target=idx, axis=p) + qbc = self.U.create_circuit(abstract_circuit=bc, variables=None) + Esamples = [] + for sample in range(samples): + if self.U.has_noise and sample>0: + state = self.U.initialize_state(self.n_qubits) + self.U.circuit.update_quantum_state(state) + state_tmp = state + else: + state_tmp = state.copy() + if len(bc.gates) > 0: # otherwise there is no basis change (empty qulacs circuit does not work out) + qbc.update_quantum_state(state_tmp) + ps_measure = 1.0 + for idx in ps.keys(): + assert idx in self.U.abstract_qubits # assert that the hamiltonian was really reduced + M = qulacs.gate.Measurement(self.U.qubit(idx), self.U.qubit(idx)) + M.update_quantum_state(state_tmp) + measured = state_tmp.get_classical_value(self.U.qubit(idx)) + ps_measure *= (-2.0 * measured + 1.0) # 0 becomes 1 and 1 becomes -1 + Esamples.append(ps_measure) + E += ps.coeff * sum(Esamples) / len(Esamples) + result.append(E) + return numpy.asarray(result)
+
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/simulators/simulator_qulacs_gpu.html b/docs/sphinx/_modules/tequila_code/simulators/simulator_qulacs_gpu.html new file mode 100644 index 0000000..6e2e510 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/simulators/simulator_qulacs_gpu.html @@ -0,0 +1,130 @@ + + + + + + + + tequila_code.simulators.simulator_qulacs_gpu — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for tequila_code.simulators.simulator_qulacs_gpu

+import qulacs
+from tequila import TequilaException
+from tequila.simulators.simulator_qulacs import BackendCircuitQulacs, BackendExpectationValueQulacs
+
+
+[docs] +class TequilaQulacsGpuException(TequilaException): + def __str__(self): + return "Error in qulacs gpu backend:" + self.message
+ + +
+[docs] +class BackendCircuitQulacsGpu(BackendCircuitQulacs): +
+[docs] + def initialize_state(self, n_qubits:int=None) -> qulacs.QuantumState: + if n_qubits is None: + n_qubits = self.n_qubits + return qulacs.QuantumStateGpu(n_qubits)
+
+ + +
+[docs] +class BackendExpectationValueQulacsGpu(BackendExpectationValueQulacs): + BackendCircuitType = BackendCircuitQulacsGpu + pass
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_modules/tequila_code/simulators/simulator_symbolic.html b/docs/sphinx/_modules/tequila_code/simulators/simulator_symbolic.html new file mode 100644 index 0000000..c282379 --- /dev/null +++ b/docs/sphinx/_modules/tequila_code/simulators/simulator_symbolic.html @@ -0,0 +1,263 @@ + + + + + + + + tequila_code.simulators.simulator_symbolic — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Source code for tequila_code.simulators.simulator_symbolic

+from tequila.simulators.simulator_base import BackendExpectationValue, BackendCircuit
+from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
+from tequila.circuit.circuit import QCircuit
+from tequila.circuit.gates import QGate
+from tequila import BitString
+import numpy
+import copy
+import sympy
+
+"""
+Simple Symbolic Simulator for debugging purposes
+"""
+
+
+[docs] +class BackendCircuitSymbolic(BackendCircuit): + + # compiler instructions + compiler_arguments = { + "trotterized": True, + "swap": True, + "multitarget": True, + "controlled_rotation": False, + "generalized_rotation": True, + "exponential_pauli": True, + "controlled_exponential_pauli": True, + "phase": True, + "power": True, + "hadamard_power": True, + "controlled_power": True, + "controlled_phase": True, + "toffoli": True, + "phase_to_z": True, + "cc_max": True + } + + convert_to_numpy = True + +
+[docs] + def create_circuit(self, abstract_circuit: QCircuit, variables=None): + return abstract_circuit
+ + +
+[docs] + def update_variables(self, variables): + pass
+ + +
+[docs] + @classmethod + def apply_gate(cls, state: QubitWaveFunction, gate: QGate, qubits: dict, variables) -> QubitWaveFunction: + result = QubitWaveFunction() + n_qubits = len(qubits.keys()) + for s, v in state.items(): + s.nbits = n_qubits + result += v * cls.apply_on_standard_basis(gate=gate, basisfunction=s, qubits=qubits, variables=variables) + return result
+ + +
+[docs] + @classmethod + def apply_on_standard_basis(cls, gate: QGate, basisfunction: BitString, qubits:dict, variables) -> QubitWaveFunction: + + basis_array = basisfunction.array + if gate.is_controlled(): + do_apply = True + check = [basis_array[qubits[c]] == 1 for c in gate.control] + for c in check: + if not c: + do_apply = False + if not do_apply: + return QubitWaveFunction.from_int(basisfunction) + + if len(gate.target) > 1: + raise Exception("Multi-targets not supported for symbolic simulators") + + result = QubitWaveFunction() + for tt in gate.target: + t = qubits[tt] + qt = basis_array[t] + a_array = copy.deepcopy(basis_array) + a_array[t] = (a_array[t] + 1) % 2 + current_state = QubitWaveFunction.from_int(basisfunction) + altered_state = QubitWaveFunction.from_int(BitString.from_array(a_array)) + + fac1 = None + fac2 = None + if gate.name == "H": + fac1 = (sympy.Integer(-1) ** qt * sympy.sqrt(sympy.Rational(1 / 2))) + fac2 = (sympy.sqrt(sympy.Rational(1 / 2))) + elif gate.name.upper() == "CNOT" or gate.name.upper() == "X": + fac2 = sympy.Integer(1) + elif gate.name.upper() == "Y": + fac2 = sympy.I * sympy.Integer(-1) ** (qt) + elif gate.name.upper() == "Z": + fac1 = sympy.Integer(-1) ** (qt) + elif gate.name.upper() == "RX": + angle = sympy.Rational(1 / 2) * gate.parameter(variables) + fac1 = sympy.cos(angle) + fac2 = -sympy.sin(angle) * sympy.I + elif gate.name.upper() == "RY": + angle = -sympy.Rational(1 / 2) * gate.parameter(variables) + fac1 = sympy.cos(angle) + fac2 = +sympy.sin(angle) * sympy.Integer(-1) ** (qt + 1) + elif gate.name.upper() == "RZ": + angle = sympy.Rational(1 / 2) * gate.parameter(variables) + fac1 = sympy.exp(-angle * sympy.I * sympy.Integer(-1) ** (qt)) + else: + raise Exception("Gate is not known to simulators, " + str(gate)) + + if fac1 is None or fac1 == 0: + result += fac2 * altered_state + elif fac2 is None or fac2 == 0: + result += fac1 * current_state + elif fac1 is None and fac2 is None: + raise Exception("???") + else: + result += fac1 * current_state + fac2 * altered_state + + return result
+ + +
+[docs] + def do_simulate(self, variables, initial_state: int = None, *args, **kwargs) -> QubitWaveFunction: + qubits = dict() + count = 0 + for q in self.abstract_circuit.qubits: + qubits[q] = count + count +=1 + + n_qubits = len(self.abstract_circuit.qubits) + + if initial_state is None: + initial_state = QubitWaveFunction.from_int(i=0, n_qubits=n_qubits) + elif isinstance(initial_state, int): + initial_state = QubitWaveFunction.from_int(initial_state, n_qubits=n_qubits) + + result = initial_state + for g in self.abstract_circuit.gates: + result = self.apply_gate(state=result, gate=g, qubits=qubits, variables=variables) + + wfn = QubitWaveFunction() + if self.convert_to_numpy: + for k,v in result.items(): + wfn[k] = complex(v) + else: + wfn = result + + return wfn
+
+ + +
+[docs] +class BackendExpectationValueSymbolic(BackendExpectationValue): + BackendCircuitType = BackendCircuitSymbolic
+ +
+ +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/_sources/circuit.rst.txt b/docs/sphinx/_sources/circuit.rst.txt new file mode 100644 index 0000000..c9cb18e --- /dev/null +++ b/docs/sphinx/_sources/circuit.rst.txt @@ -0,0 +1,77 @@ +Circuit +=============== + +Submodules +---------- + +circuit module +---------------------- + +.. automodule:: tequila_code.circuit.circuit + :members: + :undoc-members: + :show-inheritance: + +compiler module +----------------------- + +.. automodule:: tequila_code.circuit.compiler + :members: + :undoc-members: + :show-inheritance: + +gates module +-------------------- + +.. automodule:: tequila_code.circuit.gates + :members: + :undoc-members: + :show-inheritance: + +gradient module +----------------------- + +.. automodule:: tequila_code.circuit.gradient + :members: + :undoc-members: + :show-inheritance: + +noise module +-------------------- + +.. automodule:: tequila_code.circuit.noise + :members: + :undoc-members: + :show-inheritance: + +pyzx module +------------------- + +.. automodule:: tequila_code.circuit.pyzx + :members: + :undoc-members: + :show-inheritance: + +qasm module +------------------- + +.. automodule:: tequila_code.circuit.qasm + :members: + :undoc-members: + :show-inheritance: + +qpic module +------------------- + +.. automodule:: tequila_code.circuit.qpic + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: tequila_code.circuit + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/sphinx/_sources/docu_instruction.rst.txt b/docs/sphinx/_sources/docu_instruction.rst.txt new file mode 100644 index 0000000..0ba2e63 --- /dev/null +++ b/docs/sphinx/_sources/docu_instruction.rst.txt @@ -0,0 +1,146 @@ +Documenting Code in reStructuredText for Sphinx +================================================ + +Introduction +------------ +Sphinx supports automatic code documentation using the ``autodoc`` extension, which extracts docstrings from your code and integrates them into your documentation. This guide explains how to structure your code comments using reStructuredText to ensure your documentation is well-formatted and informative. + +1. Setting Up the Documentation +------------------------------- +Before you start documenting, make sure you have the Sphinx project and ``autodoc`` enabled in your ``conf.py``:: + + # In conf.py, ensure these extensions are present + extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', # Optional: For Google/NumPy style docstrings + ] + +2. Writing Docstrings with reStructuredText +------------------------------------------- +reStructuredText is a lightweight markup language used in docstrings. Here’s how to write effective docstrings for different parts of your code. + +**2.1 Module-Level Docstring** + +At the top of your module (``mymodule.py``), include a general description:: + + """ + mymodule.py + =========== + + This module contains functions and classes for data processing. + """ + +**2.2 Documenting Functions** + +Describe the function’s purpose, parameters, and return values. Use the following format:: + + def add_numbers(a, b): + """ + Adds two numbers together. + + :param int a: The first number. + :param int b: The second number. + :returns: The sum of `a` and `b`. + :rtype: int + """ + return a + b + +**2.3 Documenting Classes** + +For classes, include a class-level docstring and document each method:: + + class Calculator: + """ + A simple calculator class to perform basic arithmetic operations. + + :param str name: The name of the calculator instance. + """ + + def __init__(self, name): + """ + Initializes the calculator with a given name. + """ + self.name = name + + def multiply(self, x, y): + """ + Multiplies two numbers. + + :param int x: The first factor. + :param int y: The second factor. + :returns: The product of `x` and `y`. + :rtype: int + """ + return x * y + +**2.4 Documenting Class Attributes** + +Use the ``:ivar`` directive to describe class attributes:: + + class Rectangle: + """ + Represents a geometric rectangle. + + :ivar float length: The length of the rectangle. + :ivar float width: The width of the rectangle. + """ + def __init__(self, length, width): + self.length = length + self.width = width + +3. Formatting Docstrings +------------------------ +**3.1 Sections** + +Use specific section headers (optional but recommended): + +- ``Parameters`` +- ``Returns`` +- ``Raises`` (for exceptions) + +Example:: + + def divide(x, y): + """ + Divides `x` by `y`. + + **Parameters:** + + - `x (float)`: Numerator. + - `y (float)`: Denominator. + + **Returns:** + + - `float`: The result of division. + + **Raises:** + + - `ZeroDivisionError`: If `y` is zero. + """ + if y == 0: + raise ZeroDivisionError("Cannot divide by zero.") + return x / y + +**3.2 Cross-referencing** + +To reference other parts of the code, use the ``:class:``, ``:func:`` and similar directives:: + + """ + See also :class:`Calculator` for more operations. + """ + +4. Building the Documentation +----------------------------- +Once your code is documented, build the documentation to see the results:: + + make html + +This will generate the HTML files in the ``_build`` directory, integrating your code comments into the documentation. + +5. Cleaning the Build Directory +------------------------------- +If you need to rebuild the documentation from scratch, use:: + + make clean + +This removes all previously built files. diff --git a/docs/sphinx/_sources/hamiltonian.rst.txt b/docs/sphinx/_sources/hamiltonian.rst.txt new file mode 100644 index 0000000..58e075d --- /dev/null +++ b/docs/sphinx/_sources/hamiltonian.rst.txt @@ -0,0 +1,37 @@ +Hamiltonian +=================== + +Submodules +---------- + +paulis module +------------------------- + +.. automodule:: tequila_code.hamiltonian.paulis + :members: + :undoc-members: + :show-inheritance: + +paulistring module +------------------------------ + +.. automodule:: tequila_code.hamiltonian.paulistring + :members: + :undoc-members: + :show-inheritance: + +qubit-hamiltonian module +------------------------------------- + +.. automodule:: tequila_code.hamiltonian.qubit_hamiltonian + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: tequila_code.hamiltonian + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/sphinx/_sources/index.rst.txt b/docs/sphinx/_sources/index.rst.txt new file mode 100644 index 0000000..c5b5c0a --- /dev/null +++ b/docs/sphinx/_sources/index.rst.txt @@ -0,0 +1,40 @@ +.. Tequila Documentation documentation master file, created by + sphinx-quickstart on Fri Sep 27 21:03:37 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Tequila Documentation +====================== + + +Welcome to the Tequila Documentation website. +This website provides comprehensive information about the modules available in Tequila, +including a detailed overview of each module's functions and instructions on how to utilise them correctly. + + +Additionally, there are practical tutorials that illustrate the capabilities of Tequila. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + modules + +Practical Tutorials +-------------------- + +`Tutorials Website `_ + + + + + + + + + + + + + + diff --git a/docs/sphinx/_sources/modules.rst.txt b/docs/sphinx/_sources/modules.rst.txt new file mode 100644 index 0000000..48cc499 --- /dev/null +++ b/docs/sphinx/_sources/modules.rst.txt @@ -0,0 +1,12 @@ +Tequila Library Reference +========================== + +.. toctree:: + :maxdepth: 6 + + hamiltonian + circuit + optimizers + simulators + quantumchemistry + diff --git a/docs/sphinx/_sources/optimizers.rst.txt b/docs/sphinx/_sources/optimizers.rst.txt new file mode 100644 index 0000000..5f03029 --- /dev/null +++ b/docs/sphinx/_sources/optimizers.rst.txt @@ -0,0 +1,45 @@ +Optimizers +================== + +Submodules +---------- + +optimizer base module +--------------------------------- + +.. automodule:: tequila_code.optimizers.optimizer_base + :members: + :undoc-members: + :show-inheritance: + +optimizer gradient module +------------------------------- + +.. automodule:: tequila_code.optimizers.optimizer_gd + :members: + :undoc-members: + :show-inheritance: + +optimizer gpyopt module +----------------------------------- + +.. automodule:: tequila_code.optimizers.optimizer_gpyopt + :members: + :undoc-members: + :show-inheritance: + +optimizer scipy module +---------------------------------- + +.. automodule:: tequila_code.optimizers.optimizer_scipy + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: tequila_code.optimizers + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/sphinx/_sources/quantumchemistry.rst.txt b/docs/sphinx/_sources/quantumchemistry.rst.txt new file mode 100644 index 0000000..5c8ddb2 --- /dev/null +++ b/docs/sphinx/_sources/quantumchemistry.rst.txt @@ -0,0 +1,70 @@ +Quantum Chemistry +=================== + +Submodules +---------- + +chemistry tools module +---------------------------------------- + +.. automodule:: tequila_code.quantumchemistry.chemistry_tools + :members: + :undoc-members: + :show-inheritance: + +encodings module +--------------------------------- + +.. automodule:: tequila_code.quantumchemistry.encodings + :members: + :undoc-members: + :show-inheritance: + +madness interface module +------------------------------------------ + +.. automodule:: tequila_code.quantumchemistry.madness_interface + :members: + :undoc-members: + :show-inheritance: + +orbital optimizer module +------------------------------------------ + +.. automodule:: tequila_code.quantumchemistry.orbital_optimizer + :members: + :undoc-members: + :show-inheritance: + +psi4 interface module +--------------------------------------- + +.. automodule:: tequila_code.quantumchemistry.psi4_interface + :members: + :undoc-members: + :show-inheritance: + + +pyscf interface module +---------------------------------------- + +.. automodule:: tequila_code.quantumchemistry.pyscf_interface + :members: + :undoc-members: + :show-inheritance: + +qc base module +-------------------------------- + +.. automodule:: tequila_code.quantumchemistry.qc_base + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: tequila_code.quantumchemistry + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/sphinx/_sources/simulators.rst.txt b/docs/sphinx/_sources/simulators.rst.txt new file mode 100644 index 0000000..a112d4c --- /dev/null +++ b/docs/sphinx/_sources/simulators.rst.txt @@ -0,0 +1,93 @@ +Simulators +================== + +Submodules +---------- + +simulator api module +-------------------------------- + +.. automodule:: tequila_code.simulators.simulator_api + :members: + :undoc-members: + :show-inheritance: + +simulator base module +--------------------------------- + +.. automodule:: tequila_code.simulators.simulator_base + :members: + :undoc-members: + :show-inheritance: + +simulator cirq module +--------------------------------- + +.. automodule:: tequila_code.simulators.simulator_cirq + :members: + :undoc-members: + :show-inheritance: + +simulator pyquil module +----------------------------------- + +.. automodule:: tequila_code.simulators.simulator_pyquil + :members: + :undoc-members: + :show-inheritance: + +simulator qibo module +--------------------------------- + +.. automodule:: tequila_code.simulators.simulator_qibo + :members: + :undoc-members: + :show-inheritance: + +simulator qiskit module +----------------------------------- + +.. automodule:: tequila_code.simulators.simulator_qiskit + :members: + :undoc-members: + :show-inheritance: + +simulator qlm module +-------------------------------- + +.. automodule:: tequila_code.simulators.simulator_qlm + :members: + :undoc-members: + :show-inheritance: + +simulator qulacs module +----------------------------------- + +.. automodule:: tequila_code.simulators.simulator_qulacs + :members: + :undoc-members: + :show-inheritance: + +simulator qulacs gpu module +---------------------------------------- + +.. automodule:: tequila_code.simulators.simulator_qulacs_gpu + :members: + :undoc-members: + :show-inheritance: + +simulator symbolic module +------------------------------------- + +.. automodule:: tequila_code.simulators.simulator_symbolic + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: tequila_code.simulators + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/sphinx/_static/_sphinx_javascript_frameworks_compat.js b/docs/sphinx/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 0000000..8141580 --- /dev/null +++ b/docs/sphinx/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,123 @@ +/* Compatability shim for jQuery and underscores.js. + * + * Copyright Sphinx contributors + * Released under the two clause BSD licence + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/docs/sphinx/_static/basic.css b/docs/sphinx/_static/basic.css new file mode 100644 index 0000000..7ebbd6d --- /dev/null +++ b/docs/sphinx/_static/basic.css @@ -0,0 +1,914 @@ +/* + * Sphinx stylesheet -- basic theme. + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin-top: 10px; +} + +ul.search li { + padding: 5px 0; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/sphinx/_static/css/badge_only.css b/docs/sphinx/_static/css/badge_only.css new file mode 100644 index 0000000..88ba55b --- /dev/null +++ b/docs/sphinx/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px} \ No newline at end of file diff --git a/docs/sphinx/_static/css/fonts/Roboto-Slab-Bold.woff b/docs/sphinx/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 0000000..6cb6000 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/docs/sphinx/_static/css/fonts/Roboto-Slab-Bold.woff2 b/docs/sphinx/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 0000000..7059e23 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/docs/sphinx/_static/css/fonts/Roboto-Slab-Regular.woff b/docs/sphinx/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 0000000..f815f63 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/docs/sphinx/_static/css/fonts/Roboto-Slab-Regular.woff2 b/docs/sphinx/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 0000000..f2c76e5 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/docs/sphinx/_static/css/fonts/fontawesome-webfont.eot b/docs/sphinx/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..e9f60ca Binary files /dev/null and b/docs/sphinx/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/docs/sphinx/_static/css/fonts/fontawesome-webfont.svg b/docs/sphinx/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..855c845 --- /dev/null +++ b/docs/sphinx/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/sphinx/_static/css/fonts/fontawesome-webfont.ttf b/docs/sphinx/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/docs/sphinx/_static/css/fonts/fontawesome-webfont.woff b/docs/sphinx/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..400014a Binary files /dev/null and b/docs/sphinx/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/docs/sphinx/_static/css/fonts/fontawesome-webfont.woff2 b/docs/sphinx/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/docs/sphinx/_static/css/fonts/lato-bold-italic.woff b/docs/sphinx/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 0000000..88ad05b Binary files /dev/null and b/docs/sphinx/_static/css/fonts/lato-bold-italic.woff differ diff --git a/docs/sphinx/_static/css/fonts/lato-bold-italic.woff2 b/docs/sphinx/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 0000000..c4e3d80 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/docs/sphinx/_static/css/fonts/lato-bold.woff b/docs/sphinx/_static/css/fonts/lato-bold.woff new file mode 100644 index 0000000..c6dff51 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/lato-bold.woff differ diff --git a/docs/sphinx/_static/css/fonts/lato-bold.woff2 b/docs/sphinx/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 0000000..bb19504 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/lato-bold.woff2 differ diff --git a/docs/sphinx/_static/css/fonts/lato-normal-italic.woff b/docs/sphinx/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 0000000..76114bc Binary files /dev/null and b/docs/sphinx/_static/css/fonts/lato-normal-italic.woff differ diff --git a/docs/sphinx/_static/css/fonts/lato-normal-italic.woff2 b/docs/sphinx/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 0000000..3404f37 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/docs/sphinx/_static/css/fonts/lato-normal.woff b/docs/sphinx/_static/css/fonts/lato-normal.woff new file mode 100644 index 0000000..ae1307f Binary files /dev/null and b/docs/sphinx/_static/css/fonts/lato-normal.woff differ diff --git a/docs/sphinx/_static/css/fonts/lato-normal.woff2 b/docs/sphinx/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 0000000..3bf9843 Binary files /dev/null and b/docs/sphinx/_static/css/fonts/lato-normal.woff2 differ diff --git a/docs/sphinx/_static/css/theme.css b/docs/sphinx/_static/css/theme.css new file mode 100644 index 0000000..0f14f10 --- /dev/null +++ b/docs/sphinx/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search .wy-dropdown>aactive,.wy-side-nav-search .wy-dropdown>afocus,.wy-side-nav-search>a:hover,.wy-side-nav-search>aactive,.wy-side-nav-search>afocus{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon,.wy-side-nav-search>a.icon{display:block}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.switch-menus{position:relative;display:block;margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-side-nav-search>div.switch-menus>div.language-switch,.wy-side-nav-search>div.switch-menus>div.version-switch{display:inline-block;padding:.2em}.wy-side-nav-search>div.switch-menus>div.language-switch select,.wy-side-nav-search>div.switch-menus>div.version-switch select{display:inline-block;margin-right:-2rem;padding-right:2rem;max-width:240px;text-align-last:center;background:none;border:none;border-radius:0;box-shadow:none;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-size:1em;font-weight:400;color:hsla(0,0%,100%,.3);cursor:pointer;appearance:none;-webkit-appearance:none;-moz-appearance:none}.wy-side-nav-search>div.switch-menus>div.language-switch select:active,.wy-side-nav-search>div.switch-menus>div.language-switch select:focus,.wy-side-nav-search>div.switch-menus>div.language-switch select:hover,.wy-side-nav-search>div.switch-menus>div.version-switch select:active,.wy-side-nav-search>div.switch-menus>div.version-switch select:focus,.wy-side-nav-search>div.switch-menus>div.version-switch select:hover{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.wy-side-nav-search>div.switch-menus>div.language-switch select option,.wy-side-nav-search>div.switch-menus>div.version-switch select option{color:#000}.wy-side-nav-search>div.switch-menus>div.language-switch:has(>select):after,.wy-side-nav-search>div.switch-menus>div.version-switch:has(>select):after{display:inline-block;width:1.5em;height:100%;padding:.1em;content:"\f0d7";font-size:1em;line-height:1.2em;font-family:FontAwesome;text-align:center;pointer-events:none;box-sizing:border-box}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/docs/sphinx/_static/doctools.js b/docs/sphinx/_static/doctools.js new file mode 100644 index 0000000..0398ebb --- /dev/null +++ b/docs/sphinx/_static/doctools.js @@ -0,0 +1,149 @@ +/* + * Base JavaScript utilities for all Sphinx HTML documentation. + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/docs/sphinx/_static/documentation_options.js b/docs/sphinx/_static/documentation_options.js new file mode 100644 index 0000000..505b7cf --- /dev/null +++ b/docs/sphinx/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '13.9.2024', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/docs/sphinx/_static/file.png b/docs/sphinx/_static/file.png new file mode 100644 index 0000000..a858a41 Binary files /dev/null and b/docs/sphinx/_static/file.png differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-bold.eot b/docs/sphinx/_static/fonts/Lato/lato-bold.eot new file mode 100644 index 0000000..3361183 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-bold.eot differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-bold.ttf b/docs/sphinx/_static/fonts/Lato/lato-bold.ttf new file mode 100644 index 0000000..29f691d Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-bold.ttf differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-bold.woff b/docs/sphinx/_static/fonts/Lato/lato-bold.woff new file mode 100644 index 0000000..c6dff51 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-bold.woff differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-bold.woff2 b/docs/sphinx/_static/fonts/Lato/lato-bold.woff2 new file mode 100644 index 0000000..bb19504 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-bold.woff2 differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-bolditalic.eot b/docs/sphinx/_static/fonts/Lato/lato-bolditalic.eot new file mode 100644 index 0000000..3d41549 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-bolditalic.eot differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-bolditalic.ttf b/docs/sphinx/_static/fonts/Lato/lato-bolditalic.ttf new file mode 100644 index 0000000..f402040 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-bolditalic.ttf differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-bolditalic.woff b/docs/sphinx/_static/fonts/Lato/lato-bolditalic.woff new file mode 100644 index 0000000..88ad05b Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-bolditalic.woff differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-bolditalic.woff2 b/docs/sphinx/_static/fonts/Lato/lato-bolditalic.woff2 new file mode 100644 index 0000000..c4e3d80 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-bolditalic.woff2 differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-italic.eot b/docs/sphinx/_static/fonts/Lato/lato-italic.eot new file mode 100644 index 0000000..3f82642 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-italic.eot differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-italic.ttf b/docs/sphinx/_static/fonts/Lato/lato-italic.ttf new file mode 100644 index 0000000..b4bfc9b Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-italic.ttf differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-italic.woff b/docs/sphinx/_static/fonts/Lato/lato-italic.woff new file mode 100644 index 0000000..76114bc Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-italic.woff differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-italic.woff2 b/docs/sphinx/_static/fonts/Lato/lato-italic.woff2 new file mode 100644 index 0000000..3404f37 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-italic.woff2 differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-regular.eot b/docs/sphinx/_static/fonts/Lato/lato-regular.eot new file mode 100644 index 0000000..11e3f2a Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-regular.eot differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-regular.ttf b/docs/sphinx/_static/fonts/Lato/lato-regular.ttf new file mode 100644 index 0000000..74decd9 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-regular.ttf differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-regular.woff b/docs/sphinx/_static/fonts/Lato/lato-regular.woff new file mode 100644 index 0000000..ae1307f Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-regular.woff differ diff --git a/docs/sphinx/_static/fonts/Lato/lato-regular.woff2 b/docs/sphinx/_static/fonts/Lato/lato-regular.woff2 new file mode 100644 index 0000000..3bf9843 Binary files /dev/null and b/docs/sphinx/_static/fonts/Lato/lato-regular.woff2 differ diff --git a/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot new file mode 100644 index 0000000..79dc8ef Binary files /dev/null and b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot differ diff --git a/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf new file mode 100644 index 0000000..df5d1df Binary files /dev/null and b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf differ diff --git a/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff new file mode 100644 index 0000000..6cb6000 Binary files /dev/null and b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff differ diff --git a/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 new file mode 100644 index 0000000..7059e23 Binary files /dev/null and b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 differ diff --git a/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot new file mode 100644 index 0000000..2f7ca78 Binary files /dev/null and b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot differ diff --git a/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf new file mode 100644 index 0000000..eb52a79 Binary files /dev/null and b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf differ diff --git a/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff new file mode 100644 index 0000000..f815f63 Binary files /dev/null and b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff differ diff --git a/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 new file mode 100644 index 0000000..f2c76e5 Binary files /dev/null and b/docs/sphinx/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 differ diff --git a/docs/sphinx/_static/jquery.js b/docs/sphinx/_static/jquery.js new file mode 100644 index 0000000..c4c6022 --- /dev/null +++ b/docs/sphinx/_static/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t a.language.name.localeCompare(b.language.name)); + + const languagesHTML = ` +
+
Languages
+ ${languages + .map( + (translation) => ` +
+ ${translation.language.code} +
+ `, + ) + .join("\n")} +
+ `; + return languagesHTML; + } + + function renderVersions(config) { + if (!config.versions.active.length) { + return ""; + } + const versionsHTML = ` +
+
Versions
+ ${config.versions.active + .map( + (version) => ` +
+ ${version.slug} +
+ `, + ) + .join("\n")} +
+ `; + return versionsHTML; + } + + function renderDownloads(config) { + if (!Object.keys(config.versions.current.downloads).length) { + return ""; + } + const downloadsNameDisplay = { + pdf: "PDF", + epub: "Epub", + htmlzip: "HTML", + }; + + const downloadsHTML = ` +
+
Downloads
+ ${Object.entries(config.versions.current.downloads) + .map( + ([name, url]) => ` +
+ ${downloadsNameDisplay[name]} +
+ `, + ) + .join("\n")} +
+ `; + return downloadsHTML; + } + + document.addEventListener("readthedocs-addons-data-ready", function (event) { + const config = event.detail.data(); + + const flyout = ` +
+ + Read the Docs + v: ${config.versions.current.slug} + + +
+
+ ${renderLanguages(config)} + ${renderVersions(config)} + ${renderDownloads(config)} +
+
On Read the Docs
+
+ Project Home +
+
+ Builds +
+
+ Downloads +
+
+
+
Search
+
+
+ +
+
+
+
+ + Hosted by Read the Docs + +
+
+ `; + + // Inject the generated flyout into the body HTML element. + document.body.insertAdjacentHTML("beforeend", flyout); + + // Trigger the Read the Docs Addons Search modal when clicking on the "Search docs" input from inside the flyout. + document + .querySelector("#flyout-search-form") + .addEventListener("focusin", () => { + const event = new CustomEvent("readthedocs-search-show"); + document.dispatchEvent(event); + }); + }) +} + +if (themeLanguageSelector || themeVersionSelector) { + function onSelectorSwitch(event) { + const option = event.target.selectedIndex; + const item = event.target.options[option]; + window.location.href = item.dataset.url; + } + + document.addEventListener("readthedocs-addons-data-ready", function (event) { + const config = event.detail.data(); + + const versionSwitch = document.querySelector( + "div.switch-menus > div.version-switch", + ); + if (themeVersionSelector) { + let versions = config.versions.active; + if (config.versions.current.hidden || config.versions.current.type === "external") { + versions.unshift(config.versions.current); + } + const versionSelect = ` + + `; + + versionSwitch.innerHTML = versionSelect; + versionSwitch.firstElementChild.addEventListener("change", onSelectorSwitch); + } + + const languageSwitch = document.querySelector( + "div.switch-menus > div.language-switch", + ); + + if (themeLanguageSelector) { + if (config.projects.translations.length) { + // Add the current language to the options on the selector + let languages = config.projects.translations.concat( + config.projects.current, + ); + languages = languages.sort((a, b) => + a.language.name.localeCompare(b.language.name), + ); + + const languageSelect = ` + + `; + + languageSwitch.innerHTML = languageSelect; + languageSwitch.firstElementChild.addEventListener("change", onSelectorSwitch); + } + else { + languageSwitch.remove(); + } + } + }); +} + +document.addEventListener("readthedocs-addons-data-ready", function (event) { + // Trigger the Read the Docs Addons Search modal when clicking on "Search docs" input from the topnav. + document + .querySelector("[role='search'] input") + .addEventListener("focusin", () => { + const event = new CustomEvent("readthedocs-search-show"); + document.dispatchEvent(event); + }); +}); \ No newline at end of file diff --git a/docs/sphinx/_static/language_data.js b/docs/sphinx/_static/language_data.js new file mode 100644 index 0000000..c7fe6c6 --- /dev/null +++ b/docs/sphinx/_static/language_data.js @@ -0,0 +1,192 @@ +/* + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, if available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/docs/sphinx/_static/minus.png b/docs/sphinx/_static/minus.png new file mode 100644 index 0000000..d96755f Binary files /dev/null and b/docs/sphinx/_static/minus.png differ diff --git a/docs/sphinx/_static/plus.png b/docs/sphinx/_static/plus.png new file mode 100644 index 0000000..7107cec Binary files /dev/null and b/docs/sphinx/_static/plus.png differ diff --git a/docs/sphinx/_static/pygments.css b/docs/sphinx/_static/pygments.css new file mode 100644 index 0000000..84ab303 --- /dev/null +++ b/docs/sphinx/_static/pygments.css @@ -0,0 +1,75 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #9C6500 } /* Comment.Preproc */ +.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #E40000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #008400 } /* Generic.Inserted */ +.highlight .go { color: #717171 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #687822 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #767600 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #666666 } /* Literal.Number.Bin */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sa { color: #BA2121 } /* Literal.String.Affix */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #A45A77 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #0000FF } /* Name.Function.Magic */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .vm { color: #19177C } /* Name.Variable.Magic */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/docs/sphinx/_static/searchtools.js b/docs/sphinx/_static/searchtools.js new file mode 100644 index 0000000..2c774d1 --- /dev/null +++ b/docs/sphinx/_static/searchtools.js @@ -0,0 +1,632 @@ +/* + * Sphinx JavaScript utilities for the full-text search. + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename, kind] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +// Global search result kind enum, used by themes to style search results. +class SearchResultKind { + static get index() { return "index"; } + static get object() { return "object"; } + static get text() { return "text"; } + static get title() { return "title"; } +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename, kind] = item; + + let listItem = document.createElement("li"); + // Add a class representing the item's type: + // can be used by a theme's CSS selector for styling + // See SearchResultKind for the class names. + listItem.classList.add(`kind-${kind}`); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = Documentation.ngettext( + "Search finished, found one page matching the search query.", + "Search finished, found ${resultCount} pages matching the search query.", + resultCount, + ).replace('${resultCount}', resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename, kind]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.setAttribute("role", "list"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename, kind]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + const score = Math.round(Scorer.title * queryLower.length / title.length); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score + boost, + filenames[file], + SearchResultKind.title, + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + SearchResultKind.index, + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + SearchResultKind.object, + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + SearchResultKind.text, + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/docs/sphinx/_static/sphinx_highlight.js b/docs/sphinx/_static/sphinx_highlight.js new file mode 100644 index 0000000..8a96c69 --- /dev/null +++ b/docs/sphinx/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/docs/sphinx/circuit.html b/docs/sphinx/circuit.html new file mode 100644 index 0000000..2dbcd0b --- /dev/null +++ b/docs/sphinx/circuit.html @@ -0,0 +1,2272 @@ + + + + + + + + + Circuit — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Circuit

+
+

Submodules

+
+
+

circuit module

+
+
+class tequila_code.circuit.circuit.Moment(gates: List[QGateImpl] = None, sort=False)[source]
+

Bases: QCircuit

+

the class which represents a set of simultaneously applicable gates.

+
+
+with_gate:
+

attempt to add a gate to the moment, replacing any gate it may conflict with.

+
+ +
+
+with_gates:
+

attempt to add multiple gates to the moment, replacing any gates they may conflict with.

+
+ +
+
+add_gate(gate: QCircuit | QGateImpl)[source]
+

add a gate to the moment.

+
+
Parameters:
+

gate – the desired gate.

+
+
Returns:
+

a new moment, of self + a new gate

+
+
Return type:
+

Moment

+
+
+
+ +
+
+as_circuit()[source]
+

convert back into the unrestricted QCircuit. +:returns: a circuit with the same gates as self. +:rtype: QCircuit

+
+ +
+
+property canonical_depth
+

gate depth of the abstract circuit in alternating layer form. +:returns: int +:rtype: depth of the alternating layer form.

+
+ +
+
+property canonical_moments
+

Break self up into parametrized and unparametrized layers. +:returns: list of 2 Moments, one of which may be empty. +:rtype: list

+
+ +
+
+property depth
+

gate depth of the abstract circuit. +:returns: int +:rtype: the depth.

+
+ +
+
+static from_moments(moments: List)[source]
+
+
Raises:
+

TequilaException

+
+
+
+ +
+
+fully_parametrized()[source]
+

Todo: Why not just inherit from base? +:returns: whether or not EVERY gate in self.gates is parameterized. +:rtype: bool

+
+ +
+
+property moments
+

Divide self into subcircuits representing layers of simultaneous gates. Attempts to minimize gate depth. +:returns: list of Moment objects. +:rtype: list

+
+ +
+
+replace_gate(position, gates)[source]
+

substitute a gate at a given position with other gates. +:param position: where in the list of gates the gate to be replaced occurs. +:param gates: the gates to replace the unwanted gate with.

+
+
Returns:
+

self, with unwanted gate removed and new gates inserted. May not be a moment.

+
+
Return type:
+

QCircuit or Moment

+
+
+
+ +
+
+with_gate(gate: QCircuit | QGateImpl)[source]
+

Add a gate, or else replace some gate with it.

+
+
Parameters:
+

gate – the gate to insert into the moment.

+
+
Returns:
+

a New moment with the proper gates.

+
+
Return type:
+

Moment

+
+
+
+ +
+
+with_gates(gates)[source]
+

with gate, but on multiple gates.

+
+
Parameters:
+

gates – list of QGates

+
+
Returns:
+

a new Moment, with the desired gates insert into self.

+
+
Return type:
+

Moment

+
+
+
+ +
+
+static wrap_gate(gate: QGateImpl)[source]
+
+
Parameters:
+

gate (QGateImpl:) – the gate, to wrap as a moment

+
+
Returns:
+

a moment with one gate in it.

+
+
Return type:
+

Moment

+
+
+
+ +
+ +
+
+class tequila_code.circuit.circuit.QCircuit(gates=None, parameter_map=None)[source]
+

Bases: object

+

Fundamental class representing an abstract circuit.

+
+
+canonical_depth
+

the depth of the circuit, if converted to alternating parametrized and unparametrized layers.

+
+ +
+
+canonical_moments
+

returns the circuit as a list of Moment objects alternating between parametrized and unparametrized layers.

+
+ +
+
+depth
+

returns the gate depth of the circuit.

+
+ +
+
+gates
+

returns the gates in the circuit, as a list.

+
+ +
+
+moments
+

returns the circuit as a list of Moment objects.

+
+ +
+
+n_qubits
+

the number of qubits on which the circuit operates.

+
+ +
+
+numbering
+

returns the numbering convention use by tequila circuits.

+
+ +
+
+qubits
+

returns a list of qubits acted upon by the circuit.

+
+ +
+
+make_parameter_map:
+
+ +
+
+add_controls(control, inpl: bool | None = False) QCircuit | None[source]
+
+
Depending on the truth value of inpl:
    +
  • return controlled version of self with control as the control qubits if inpl;

  • +
  • mutate self so that the qubits in control are added as the control qubits if not inpl.

  • +
+
+
+

Raise ValueError if there any qubits in common between self and control.

+
+ +
+
+property canonical_depth
+

gate depth of the abstract circuit in alternating layer form. +:returns: int +:rtype: depth of the alternating layer form.

+
+ +
+
+property canonical_moments
+

Divide self into subcircuits of alternating unparametrized and parametrized layers. +:rtype: list of Moment objects.

+
+ +
+
+dagger()[source]
+
+
Returns:
+

The adjoint of the circuit

+
+
Return type:
+

QCircuit

+
+
+
+ +
+
+property depth
+

gate depth of the abstract circuit. +:returns: int +:rtype: the depth.

+
+ +
+
+export_to(*args, **kwargs)[source]
+

Export to png, pdf, qpic, tex with qpic backend +Convenience: see src/tequila/circuit/qpic.py - export_to for more +Parameters

+
+ +
+
+extract_variables() list[source]
+

return a list containing all the variable objects contained in any of the gates within the unitary +including those nested within gates themselves.

+
+
Returns:
+

the variables of the circuit

+
+
Return type:
+

list

+
+
+
+ +
+
+static from_moments(moments: List)[source]
+

build a circuit from Moment objects.

+
+
Parameters:
+

moments (list:) – a list of Moment objects.

+
+
+
+ +
+
+property gates
+
+ +
+
+insert_gates(positions, gates)[source]
+

See replace_gates

+
+ +
+
+is_fully_parametrized()[source]
+
+
Returns:
+

whether or not all gates in the circuit are paremtrized

+
+
Return type:
+

bool

+
+
+
+ +
+
+is_fully_unparametrized()[source]
+
+
Returns:
+

whether or not all gates in the circuit are unparametrized

+
+
Return type:
+

bool

+
+
+
+ +
+
+is_mixed()[source]
+
+ +
+
+is_primitive()[source]
+

Check if this is a single gate wrapped in this structure +:return: True if the circuit is just a single gate

+
+ +
+
+make_parameter_map() dict[source]
+
+
Returns:
+

    +
  • ParameterMap of the circuit (A dictionary with)

  • +
  • keys (variables in the circuit)

  • +
  • values (list of all gates and their positions in the circuit)

  • +
  • e.g. result[Variable(“a”)] = [(3, Rx), (5, Ry), …]

  • +
+

+
+
+
+ +
+
+map_qubits(qubit_map)[source]
+

E.G. Rx(1)Ry(2) –> Rx(3)Ry(1) with qubit_map = {1:3, 2:1}

+
+
Parameters:
+

qubit_map – a dictionary which maps old to new qubits

+
+
Return type:
+

A new circuit with mapped qubits

+
+
+
+ +
+
+map_variables(variables: dict, *args, **kwargs)[source]
+
+
Parameters:
+

variables – dictionary with old variable names as keys and new variable names or values as values

+
+
Return type:
+

Circuit with changed variables

+
+
+
+ +
+
+max_qubit()[source]
+

Returns: +int:

+
+

Highest index of qubits in the circuit

+
+
+ +
+
+property moments
+

Divide self into subcircuits representing layers of simultaneous gates. Attempts to minimize gate depth. +:returns: list of Moment objects. +:rtype: list

+
+ +
+
+property n_qubits
+
+ +
+
+property numbering: BitNumbering
+
+ +
+
+property qubits
+
+ +
+
+replace_gates(positions: list, circuits: list, replace: list = None)[source]
+

Notes

+

Replace or insert gates at specific positions into the circuit +at different positions (faster than multiple calls to replace_gate)

+
+
Parameters:
+
    +
  • positions (list of int:) – the positions at which the gates should be added. Always refer to the positions in the original circuit

  • +
  • circuits (list or QCircuit:) – the gates to add at the corresponding positions

  • +
  • replace (list of bool: (Default value: None)) – Default is None which corresponds to all true +decide if gates shall be replaces or if the new parts shall be inserted without replacement +if replace[i] = true: gate at position [i] will be replaces by gates[i] +if replace[i] = false: gates[i] circuit will be inserted at position [i] (beaming before gate previously at position [i])

  • +
+
+
Return type:
+

new circuit with inserted gates

+
+
+
+ +
+
+sort_gates()[source]
+

sort self into subcircuits corresponding to all simultaneous operations, greedily; then reinitialize gates. +:rtype: None

+
+ +
+
+to_networkx()[source]
+

Turn a given quantum circuit from tequila into graph form via NetworkX +:param self: tq.gates.QCircuit +:return: G, a graph in NetworkX with qubits as nodes and gate connections as edges

+
+ +
+
+verify() bool[source]
+

make sure self is built properly and of the correct types. +:returns: whether or not the circuit is properly constructed. +:rtype: bool

+
+ +
+
+static wrap_gate(gate: QGateImpl)[source]
+

take a gate and return a qcircuit containing only that gate. +:param gate: the gate to wrap in a circuit. +:type gate: QGateImpl

+
+
Returns:
+

a one gate circuit.

+
+
Return type:
+

QCircuit

+
+
+
+ +
+ +
+
+tequila_code.circuit.circuit.find_unused_qubit(U0: QCircuit = None, U1: QCircuit = None) int[source]
+

Function that checks which are the active qubits of two circuits and +provides an unused qubit that is not among them. If all qubits are used +it adds a new one.

+
+
Parameters:
+
    +
  • U0 (QCircuit, corresponding to the first state.)

  • +
  • U1 (QCircuit, corresponding to the second state.)

  • +
+
+
Returns:
+

control_qubit

+
+
Return type:
+

int

+
+
+
+ +
+
+

compiler module

+
+
+class tequila_code.circuit.compiler.CircuitCompiler(multitarget=False, multicontrol=False, trotterized=False, generalized_rotation=False, exponential_pauli=False, controlled_exponential_pauli=False, hadamard_power=False, controlled_power=False, power=False, toffoli=False, controlled_phase=False, phase=False, phase_to_z=False, controlled_rotation=False, swap=False, cc_max=False, gradient_mode=False, ry_gate=False, y_gate=False, ch_gate=False, hadamard=False)[source]
+

Bases: object

+

an object that performs abstract compilation of QCircuits and Objectives.

+
+

Note

+

see init for attributes, since all are specified there

+
+
+
+compile_objective()[source]
+

perform compilation on an entire objective

+
+ +
+
+compile_objective_argument()[source]
+

perform compilation on a single arg of objective

+
+ +
+
+compile_circuit:
+

perform compilation on a circuit.

+
+ +
+
+classmethod all_flags_true(*args, **kwargs)[source]
+
+ +
+
+compile_circuit(abstract_circuit: QCircuit, variables=None, *args, **kwargs) QCircuit[source]
+

compile a circuit. +:param abstract_circuit: the circuit to compile. +:type abstract_circuit: QCircuit +:param variables: (Default value = None):

+
+

list of the variables whose gates, specifically, must compile. +Used to prevent excess compilation in gates whose parameters are fixed. +Default: compile every single gate.

+
+
+
Parameters:
+
    +
  • args

  • +
  • kwargs

  • +
+
+
Return type:
+

QCircuit; a compiled circuit.

+
+
+
+ +
+
+compile_objective(objective, *args, **kwargs)[source]
+

Compile an objective.

+
+
Parameters:
+
    +
  • objective (Objective:) – the objective.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Return type:
+

the objective, compiled

+
+
+
+ +
+
+compile_objective_argument(arg, *args, **kwargs)[source]
+

Compile an argument of an objective.

+
+
Parameters:
+
    +
  • arg – the term to compile

  • +
  • args

  • +
  • kwargs

  • +
+
+
Return type:
+

the arg, compiled

+
+
+
+ +
+
+classmethod standard_gate_set(*args, **kwargs)[source]
+
+ +
+ +
+
+exception tequila_code.circuit.compiler.TequilaCompilerException(msg)[source]
+

Bases: TequilaException

+
+ +
+
+tequila_code.circuit.compiler.change_basis(target, axis=None, name=None, daggered=False)[source]
+

helper function; returns circuit that performs change of basis. +:param target: the qubit having its basis changed +:param axis: The axis of rotation to shift into. +:param daggered: adjusts the sign of the gate if axis = 1, I.E, change of basis about Y axis. +:type daggered: bool:

+
+
Return type:
+

QCircuit that performs change of basis on target qubit onto desired axis

+
+
+
+ +
+
+tequila_code.circuit.compiler.compile_ch(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_controlled_phase(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_controlled_power(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_controlled_rotation(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_exponential_pauli_gate(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_generalized_rotation_gate(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_multitarget(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_phase(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_phase_to_z(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_power_base(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_power_gate(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_ry(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_swap(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_to_single_control(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_toffoli(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_trotterized_gate(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compile_y(gate, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.compiler.compiler(f)[source]
+

Decorator for compile functions.

+

Make them applicable for single gates as well as for whole circuits +Note that all arguments need to be passed as keyword arguments

+
+ +
+
+tequila_code.circuit.compiler.do_compile_trotterized_gate(generator, steps, factor, randomize, control)[source]
+
+ +
+
+

gates module

+
+
+tequila_code.circuit.gates.CNOT(control: int, target: int) QCircuit[source]
+

Convenience CNOT initialization

+
+
Parameters:
+
    +
  • control (int) – control qubit

  • +
  • target (int) – target qubit

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.CRx(control: int, target: int, angle: float) QCircuit[source]
+

Convenience initialization CRx (controlled Pauli X Rotation)

+
+
Parameters:
+
    +
  • control (int) – control qubit

  • +
  • target (int) – target qubit

  • +
  • angle – Hashable type (will be treated as Variable) or Numeric type (static angle)

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.CRy(control: int, target: int, angle: float) QCircuit[source]
+

Convenience initialization CRy (controlled Pauli Y Rotation)

+
+
Parameters:
+
    +
  • control (int) – control qubit

  • +
  • target (int) – target qubit

  • +
  • angle – Hashable type (will be treated as Variable) or Numeric type (static angle)

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.CRz(control: int, target: int, angle: float) QCircuit[source]
+

Convenience initialization CRz (controlled Pauli Z Rotation)

+
+
Parameters:
+
    +
  • control (int) – control qubit

  • +
  • target (int) – target qubit

  • +
  • angle – Hashable type (will be treated as Variable) or Numeric type (static angle)

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.CX(control: int, target: int) QCircuit[source]
+

Convenience initialization CX (CNOT)

+
+
Parameters:
+
    +
  • control (int) – control qubit

  • +
  • target (int) – target qubit

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.CY(control: int, target: int) QCircuit[source]
+

Convenience initialization CY (controlled Pauli Y)

+
+
Parameters:
+
    +
  • control (int) – control qubit

  • +
  • target (int) – target qubit

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.CZ(control: int, target: int) QCircuit[source]
+

Convenience initialization CZ (controlled Pauli Z)

+
+
Parameters:
+
    +
  • control (int) – control qubit

  • +
  • target (int) – target qubit

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.ExpPauli(paulistring: PauliString | str | dict, angle, control: list | int = None, *args, **kwargs)[source]
+

Exponentiated Pauligate:

+

ExpPauli(PauliString, angle) = exp(-i* angle/2* PauliString)

+
+
Parameters:
+
    +
  • paulistring (Union[PauliString :) – given as PauliString structure or as string or dict or list +if given as string: Format should be like X(0)Y(3)Z(2) +if given as list: Format should be like [(0,’X’),(3,’Y’),(2,’Z’)] +if given as dict: Format should be like { 0:’X’, 3:’Y’, 2:’Z’ }

  • +
  • angle – the angle (will be multiplied by paulistring coefficient if there is one)

  • +
  • control (Union[list :) – control qubits

  • +
  • paulistring

  • +
  • str]

  • +
  • control

  • +
  • int] – (Default value = None)

  • +
+
+
Returns:
+

Gate wrapped in circuit

+
+
Return type:
+

type

+
+
+
+ +
+
+tequila_code.circuit.gates.GenRot(*args, **kwargs)[source]
+
+ +
+
+tequila_code.circuit.gates.GeneralizedRotation(angle: List[Hashable] | List[Real], generator: QubitHamiltonian, control: list | int = None, eigenvalues_magnitude: float = 0.5, p0=None, steps: int = 1, assume_real=False) QCircuit[source]
+

Notes

+
+
A gates which is shift-rule differentiable
    +
  • its generator only has two distinguishable eigenvalues

  • +
  • it is then differentiable by the shift rule

  • +
  • eigenvalues_magnitude needs to be given upon initialization (this is “r” from Schuld et. al. and the default is r=1/2)

  • +
  • the generator will not (!) be verified to fullfill the properties

  • +
+

Compiling will be done in analogy to a trotterized gate with steps=1 as default

+
+
+

The gate will act in the same way as rotations and exppauli gates

+
+\[U_{G}(\text{angle}) = e^{-i\frac{\text{angle}}{2} G}\]
+
+
Parameters:
+
    +
  • angle – numeric type or hashable symbol or tequila objective

  • +
  • generator – tequila QubitHamiltonian or any other structure with paulistrings

  • +
  • control – list of control qubits

  • +
  • eigenvalues_magnitude – magnitude of eigenvalues, in most papers referred to as “r” (default 0.5)

  • +
  • p0 – possible nullspace projector (if the rotation is happens in Q = 1-P0). See arxiv:2011.05938

  • +
  • steps – possible Trotterization steps (default 1)

  • +
+
+
Return type:
+

The gate wrapped in a circuit

+
+
+
+ +
+
+tequila_code.circuit.gates.Givens(first: int, second: int, control: int | list = None, angle: float = None, *args, **kwargs) QCircuit[source]
+

Notes

+

Givens gate G +.. math:

+
G = e^{-i\theta \frac{(Y \otimes X - X \otimes Y )}{2}}
+
+
+
+
Parameters:
+
    +
  • first (int) – target qubit

  • +
  • second (int) – target qubit

  • +
  • control – int or list of ints

  • +
  • angle – numeric type (fixed exponent) or hashable type (parametrized exponent), theta in the above formula

  • +
+
+
Return type:
+

QCircuit

+
+
+
+ +
+
+tequila_code.circuit.gates.H(target: list | int, control: list | int = None, power=None, angle=None, *args, **kwargs) QCircuit[source]
+

Notes

+

Hadamard gate

+
+
Parameters:
+
    +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
  • power

    numeric type (fixed exponent) or hashable type (parametrized exponent) +angle +similar to power, but will be interpreted as +.. math:

    +
    U(\text{angle})=e^{-i\frac{angle}{2} generator}
    +
    +
    +

    the default is angle=pi +.. math:

    +
    U(\pi) = H
    +
    +
    +

    If angle and power are given both, tequila will combine them

    +

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.PauliGate(paulistring: PauliString | str | dict, control: list | int = None, *args, **kwargs) QCircuit[source]
+

Functions that converts a Pauli string into the corresponding quantum +circuit.

+
+
Parameters:
+
    +
  • paulistring (Union[PauliString , str, dict])

  • +
  • list (if given as)

  • +
  • string (if given as)

  • +
  • list

  • +
  • dict (if given as)

  • +
  • control (Union[list, int] : (Default value = None)) – control qubits

  • +
+
+
Raises:
+

Exception – Not a Pauli Operator.:

+
+
Returns:
+

U

+
+
Return type:
+

QCircuit object corresponding to the Pauli string.

+
+
+
+ +
+
+tequila_code.circuit.gates.Phase(target: list | int, control: list | int = None, angle: Hashable | Number = None, *args, **kwargs) QCircuit[source]
+

Notes

+

Initialize an abstract phase gate which acts as

+
+\[\begin{split}S(\phi) = \begin{pmatrix} 1 & 0 \\ 0 & e^{i\phi} \end{pmatrix}\end{split}\]
+
+
Parameters:
+
    +
  • angle – defines the phase, can be numeric type (static gate) or hashable non-numeric type (parametrized gate)

  • +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.PowerGate(name: str, target: list | int, power: float = None, control: list | int = None, generator: QubitHamiltonian = None, *args, **kwargs)[source]
+

Initialize a (potentially parametrized) gate which is supported on the backend

+
+
Parameters:
+
    +
  • name (str) – name of the gate on the backend (usually, H, X, Y, Z)

  • +
  • target – int or list of int

  • +
  • power – numeric type (fixed exponent) or hashable type (parametrized exponent) +will be interpreted as

  • +
  • angle

    similar to power, but will be interpreted as +.. math:

    +
    U=e^{-i\frac{angle}{2} generator}
    +
    +
    +

  • +
  • control – int or list of int

  • +
+
+
+
+ +
+
+tequila_code.circuit.gates.QGate(name, target: list | int, control: list | int = None, generator: QubitHamiltonian = None)[source]
+
+ +
+
+tequila_code.circuit.gates.QubitExcitation(angle: Real | Variable | Hashable, target: List, control=None, assume_real: bool = False, compile_options='optimize')[source]
+

A Qubit Excitation, as described under “qubit perspective” in https://doi.org/10.1039/D0SC06627C +For the Fermionic operators under corresponding Qubit encodings: Use the chemistry interface +:param angle: the angle of the excitation unitary +:param target: even number of qubit indices interpreted as [0,1,2,3….] = [(0,1), (2,3), …]

+
+

i.e. as qubit excitations from 0 to 1, 2 to 3, etc

+
+
+
Parameters:
+
    +
  • control – possible control qubits

  • +
  • assume_real – assume the wavefunction on which this acts is always real (cheaper gradients: see https://doi.org/10.1039/D0SC06627C)

  • +
+
+
Return type:
+

QubitExcitation gate wrapped into a tequila circuit

+
+
+
+ +
+
+class tequila_code.circuit.gates.QubitExcitationImpl(angle, target, generator=None, p0=None, assume_real=True, control=None, compile_options=None)[source]
+

Bases: GeneralizedRotationImpl

+
+
+compile(exponential_pauli=False, *args, **kwargs)[source]
+
+ +
+
+map_qubits(qubit_map: dict)[source]
+
+ +
+ +
+
+tequila_code.circuit.gates.RotationGate(axis: int, angle: Hashable | Number, target: list | int, control: list | int = None, assume_real=False)[source]
+

Notes

+

Initialize an abstract rotation gate of the form

+
+\[R_{\text{axis}}(\text{angle}) = e^{-i\frac{\text{angle}}{2} \sigma_{\text{axis}}}\]
+
+
Parameters:
+
    +
  • axis – integer 1 for x, 2 for y, 3 for z

  • +
  • angle – Hashable type (will be treated as Variable) or Numeric type (static angle)

  • +
  • target – integer or list of integers

  • +
  • control – integer or list of integers

  • +
  • assume_real – enable improved gradient compilation for controlled gates (wavefunction needs to be real)

  • +
+
+
Return type:
+

QCircuit object with this RotationGate

+
+
+
+ +
+
+tequila_code.circuit.gates.Rp(paulistring: PauliString | str, angle, control: list | int = None, *args, **kwargs)[source]
+

Same as ExpPauli

+
+ +
+
+tequila_code.circuit.gates.Rx(angle, target: list | int, control: list | int = None, assume_real=False) QCircuit[source]
+

Notes

+

Rx gate of the form

+
+\[R_{x}(\text{angle}) = e^{-i\frac{\text{angle}}{2} \sigma_{x}}\]
+
+
Parameters:
+
    +
  • angle – Hashable type (will be treated as Variable) or Numeric type (static angle)

  • +
  • target – integer or list of integers

  • +
  • control – integer or list of integers

  • +
  • assume_real – enable improved gradient compilation for controlled gates

  • +
+
+
Return type:
+

QCircuit object with this RotationGate

+
+
+
+ +
+
+tequila_code.circuit.gates.Ry(angle, target: list | int, control: list | int = None, assume_real=False) QCircuit[source]
+

Notes

+

Ry gate of the form

+
+\[R_{y}(\text{angle}) = e^{-i\frac{\text{angle}}{2} \sigma_{y}}\]
+
+
Parameters:
+
    +
  • angle – Hashable type (will be treated as Variable) or Numeric type (static angle)

  • +
  • target – integer or list of integers

  • +
  • control – integer or list of integers

  • +
+
+
Return type:
+

QCircuit object with this RotationGate

+
+
+
+ +
+
+tequila_code.circuit.gates.Rz(angle, target: list | int, control: list | int = None, assume_real=False) QCircuit[source]
+

Notes

+

Rz gate of the form

+
+\[R_{z}(\text{angle}) = e^{-i\frac{\text{angle}}{2} \sigma_{z}}\]
+
+
Parameters:
+
    +
  • angle – Hashable type (will be treated as Variable) or Numeric type (static angle)

  • +
  • target – integer or list of integers

  • +
  • control – integer or list of integers

  • +
  • Returns

  • +
  • RotationGate (QCircuit object with this)

  • +
  • -------

  • +
+
+
+
+ +
+
+tequila_code.circuit.gates.S(target: list | int, control: list | int = None) QCircuit[source]
+

Notes

+
+\[\begin{split}S = \begin{pmatrix} 1 & 0 \\ 0 & e^{i\frac{\pi}{2}} \end{pmatrix}\end{split}\]
+
+
Parameters:
+
    +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.SWAP(first: int, second: int, angle: float = None, control: int | list = None, power: float = None, *args, **kwargs) QCircuit[source]
+

Notes

+

SWAP gate, order of targets does not matter

+
+
Parameters:
+
    +
  • first (int) – target qubit

  • +
  • second (int) – target qubit

  • +
  • angle (numeric type or hashable type) – exponent in the for e^{-i a/2 G}

  • +
  • control – int or list of ints

  • +
  • power – numeric type (fixed exponent) or hashable type (parametrized exponent in the form (SWAP)^n

  • +
+
+
Return type:
+

QCircuit

+
+
+
+ +
+
+tequila_code.circuit.gates.T(target: list | int, control: list | int = None)[source]
+

Notes

+

Fixed phase gate

+
+\[\begin{split}T = \begin{pmatrix} 1 & 0 \\ 0 & e^{i\frac{\pi}{4}} \end{pmatrix}\end{split}\]
+
+
Parameters:
+
    +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.Toffoli(first: int, second: int, target: int) QCircuit[source]
+

Convenience Toffoli initialization

+
+
Parameters:
+
    +
  • first (int) – first control qubit

  • +
  • second (int) – second control qubit

  • +
  • target (int) – target qubit

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.Trotterized(generator: QubitHamiltonian = None, steps: int = 1, angle: Hashable | Real | Variable = None, control: list | int = None, randomize=False, *args, **kwargs) QCircuit[source]
+
+
+
generator :

generator of the gate U = e^{-i

+
+
+
+
+
rac{angle}{2} G }
+
angles :

coefficients for each generator

+
+
steps :

trotter steps

+
+
control :

control qubits

+
+
generators: QubitHamiltonian :

The generator of the gate

+
+
steps: int :

Trotter Steps

+
+
angle: typing.Hashable :

A symbol that will be converted to a tq.Variable

+
+
numbers.Real :

A fixed real number

+
+
Variable :

A tequila Variable

+
+
+

control: control qubits +Returns +——- +QCircuit

+
+
+
+ +
+
+tequila_code.circuit.gates.U(theta, phi, lambd, target: list | int, control: list | int = None) QCircuit[source]
+

Notes

+

Convenient gate, one of the abstract gates defined by OpenQASM.

+
+\[ \begin{align}\begin{aligned}\begin{split}U(\theta, \phi, \lambda) = R_z(\phi)R_x(-\pi/2)R_z(\theta)R_x(\pi/2)R_z(\lambda) +U(\theta, \phi, \lambda) = \begin{pmatrix} + e^{-i \frac{\phi}{2}} & 0 \\ + 0 & e^{i \frac{\phi}{2}} + \end{pmatrix} + \begin{pmatrix} + \cos{-\frac{\pi}{4}} & -i \sin{-\frac{\pi}{4}} \\ + -i \sin{-\frac{\pi}{4}} & \cos{-\frac{\pi}{4}} + \end{pmatrix} + \begin{pmatrix} + e^{-i \frac{\theta}{2}} & 0 \\ + 0 & e^{i \frac{\theta}{2}} + \end{pmatrix} + \begin{pmatrix} + \cos{\frac{\pi}{4}} & -i \sin{\frac{\pi}{4}} \\ + -i \sin{\frac{\pi}{4}} & \cos{\frac{\pi}{4}} + \end{pmatrix} + \begin{pmatrix} + e^{-i \frac{\lambda}{2}} & 0 \\ + 0 & e^{i \frac{\lambda}{2}} + \end{pmatrix}\end{split}\\\begin{split}U(\theta, \phi, \lambda) = \begin{pmatrix} + \cos{\frac{\theta}{2}} & + -e^{i \lambda} \sin{\frac{\theta}{2}} \\ + e^{i \phi} \sin{\frac{\theta}{2}} & + e^{i (\phi+\lambda)} \cos{\frac{\theta}{2}} + \end{pmatrix}\end{split}\end{aligned}\end{align} \]
+
+
Parameters:
+
    +
  • theta – first parameter angle

  • +
  • phi – second parameter angle

  • +
  • lamnd – third parameter angle

  • +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.X(target: list | int, control: list | int = None, power=None, angle=None, *args, **kwargs) QCircuit[source]
+

Notes

+

Pauli X Gate

+
+
Parameters:
+
    +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
  • power – numeric type (fixed exponent) or hashable type (parametrized exponent)

  • +
  • angle

    similar to power, but will be interpreted as +.. math:

    +
    U(\text{angle})=e^{-i\frac{angle}{2} (1-X)}
    +
    +
    +

    the default is angle=pi +.. math:

    +
    U(\pi) = X
    +
    +
    +

    If angle and power are given both, tequila will combine them

    +

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.Y(target: list | int, control: list | int = None, power=None, angle=None, *args, **kwargs) QCircuit[source]
+

Notes

+

Pauli Y Gate

+
+
Parameters:
+
    +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
  • power – numeric type (fixed exponent) or hashable type (parametrized exponent)

  • +
  • angle

    similar to power, but will be interpreted as +.. math:

    +
    U(\text{angle})=e^{-i\frac{angle}{2} (1-Y)}
    +
    +
    +

    the default is angle=pi +.. math:

    +
    U(\pi) = Y
    +
    +
    +

    If angle and power are given both, tequila will combine them

    +

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.Z(target: list | int, control: list | int = None, power=None, angle=None, *args, **kwargs) QCircuit[source]
+

Notes

+

Pauli Z Gate

+
+
Parameters:
+
    +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
  • power – numeric type (fixed exponent) or hashable type (parametrized exponent)

  • +
  • angle

    similar to power, but will be interpreted as +.. math:

    +
    U(\text{angle})=e^{-i\frac{angle}{2} (1-Z)}
    +
    +
    +

    the default is angle=pi +.. math:

    +
    U(\pi) = Z
    +
    +
    +

    If angle and power are given both, tequila will combine them

    +

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.iSWAP(first: int, second: int, control: int | list = None, power: float = 1.0, *args, **kwargs) QCircuit[source]
+

Notes

+

iSWAP gate +.. math:

+
iSWAP = e^{i\frac{\pi}{4} (X \otimes X + Y \otimes Y )}
+
+
+
+
Parameters:
+
    +
  • first (int) – target qubit

  • +
  • second (int) – target qubit

  • +
  • control – int or list of ints

  • +
  • power – numeric type (fixed exponent) or hashable type (parametrized exponent)

  • +
+
+
Return type:
+

QCircuit

+
+
+
+ +
+
+tequila_code.circuit.gates.u1(lambd, target: list | int, control: list | int = None) QCircuit[source]
+

Notes

+

Convenient gate, one of the abstract gates defined by Quantum Experience Standard Header. +Changes the phase of a carrier without applying any pulses.

+
+\[\begin{split}from OpenQASM 2.0 specification: + u1(\lambda) \sim U(0, 0, \lambda) = R_z(\lambda) = e^{-i\frac{\lambda}{2} \sigma_{z}} +also is equal to: + u1(\lambda) = \begin{pmatrix} 1 & 0 \\ 0 & e^{i\lambda} \end{pmatrix} +which is the Tequila Phase gate: + u1(\lambda) = Phase(\lambda)\end{split}\]
+
+
Parameters:
+
    +
  • lambd – parameter angle

  • +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.u2(phi, lambd, target: list | int, control: list | int = None) QCircuit[source]
+

Notes

+

Convenient gate, one of the abstract gates defined by Quantum Experience Standard Header. +Uses a single pi/2-pulse.

+
+\[ \begin{align}\begin{aligned}u2(\phi, \lambda) = U(\pi/2, \phi, \lambda) = R_z(\phi + \pi/2)R_x(\pi/2)R_z(\lambda - \pi/2)\\\begin{split}u2(\phi, \lambda) = \frac{1}{\sqrt{2}} + \begin{pmatrix} + 1 & -e^{i\lambda} \\ + e^{i\phi} & e^{i(\phi+\lambda)} + \end{pmatrix}\end{split}\end{aligned}\end{align} \]
+
+
Parameters:
+
    +
  • phi – first parameter angle

  • +
  • lambd – second parameter angle

  • +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+tequila_code.circuit.gates.u3(theta, phi, lambd, target: list | int, control: list | int = None) QCircuit[source]
+

Notes

+

Convenient gate, one of the abstract gates defined by Quantum Experience Standard Header +The most general single-qubit gate. +Uses a pair of pi/2-pulses.

+
+\[\begin{split}u3(\theta, \phi, \lambda) = U(\theta, \phi, \lambda) + = \begin{pmatrix} + \cos{\frac{\5theta}{2}} & + -e^{i \lambda} \sin{\frac{\theta}{2}} \\ + e^{i \phi} \sin{\frac{\theta}{2}} & + e^{i (\phi+\lambda)} \cos{\frac{\theta}{2}} + \end{pmatrix}\end{split}\]
+
+
Parameters:
+
    +
  • theta – first parameter angle

  • +
  • phi – second parameter angle

  • +
  • lambd – third parameter angle

  • +
  • target – int or list of int

  • +
  • control – int or list of int

  • +
+
+
Return type:
+

QCircuit object

+
+
+
+ +
+
+

gradient module

+
+
+tequila_code.circuit.gradient.grad(objective: Objective | QTensor, variable: Variable = None, no_compile=False, *args, **kwargs)[source]
+

wrapper function for getting the gradients of Objectives,ExpectationValues, Unitaries (including single gates), and Transforms. +:param obj (QCircuit,ParametrizedGateImpl,Objective,ExpectationValue,Transform,Variable): structure to be differentiated +:param variables (list of Variable): parameter with respect to which obj should be differentiated.

+
+

default None: total gradient.

+
+

return: dictionary of Objectives, if called on gate, circuit, exp.value, or objective; if Variable or Transform, returns number.

+
+ +
+
+

noise module

+
+
+tequila_code.circuit.noise.AmplitudeDamp(p: float, level: int)[source]
+

Returns a NoiseModel one QuantumNoise, corresponding to amplitude damping. +this channel takes 1 to 0, but leaves 0 unaffected. +kraus maps:

+
+
E_0= [[1,0],

[0,sqrt(1-p)]]

+
+
E_1= [[0,sqrt(p)],

[0,0]]

+
+
+
+
Parameters:
+
    +
  • p (float:) – the probability with which the noise is applied.

  • +
  • level (int:) – the # of qubits in operations to apply this noise to.

  • +
+
+
Return type:
+

NoiseModel

+
+
+
+ +
+
+tequila_code.circuit.noise.BitFlip(p: float, level: int)[source]
+

Returns a NoiseModel with one QuantumNoise, having a kraus map corresponding to applying pauli X with likelihood p.

+
+
Parameters:
+
    +
  • p (float:) – the probability with which the noise is applied.

  • +
  • level (int:) – the # of qubits in operations to apply this noise to.

  • +
+
+
Return type:
+

NoiseModel

+
+
+
+ +
+
+tequila_code.circuit.noise.DepolarizingError(p: float, level: int)[source]
+

Returns a NoiseModel with one QuantumNoise, having a kraus map corresponding to equal +probabilities of each of the three pauli matrices being applied.

+
+
Parameters:
+
    +
  • p (float:) – the probability with which the noise is applied.

  • +
  • level (int:) – the # of qubits in operations to apply this noise to.

  • +
+
+
Return type:
+

NoiseModel

+
+
+
+ +
+
+class tequila_code.circuit.noise.NoiseModel(noises: List[dict | QuantumNoise] = None)[source]
+

Bases: object

+

class representing noises to apply to a quantum circuit during simulation.

+
+
+noises
+

a list of all the noises to apply.

+
+ +
+
+without_noise_on_level:
+

remove all noise affecting operations with <level> qubits.

+
+ +
+
+without_noise_op:
+

remove all noise of a given type, I.E get rid of all bit flips.

+
+ +
+
+without_noise_on_level(level)[source]
+
+ +
+
+without_noise_op(name)[source]
+
+ +
+
+static wrap_noise(other)[source]
+
+ +
+ +
+
+tequila_code.circuit.noise.PhaseAmplitudeDamp(p1: float, p2: float, level: int)[source]
+

Returns a NoiseModel with one QuantumNoise, having a kraus map corresponding to phase and amplitude damping.

+
+
Parameters:
+
    +
  • p1 (float:) – the probability with which phase is damped

  • +
  • p2 (float:) – the probability with which amplitude is damped

  • +
  • level (int:) – the # of qubits in operations to apply this noise to.

  • +
+
+
Return type:
+

NoiseModel

+
+
+
+ +
+
+tequila_code.circuit.noise.PhaseDamp(p: float, level: int)[source]
+

Returns a NoiseModel of one QuantumNoise, having a kraus map corresponding to phase damping; +Krauss map is defined following Nielsen and Chuang; +E_0= [[1,0],

+
+

[0,sqrt(1-p)]]

+
+
+
E_1= [[0,0],

[0,sqrt(p)]]

+
+
+
+
Parameters:
+
    +
  • p (float:) – the probability with which the noise is applied.

  • +
  • level (int:) – the # of qubits in operations to apply this noise to.

  • +
+
+
Return type:
+

NoiseModel

+
+
+
+ +
+
+tequila_code.circuit.noise.PhaseFlip(p: float, level: int)[source]
+

Returns a NoiseModel of one QuantumNoise, having a kraus map corresponding to applying pauli Z with likelihood p.

+
+
Parameters:
+
    +
  • p (float:) – the probability with which the noise is applied.

  • +
  • level (int:) – the # of qubits in operations to apply this noise to.

  • +
+
+
Return type:
+

NoiseModel

+
+
+
+ +
+
+class tequila_code.circuit.noise.QuantumNoise(name: str, probs: List[float], level: int)[source]
+

Bases: object

+

class representing a specific quantum noise operation on gates of a certain number of qubits.

+
+
+name
+

what noise to apply

+
+ +
+
+probs
+

the probabilities with which to apply the noise

+
+ +
+
+level
+

the number of qubits in the gates this noise acts upon

+
+ +
+
+from_dict:
+

initialize from a dictionary.

+
+ +
+
+static from_dict(d)[source]
+
+ +
+
+property level
+
+ +
+
+property name
+
+ +
+
+prob_length = {'amplitude damp': 1, 'bit flip': 1, 'depolarizing': 1, 'phase damp': 1, 'phase flip': 1, 'phase-amplitude damp': 2}
+
+ +
+ +
+
+

pyzx module

+

Add to tequila the ability to make ZX-Calculus

+

Using the pyzx library: https://github.com/Quantomatic/pyzx

+
+
+tequila_code.circuit.pyzx.convert_from_pyzx(circuit) QCircuit[source]
+

Allow convert from pyzx circuit to Tequila circuit

+
+
Parameters:
+

circuit – in pyzx format (pyzx.circuit.Circuit) to be exported to Tequila circuit

+
+
Returns:
+

Tequila circuit

+
+
Return type:
+

QCircuit

+
+
+
+ +
+
+tequila_code.circuit.pyzx.convert_to_pyzx(circuit: QCircuit, variables=None)[source]
+

Allow convert from Tequila circuit to pyzx circuit

+
+
Parameters:
+
    +
  • circuit – in Tequila format to be exported to pyzx

  • +
  • variables – optional dictionary with values for variables

  • +
+
+
Returns:
+

pyzx circuit

+
+
Return type:
+

pyzx.circuit.Circuit

+
+
+
+ +
+
+

qasm module

+

Export QCircuits as qasm code

+

OPENQASM version 2.0 specification from: +A. W. Cross, L. S. Bishop, J. A. Smolin, and J. M. Gambetta, e-print arXiv:1707.03429v2 [quant-ph] (2017). +https://arxiv.org/pdf/1707.03429v2.pdf

+
+
+tequila_code.circuit.qasm.apply_custom_gate(custom_circuit: QCircuit, qregisters_values: list) QCircuit[source]
+
+ +
+
+tequila_code.circuit.qasm.convert_to_open_qasm_2(circuit: QCircuit, variables=None, zx_calculus: bool = False) str[source]
+

Allow export to OpenQASM version 2.0

+
+
Parameters:
+
    +
  • circuit – to be exported to OpenQASM

  • +
  • variables – optional dictionary with values for variables

  • +
  • zx_calculus – indicate if y-gates must be transformed to xz equivalents

  • +
+
+
Returns:
+

OpenQASM string

+
+
Return type:
+

str

+
+
+
+ +
+
+tequila_code.circuit.qasm.export_open_qasm(circuit: QCircuit, variables=None, version: str = '2.0', filename: str = None, zx_calculus: bool = False) str[source]
+

Allow export to different versions of OpenQASM

+
+
Parameters:
+
    +
  • circuit – to be exported to OpenQASM

  • +
  • variables – optional dictionary with values for variables

  • +
  • version – of the OpenQASM specification, optional

  • +
  • filename – optional file name to save the generated OpenQASM code

  • +
  • zx_calculus – indicate if y-gates must be transformed to xz equivalents

  • +
+
+
Returns:
+

OpenQASM string

+
+
Return type:
+

str

+
+
+
+ +
+
+tequila_code.circuit.qasm.get_angle(name: str) list[source]
+
+ +
+
+tequila_code.circuit.qasm.get_qregister(qreg: str, qregisters: Dict[str, int]) list | int[source]
+
+ +
+
+tequila_code.circuit.qasm.import_open_qasm(qasm_code: str, version: str = '2.0', rigorous: bool = True) QCircuit[source]
+

Allow import from different versions of OpenQASM

+
+
Parameters:
+
    +
  • qasm_code – string with the OpenQASM code

  • +
  • version – of the OpenQASM specification, optional

  • +
  • rigorous – indicates whether the QASM code should be read rigorously

  • +
+
+
Returns:
+

equivalent to the OpenQASM code received

+
+
Return type:
+

QCircuit

+
+
+
+ +
+
+tequila_code.circuit.qasm.import_open_qasm_from_file(filename: str, version: str = '2.0', rigorous: bool = True) QCircuit[source]
+

Allow import from different versions of OpenQASM from a file

+
+
Parameters:
+
    +
  • filename – string with the file name with the OpenQASM code

  • +
  • variables – optional dictionary with values for variables

  • +
  • version – of the OpenQASM specification, optional

  • +
  • rigorous – indicates whether the QASM code should be read rigorously

  • +
+
+
Returns:
+

equivalent to the OpenQASM code received

+
+
Return type:
+

QCircuit

+
+
+
+ +
+
+tequila_code.circuit.qasm.name_and_params(g, variables)[source]
+

Determines the quantum gate name and its parameters if applicable

+
+
Parameters:
+
    +
  • g – gate to get its name

  • +
  • variables – dictionary with values for variables

  • +
+
+
Returns:
+

name (and parameter) to the gate specified

+
+
Return type:
+

str

+
+
+
+ +
+
+tequila_code.circuit.qasm.parse_command(command: str, custom_gates_map: Dict[str, QCircuit], qregisters: Dict[str, int]) QCircuit[source]
+

Parse qasm code command

+
+
Parameters:
+
    +
  • command – open qasm code to be parsed

  • +
  • custom_gates_map – map with custom gates

  • +
+
+
+
+ +
+
+tequila_code.circuit.qasm.parse_custom_gate(gate_custom: str, custom_gates_map: ~typing.Dict[str, ~tequila.circuit.circuit.QCircuit]) -> (<class 'str'>, <class 'tequila.circuit.circuit.QCircuit'>)[source]
+

Parse custom gates code

+
+
Parameters:
+

gate_custom – code with custom gates

+
+
+
+ +
+
+tequila_code.circuit.qasm.parse_from_open_qasm_2(qasm_code: str, rigorous: bool = True) QCircuit[source]
+
+ +
+
+

qpic module

+

Export QCircuits as qpic files +https://github.com/qpic/qpic/blob/master/doc/qpic_doc.pdf

+
+
+tequila_code.circuit.qpic.assign_name(parameter)[source]
+
+ +
+
+tequila_code.circuit.qpic.export_to(circuit, filename: str, style='tequila', qubit_names: list = None, *args, **kwargs)[source]
+
+
Parameters:
+
    +
  • circuit – the tequila circuit to export

  • +
  • filename – filename.filetype, e.g. my_circuit.pdf, my_circuit.png (everything that qpic supports)

  • +
  • style – string keyword (tequila, standard, generators) or dictionary containing the following keys: +always_use_generators: represent all gates with their generators +decompose_control_generators: Decompose the controls to generators. Effective only in combination with always_use_generators=True. +group_together: Keep PauliStrings from the same generator together. Effective only in combination with always_use_generators=True. +possible values: False, True, ‘TOUCH’ and ‘BARRIER’. True is the same as TOUCH. +BARRIER will create a visible barrier in qpic

  • +
  • args

  • +
  • kwargs

  • +
+
+
+
+ +
+
+tequila_code.circuit.qpic.export_to_qpic(circuit, filename=None, filepath=None, always_use_generators=True, decompose_control_generators=False, group_together=False, qubit_names=None, mark_parametrized_gates=True, gatecolor1='tq', textcolor1='white', gatecolor2='guo', textcolor2='black', *args, **kwargs) str[source]
+
+ +
+
+

Module contents

+
+
+tequila_code.circuit.compile_circuit(U, *args, **kwargs)[source]
+
+ +
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/docu_instruction.html b/docs/sphinx/docu_instruction.html new file mode 100644 index 0000000..da0b238 --- /dev/null +++ b/docs/sphinx/docu_instruction.html @@ -0,0 +1,244 @@ + + + + + + + + + Documenting Code in reStructuredText for Sphinx — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Documenting Code in reStructuredText for Sphinx

+
+

Introduction

+

Sphinx supports automatic code documentation using the autodoc extension, which extracts docstrings from your code and integrates them into your documentation. This guide explains how to structure your code comments using reStructuredText to ensure your documentation is well-formatted and informative.

+
+
+

1. Setting Up the Documentation

+

Before you start documenting, make sure you have the Sphinx project and autodoc enabled in your conf.py:

+
# In conf.py, ensure these extensions are present
+extensions = [
+    'sphinx.ext.autodoc',
+    'sphinx.ext.napoleon',  # Optional: For Google/NumPy style docstrings
+]
+
+
+
+
+

2. Writing Docstrings with reStructuredText

+

reStructuredText is a lightweight markup language used in docstrings. Here’s how to write effective docstrings for different parts of your code.

+

2.1 Module-Level Docstring

+

At the top of your module (mymodule.py), include a general description:

+
"""
+mymodule.py
+===========
+
+This module contains functions and classes for data processing.
+"""
+
+
+

2.2 Documenting Functions

+

Describe the function’s purpose, parameters, and return values. Use the following format:

+
def add_numbers(a, b):
+    """
+    Adds two numbers together.
+
+    :param int a: The first number.
+    :param int b: The second number.
+    :returns: The sum of `a` and `b`.
+    :rtype: int
+    """
+    return a + b
+
+
+

2.3 Documenting Classes

+

For classes, include a class-level docstring and document each method:

+
class Calculator:
+    """
+    A simple calculator class to perform basic arithmetic operations.
+
+    :param str name: The name of the calculator instance.
+    """
+
+    def __init__(self, name):
+        """
+        Initializes the calculator with a given name.
+        """
+        self.name = name
+
+    def multiply(self, x, y):
+        """
+        Multiplies two numbers.
+
+        :param int x: The first factor.
+        :param int y: The second factor.
+        :returns: The product of `x` and `y`.
+        :rtype: int
+        """
+        return x * y
+
+
+

2.4 Documenting Class Attributes

+

Use the :ivar directive to describe class attributes:

+
class Rectangle:
+    """
+    Represents a geometric rectangle.
+
+    :ivar float length: The length of the rectangle.
+    :ivar float width: The width of the rectangle.
+    """
+    def __init__(self, length, width):
+        self.length = length
+        self.width = width
+
+
+
+
+

3. Formatting Docstrings

+

3.1 Sections

+

Use specific section headers (optional but recommended):

+
    +
  • Parameters

  • +
  • Returns

  • +
  • Raises (for exceptions)

  • +
+

Example:

+
def divide(x, y):
+    """
+    Divides `x` by `y`.
+
+    **Parameters:**
+
+    - `x (float)`: Numerator.
+    - `y (float)`: Denominator.
+
+    **Returns:**
+
+    - `float`: The result of division.
+
+    **Raises:**
+
+    - `ZeroDivisionError`: If `y` is zero.
+    """
+    if y == 0:
+        raise ZeroDivisionError("Cannot divide by zero.")
+    return x / y
+
+
+

3.2 Cross-referencing

+

To reference other parts of the code, use the :class:, :func: and similar directives:

+
"""
+See also :class:`Calculator` for more operations.
+"""
+
+
+
+
+

4. Building the Documentation

+

Once your code is documented, build the documentation to see the results:

+
make html
+
+
+

This will generate the HTML files in the _build directory, integrating your code comments into the documentation.

+
+
+

5. Cleaning the Build Directory

+

If you need to rebuild the documentation from scratch, use:

+
make clean
+
+
+

This removes all previously built files.

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/genindex.html b/docs/sphinx/genindex.html new file mode 100644 index 0000000..cefd45a --- /dev/null +++ b/docs/sphinx/genindex.html @@ -0,0 +1,2024 @@ + + + + + + + + Index — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Index

+ +
+ A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | K + | L + | M + | N + | O + | P + | Q + | R + | S + | T + | U + | V + | W + | X + | Y + | Z + +
+

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

J

+ + +
+ +

K

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

N

+ + + +
+ +

O

+ + + +
+ +

P

+ + + +
+ +

Q

+ + + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
    +
  • T() (in module tequila_code.circuit.gates) +
  • +
  • TaperedBravyKitaev (class in tequila_code.quantumchemistry.encodings) +
  • +
  • + tequila_code.circuit + +
  • +
  • + tequila_code.circuit.circuit + +
  • +
  • + tequila_code.circuit.compiler + +
  • +
  • + tequila_code.circuit.gates + +
  • +
  • + tequila_code.circuit.gradient + +
  • +
  • + tequila_code.circuit.noise + +
  • +
  • + tequila_code.circuit.pyzx + +
  • +
  • + tequila_code.circuit.qasm + +
  • +
  • + tequila_code.circuit.qpic + +
  • +
  • + tequila_code.hamiltonian + +
  • +
  • + tequila_code.hamiltonian.paulis + +
  • +
  • + tequila_code.hamiltonian.paulistring + +
  • +
  • + tequila_code.optimizers + +
  • +
  • + tequila_code.optimizers.optimizer_base + +
  • +
  • + tequila_code.optimizers.optimizer_gd + +
  • +
  • + tequila_code.optimizers.optimizer_scipy + +
  • +
  • + tequila_code.quantumchemistry + +
  • +
  • + tequila_code.quantumchemistry.chemistry_tools + +
  • +
  • + tequila_code.quantumchemistry.encodings + +
  • +
  • + tequila_code.quantumchemistry.madness_interface + +
  • +
  • + tequila_code.quantumchemistry.orbital_optimizer + +
  • +
+ +

U

+ + + +
+ +

V

+ + + +
+ +

W

+ + + +
+ +

X

+ + +
+ +

Y

+ + +
+ +

Z

+ + + +
+ + + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/hamiltonian.html b/docs/sphinx/hamiltonian.html new file mode 100644 index 0000000..4a0c157 --- /dev/null +++ b/docs/sphinx/hamiltonian.html @@ -0,0 +1,393 @@ + + + + + + + + + Hamiltonian — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Hamiltonian

+
+

Submodules

+
+
+

paulis module

+

Convenience initialization +of Pauli Operators. Resulting structures can be added and multiplied together. +Currently uses OpenFermion as backend (QubitOperators)

+
+
+tequila_code.hamiltonian.paulis.I(*args, **kwargs) QubitHamiltonian[source]
+

Initialize unit Operator

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.KetBra(ket: QubitWaveFunction, bra: QubitWaveFunction, hermitian: bool = False, threshold: float = 1e-06, n_qubits=None)[source]
+

Notes

+

Initialize the general KetBra operator +.. math:

+
H = \lvert ket \rangle \langle bra \rvert
+
+
+

e.g. +wfn1 = tq.QubitWaveFunction.from_string(“1.0*|00> + 1.0*|11>”).normalize() +wfn2 = tq.QubitWaveFunction.from_string(“1.0*|00>”) +operator = tq.paulis.KetBra(ket=wfn1, bra=wfn1) +initializes the transfer operator from the all-zero state to a Bell state

+
+
Parameters:
+
    +
  • ket (QubitWaveFunction:) – QubitWaveFunction which defines the ket element +can also be given as string or array or integer

  • +
  • bra (QubitWaveFunction:) – QubitWaveFunction which defines the bra element +can also be given as string or array or integer

  • +
  • hermitian (bool: (Default False)) – if True the hermitian version H + H^dagger is returned

  • +
  • threshold (float: (Default 1.e-6)) – elements smaller than the threshold will be ignored

  • +
  • n_qubits (only needed if ket and/or bra are passed down as integers)

  • +
+
+
Returns:
+

a tequila QubitHamiltonian (not necessarily hermitian) representing the KetBra operator desired.

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.Projector(wfn, threshold=0.0, n_qubits=None) QubitHamiltonian[source]
+

Notes

+

Initialize a projector given by

+
+\[H = \lvert \Psi \rangle \langle \Psi \rvert\]
+
+
Parameters:
+

wfn (QubitWaveFunction or int, or string, or array :) – The wavefunction onto which the projector projects +Needs to be passed down as tequilas QubitWaveFunction type +See the documentation on how to initialize a QubitWaveFunction from +integer, string or array (can also be passed down diretly as one of those types)

+
+
+
+
threshold: float: (Default value = 0.0)

neglect small parts of the operator

+
+
+

n_qubits: only needed when an integer is given as wavefunction

+
+ +
+
+tequila_code.hamiltonian.paulis.Qm(qubit) QubitHamiltonian[source]
+

Notes

+

Initialize

+
+\[\frac{1}{2} \left( 1 + \sigma_z \right)\]
+
+
Parameters:
+

qubit (int or list of ints) – qubit(s) on which the operator should act

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.Qp(qubit) QubitHamiltonian[source]
+

Notes

+

Initialize

+
+\[\frac{1}{2} \left( 1 - \sigma_z \right)\]
+
+
Parameters:
+

qubit (int or list of ints) – qubit(s) on which the operator should act

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.Sm(qubit) QubitHamiltonian[source]
+

Notes

+

Initialize

+
+\[\frac{1}{2} \left( \sigma_x - i \sigma_y \right)\]
+
+
Parameters:
+

qubit (int or list of ints) – qubit(s) on which the operator should act

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.Sp(qubit) QubitHamiltonian[source]
+

Notes

+

Initialize

+
+\[\frac{1}{2} \left( \sigma_x + i\sigma_y \right)\]
+
+
Parameters:
+

qubit (int or list of ints) – qubit(s) on which the operator should act

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.X(qubit) QubitHamiltonian[source]
+

Initialize a single Pauli X Operator

+
+
Parameters:
+

qubit (int or list of ints) – qubit(s) on which the operator should act

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.Y(qubit) QubitHamiltonian[source]
+

Initialize a single Pauli Y Operator

+
+
Parameters:
+

qubit (int or list of ints) – qubit(s) on which the operator should act

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.Z(qubit) QubitHamiltonian[source]
+

Initialize a single Pauli Z Operator

+
+
Parameters:
+

qubit (int or list of ints) – qubit(s) on which the operator should act

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.Zero(*args, **kwargs) QubitHamiltonian[source]
+

Initialize 0 Operator

+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.decompose_transfer_operator(ket: BitString, bra: BitString, qubits: List[int] = None) QubitHamiltonian[source]
+

Notes

+

Create the operator

+

Note that this is operator is not necessarily hermitian +So be careful when using it as a generator for gates

+

e.g. +decompose_transfer_operator(ket=”01”, bra=”10”, qubits=[2,3]) +gives the operator

+
+\[\lvert 01 \rangle \langle 10 \rvert_{2,3}\]
+

acting on qubits 2 and 3

+
+
Parameters:
+
    +
  • ket (pass an integer, string, or tequila BitString)

  • +
  • bra (pass an integer, string, or tequila BitString)

  • +
  • qubits (pass the qubits onto which the operator acts)

  • +
+
+
+
+ +
+
+tequila_code.hamiltonian.paulis.from_string(string, openfermion_format=False)[source]
+
+ +
+
+tequila_code.hamiltonian.paulis.pauli(qubit, type) QubitHamiltonian[source]
+
+
Parameters:
+
    +
  • qubit (int or list of ints)

  • +
  • type (str or int or list of strquaing or int:) – define if X, Y or Z (0,1,2)

  • +
+
+
Return type:
+

QubitHamiltonian

+
+
+
+ +
+
+

paulistring module

+
+
+

qubit-hamiltonian module

+
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/index.html b/docs/sphinx/index.html new file mode 100644 index 0000000..41af464 --- /dev/null +++ b/docs/sphinx/index.html @@ -0,0 +1,129 @@ + + + + + + + + + Tequila Documentation — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Tequila Documentation

+

Welcome to the Tequila Documentation website. +This website provides comprehensive information about the modules available in Tequila, +including a detailed overview of each module’s functions and instructions on how to utilise them correctly.

+

Additionally, there are practical tutorials that illustrate the capabilities of Tequila.

+ +
+

Practical Tutorials

+

Tutorials Website

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/modules.html b/docs/sphinx/modules.html new file mode 100644 index 0000000..1fa4c54 --- /dev/null +++ b/docs/sphinx/modules.html @@ -0,0 +1,955 @@ + + + + + + + + + Tequila Library Reference — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Tequila Library Reference

+
+ +
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/objects.inv b/docs/sphinx/objects.inv new file mode 100644 index 0000000..f2f00f1 Binary files /dev/null and b/docs/sphinx/objects.inv differ diff --git a/docs/sphinx/optimizers.html b/docs/sphinx/optimizers.html new file mode 100644 index 0000000..b1818c6 --- /dev/null +++ b/docs/sphinx/optimizers.html @@ -0,0 +1,1083 @@ + + + + + + + + + Optimizers — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Optimizers

+
+

Submodules

+
+
+

optimizer base module

+

Base class for Optimizers.

+
+
+class tequila_code.optimizers.optimizer_base.Optimizer(backend: str = None, maxiter: int = None, samples: int = None, device: str = None, noise=None, save_history: bool = True, silent: bool | int = False, print_level: int = 99, *args, **kwargs)[source]
+

Bases: object

+

The base optimizer class, from which other optimizers inherit.

+
+
+backend
+

The quantum backend to use (None means autopick)

+
+ +
+
+maxiter
+

Maximum number of iterations to perform.

+
+ +
+
+silent
+

whether or not to print during call or on init.

+
+ +
+
+samples
+

number of samples to call objectives with during call.

+
+ +
+
+print_level
+

Allow customization of printout in derived classes, is set to 0 if silent==True.

+
+ +
+
+save_history
+

whether or not to save history.

+
+ +
+
+history
+

a history object, saving information during optimization.

+
+ +
+
+noise
+

what noise (e.g, a NoiseModel) to apply to simulations during optimization.

+
+ +
+
+device
+

the device that sampling (real or emulated) should be performed on.

+
+ +
+
+reset_history:
+

reset the optimizer history.

+
+ +
+
+initialize_variables:
+

convenience: format variables of an objective and segregrate actives from passives.

+
+ +
+
+compile_objective:
+

convenience: compile an objective.

+
+ +
+
+compile_gradient:
+

convenience: build and compile (i.e render callable) the gradient of an objective.

+
+ +
+
+compile_hessian:
+

convenience: build and compile (i.e render callable) the hessian of an objective.

+
+ +
+
+compile_gradient(objective: Objective, variables: List[Variable], gradient=None, *args, **kwargs) Tuple[Dict, Dict][source]
+

convenience function to compile gradient objects and relavant types. For use by inheritors.

+
+
Parameters:
+
    +
  • objective (Objective:) – the objective whose gradient is to be calculated.

  • +
  • variables (list:) – the variables to take gradients with resepct to.

  • +
  • gradient – special argument to change what structure is used to calculate the gradient, like numerical, or QNG. +Default: use regular, analytic gradients.

  • +
  • optional – special argument to change what structure is used to calculate the gradient, like numerical, or QNG. +Default: use regular, analytic gradients.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

both the uncompiled and compiled gradients of objective, w.r.t variables.

+
+
Return type:
+

tuple

+
+
+
+ +
+
+compile_hessian(variables: List[Variable], grad_obj: Dict[Variable, Objective], comp_grad_obj: Dict[Variable, Objective], hessian: dict = None, *args, **kwargs) tuple[source]
+

convenience function to compile hessians for optimizers which require it. +:param variables: the variables of the hessian. +:param grad_obj: the gradient object, to be differentiated once more +:param comp_grad_obj: the compiled gradient object, used for further compilation of the hessian. +:param hessian: extra information to modulate compilation of the hessian. +:type hessian: optional: +:param args: +:param kwargs:

+
+
Returns:
+

uncompiled and compiled hessian objects, in that order

+
+
Return type:
+

tuple

+
+
+
+ +
+
+compile_objective(objective: Objective, *args, **kwargs)[source]
+

convenience function to wrap over compile; for use by inheritors. +:param objective: an objective to compile. +:type objective: Objective: +:param args: +:param kwargs:

+
+
Returns:
+

a compiled Objective. Types vary.

+
+
Return type:
+

Objective

+
+
+
+ +
+
+initialize_variables(objective, initial_values, variables)[source]
+

Convenience function to format the variables of some objective recieved in calls to optimzers.

+
+
Parameters:
+
    +
  • objective (Objective:) – the objective being optimized.

  • +
  • initial_values (dict or string:) – initial values for the variables of objective, as a dictionary. +if string: can be zero or random +if callable: custom function that initializes when keys are passed +if None: random initialization between 0 and 2pi (not recommended)

  • +
  • variables (list:) – the variables being optimized over.

  • +
+
+
Returns:
+

active_angles, a dict of those variables being optimized. +passive_angles, a dict of those variables NOT being optimized. +variables: formatted list of the variables being optimized.

+
+
Return type:
+

tuple

+
+
+
+ +
+
+reset_history()[source]
+

replace self.history with a blank history.

+
+
Return type:
+

None

+
+
+
+ +
+ +
+
+class tequila_code.optimizers.optimizer_base.OptimizerHistory(energies: ~typing.List[~numbers.Real] = <factory>, gradients: ~typing.List[~typing.Dict[str, ~numbers.Real]] = <factory>, angles: ~typing.List[~typing.Dict[str, ~numbers.Number]] = <factory>, energy_calls: ~typing.List[~numbers.Real] = <factory>, gradient_calls: ~typing.List[~typing.Dict[str, ~numbers.Real]] = <factory>, angles_calls: ~typing.List[~typing.Dict[str, ~numbers.Number]] = <factory>)[source]
+

Bases: object

+

A class representing the history of optimizers over time. Has a variety of convenience functions attached to it.

+
+
+angles: List[Dict[str, Number]]
+
+ +
+
+angles_calls: List[Dict[str, Number]]
+
+ +
+
+energies: List[Real]
+
+ +
+
+property energies_calls
+
+ +
+
+property energies_evaluations
+
+ +
+
+energy_calls: List[Real]
+
+ +
+
+extract_angles(key: str) Dict[Integral, Real][source]
+

convenience function to get the value of some variable out of the history.

+
+
Parameters:
+

key (str:) – name of the variable whose values are sought

+
+
Returns:
+

a dictionary, representing the value of variable ‘key’ over time.

+
+
Return type:
+

dict

+
+
+
+ +
+
+extract_energies(*args, **kwargs) Dict[Integral, Real][source]
+

convenience function to get the energies back as a dictionary.

+
+ +
+
+extract_gradients(key: str) Dict[Integral, Real][source]
+

convenience function to get the gradients of some variable out of the history. +:param key: the name of the variable whose gradients are sought +:type key: str:

+
+
Returns:
+

a dictionary, representing the gradient of variable ‘key’ over time.

+
+
Return type:
+

dict

+
+
+
+ +
+
+gradient_calls: List[Dict[str, Real]]
+
+ +
+
+gradients: List[Dict[str, Real]]
+
+ +
+
+property iterations
+
+ +
+
+plot(property: str | List[str] = 'energies', key: str = None, filename=None, baselines: Dict[str, float] = None, *args, **kwargs)[source]
+

Convenience function to plot the progress of the optimizer over time. +:param property: which property (eg angles, energies, gradients) to plot.

+
+

Default: plot energies over time.

+
+
+
Parameters:
+
    +
  • key (str, optional:) – if property is ‘angles’ or ‘gradients’, key allows you to plot just an individual variables’ property. +Default: plot everything

  • +
  • filename – if give, plot to this file; else, plot to terminal. +Default: plot to terminal.

  • +
  • optional – if give, plot to this file; else, plot to terminal. +Default: plot to terminal.

  • +
  • baselines (dict, optional:) – dictionary of plotting axis baseline information. +Default: use whatever matplotlib auto-generates.

  • +
  • args – args.

  • +
  • kwargs – kwargs.

  • +
+
+
Return type:
+

None

+
+
+
+ +
+ +
+
+class tequila_code.optimizers.optimizer_base.OptimizerResults(energy: float = None, history: tequila_code.optimizers.optimizer_base.OptimizerHistory = None, variables: dict = None)[source]
+

Bases: object

+
+
+property angles
+
+ +
+
+energy: float = None
+
+ +
+
+history: OptimizerHistory = None
+
+ +
+
+variables: dict = None
+
+ +
+ +
+
+exception tequila_code.optimizers.optimizer_base.TequilaOptimizerException(msg)[source]
+

Bases: TequilaException

+
+ +
+
+

optimizer gradient module

+
+
+class tequila_code.optimizers.optimizer_gd.DIIS(ndiis: int = 8, min_vectors: int = 3, tol: float = 0.05, drop: str = 'error')[source]
+

Bases: object

+
+
+do_diis() bool[source]
+

Return with DIIS should be performed.

+
+ +
+
+drop_error(p: Sequence[ndarray], e: Sequence[ndarray]) Tuple[List[ndarray], List[ndarray]][source]
+

Return P,E with the largest magnitude error vector removed.

+
+ +
+
+drop_first(p: Sequence[ndarray], e: Sequence[ndarray]) Tuple[List[ndarray], List[ndarray]][source]
+

Return P,E with the first element removed.

+
+ +
+
+push(param_vector: ndarray, error_vector: ndarray) None[source]
+

Update DIIS calculator with parameter and error vectors.

+
+ +
+
+reset() None[source]
+

Reset containers.

+
+ +
+
+update() ndarray | None[source]
+

Get update parameter from DIIS iteration, or None if DIIS is not doable.

+
+ +
+ +
+
+class tequila_code.optimizers.optimizer_gd.GDResults(energy: float = None, history: tequila_code.optimizers.optimizer_base.OptimizerHistory = None, variables: dict = None, moments: dict = None, num_iteration: int = 0)[source]
+

Bases: OptimizerResults

+
+
+moments: dict = None
+
+ +
+
+num_iteration: int = 0
+
+ +
+ +
+
+class tequila_code.optimizers.optimizer_gd.OptimizerGD(maxiter=100, method='sgd', tol: Real = None, lr: Real | List[Real] = 0.1, alpha: Real = None, gamma: Real = None, beta: Real = 0.9, rho: Real = 0.999, c: Real | List[Real] = 0.2, epsilon: Real = 1e-07, diis: dict | None = None, backend=None, samples=None, device=None, noise=None, silent=True, calibrate_lr: bool = False, **kwargs)[source]
+

Bases: Optimizer

+

The gradient descent optimizer for tequila.

+

OptimizerGD allows for two modalities: it can either function as a ‘stepper’, simply calculating updated +parameter values for a given object; or it can be called to perform an entire optimization. The former +is used to accomplish the latter, and can give users a more fine-grained control of the optimization. +See Optimizer for details on inherited attributes or methods; there are several.

+
+
+f
+

function which performs an optimization step.

+
+ +
+
+gradient_lookup
+

dictionary mapping object ids as strings to said object’s callable gradient

+
+ +
+
+active_key_lookup
+

dictionary mapping object ids as strings to said object’s active keys, itself a dict, of variables to optimize.

+
+ +
+
+moments_lookup
+

dictionary mapping object ids as strings to said object’s current stored moments; a pair of lists of floats, +namely running tallies of gradient momenta. said momenta are used to SCALE or REDIRECT gradient descent steps.

+
+ +
+
+moments_trajectory
+

dictionary mapping object ids as strings to said object’s momenta at ALL steps; that is, a list of all +the moments of a given object, in order.

+
+ +
+
+step_lookup
+

dictionary mapping object ids as strings to an int; how many optimization steps have been performed for +a given object. Relevant only to the Adam optimizer.

+
+ +
+
+diis
+

Dictionary of parameters for the DIIS accelerator.

+
+ +
+
+lr
+

a float or list of floats. Hyperparameter: The learning rate (unscaled) to be used in each update; +in some literature, called a step size.

+
+ +
+
+alpha
+

a float. Hyperparameter: used to adjust the learning rate each iteration using the formula: lr := original_lr / (iteration ** alpha) +Default: None. If not specify alpha or lr given as a list: lr will not be adjusted

+
+ +
+
+gamma
+

a float. Hyperparameter: used to adjust the step of the gradient for spsa method in each iteration +following: c := original_c / (iteration ** gamma) +Default value: None. If not specify gamma or c given as a list: c will not be adjusted

+
+ +
+
+beta
+

a float. Hyperparameter: scales (perhaps nonlinearly) all first moment terms in any relavant method.

+
+ +
+
+rho
+

a float. Hyperparameter: scales (perhaps nonlinearly) all second moment terms in any relavant method. +in some literature, may be referred to as ‘beta_2’.

+
+ +
+
+c
+

a float or list of floats. Hyperparameter: The step rate used in the spsa gradient. +If it is a list, the steprate will change each iteration until the last item of the list is reached.

+
+ +
+
+epsilon
+

a float. Hyperparameter: used to prevent division by zero in some methods.

+
+ +
+
+tol
+

a float. If specified, __call__ aborts when the difference in energies between two steps is smaller than tol.

+
+ +
+
+calibrate_lr
+

a boolean. It specifies to calibrate lr value for spsa method.

+
+ +
+
+iteration
+

a integer. It indicates the number of the iteration being runned.

+
+ +
+
+prepare:
+

perform all necessary compilation and registration of a given objective. Must be called before step +is used on the given optimizer.

+
+ +
+
+step:
+

perform a single optimization step on a compiled objective, starting from a given point.

+
+ +
+
+reset_stepper:
+

wipe all stored information about all prepared objectives.

+
+ +
+
+reset_momenta:
+

reset all moment information about all prepared objectives, but do not erase compiled gradients.

+
+ +
+
+reset_momenta_for:
+

reset all moment information about a given objective, but do not erase compiled gradients.

+
+ +
+
+classmethod available_diis()[source]
+
+
Returns:
+

All tested methods that can be diis accelerated

+
+
+
+ +
+
+classmethod available_methods()[source]
+
+
Returns:
+

All tested available methods

+
+
+
+ +
+
+nextLearningRate()[source]
+

Return the learning rate to use

+
+
Return type:
+

float representing the learning rate to use

+
+
+
+ +
+
+prepare(objective: Objective, initial_values: dict = None, variables: list = None, gradient=None)[source]
+

perform all initialization for an objective, register it with lookup tables, and return it compiled. +MUST be called before step is used.

+
+
Parameters:
+
    +
  • objective (Objective:) – the objective to ready for optimization.

  • +
  • initial_values (dict, optional:) – the initial values of to prepare the optimizer with. +Default: choose randomly.

  • +
  • variables (list, optional:) – which variables to optimize over, and hence prepare gradients for. +Default value: optimize over all variables in objective.

  • +
  • gradient (optional:) – extra keyword; information used to compile alternate gradients. +Default: prepare the standard, analytical gradient.

  • +
+
+
Returns:
+

compiled version of objective.

+
+
Return type:
+

Objective

+
+
+
+ +
+
+reset_momenta()[source]
+

reset moment information about all prepared objectives. +:rtype: None

+
+ +
+
+reset_momenta_for(objective: Objective)[source]
+

reset moment information about a specific objective. +:param objective: the objective whose information should be reset. +:type objective: Objective:

+
+
Return type:
+

None

+
+
+
+ +
+
+reset_stepper()[source]
+

reset all information about all prepared objectives. +:rtype: None

+
+ +
+
+step(objective: Objective, parameters: Dict[Variable, Real]) Dict[Variable, Real][source]
+

perform a single optimization step and return suggested parameters. +:param objective: the compiled objective, to perform an optimization step for. MUST be one returned by prepare. +:type objective: Objective: +:param parameters: the parameters to use in performing the optimization step. +:type parameters: dict:

+
+
Returns:
+

dict of new suggested parameters.

+
+
Return type:
+

dict

+
+
+
+ +
+ +
+
+tequila_code.optimizers.optimizer_gd.minimize(objective: Objective, lr: float | List[float] = 0.1, method='sgd', initial_values: Dict[Hashable, Real] = None, variables: List[Hashable] = None, gradient: str = None, samples: int = None, maxiter: int = 100, diis: int = None, backend: str = None, noise: NoiseModel = None, device: str = None, tol: float = None, silent: bool = False, save_history: bool = True, alpha: float = None, gamma: float = None, beta: float = 0.9, rho: float = 0.999, c: float | List[float] = 0.2, epsilon: float = 1e-07, calibrate_lr: bool = False, *args, **kwargs) GDResults[source]
+

Initialize and call the GD optimizer. +:param objective: The tequila objective to optimize +:type objective: Objective : +:param lr: the learning rate. Default 0.1. +:type lr: float or list of floats >0: +:param alpha: scaling factor to adjust learning rate each iteration. default None +:type alpha: float >0: +:param gamma: scaling facto to adjust step for gradient in spsa method. default None +:type gamma: float >0: +:param beta: scaling factor for first moments. default 0.9 +:type beta: float >0: +:param rho: scaling factor for second moments. default 0.999 +:type rho: float >0: +:param c: stepsize for the gradient of the spsa method +:type c: float or list of floats: +:param epsilon: small float for stability of division. default 10^-7 +:type epsilon: float>0: +:param method: which variation on Gradient Descent to use. Options include ‘sgd’,’adam’,’nesterov’,’adagrad’,’rmsprop’, etc. +:type method: string: Default = ‘sgd’ +:param initial_values:

+
+
+
Initial values as dictionary of Hashable types (variable keys) and floating point numbers. If given None,

they will all be set to zero

+
+
+
+
+
Parameters:
+
    +
  • variables (List[Hashable], optional:) – List of Variables to optimize

  • +
  • gradient (optional:) – the gradient to use. If None, calculated in the usual way. if str=’qng’, then the qng is calculated. +If a dictionary of objectives, those objectives are used. If another dictionary, +an attempt will be made to interpret that dictionary to get, say, numerical gradients.

  • +
  • samples (int, optional:) – samples/shots to take in every run of the quantum circuits (None activates full wavefunction simulation)

  • +
  • maxiter (int : Default = 100:) – the maximum number of iterations to run.

  • +
  • diis (int, optional:) – Number of iteration before starting DIIS acceleration.

  • +
  • backend (str, optional:) – Simulation backend which will be automatically chosen if set to None

  • +
  • noise (NoiseModel, optional:) – a NoiseModel to apply to all expectation values in the objective.

  • +
  • device (optional:) – the device from which to (potentially, simulatedly) sample all quantum circuits employed in optimization.

  • +
  • tol (float : Default = 10^-4) – Convergence tolerance for optimization; if abs(delta f) smaller than tol, stop.

  • +
  • silent (bool : Default = False:) – No printout if True

  • +
  • save_history (bool: Default = True:) – Save the history throughout the optimization

  • +
  • calibrate_lr (bool: Default = False:) – Calibrates the value of the learning rate

  • +
+
+
+
+

Note

+

optional kwargs may include beta, beta2, and rho, parameters which affect +(but do not need to be altered) the various method algorithms.

+
+
+
Returns:
+

the results of an optimization.

+
+
Return type:
+

GDResults

+
+
+
+ +
+
+

optimizer gpyopt module

+
+
+

optimizer scipy module

+
+
+class tequila_code.optimizers.optimizer_scipy.OptimizerSciPy(method: str = 'L-BFGS-B', tol: Real = None, method_options=None, method_bounds=None, method_constraints=None, **kwargs)[source]
+

Bases: Optimizer

+

Class wrapping over the scipy optimizer for use by Tequila.

+
+
+method
+

The scipy optimization method passed as string.

+
+ +
+
+tol
+

See scipy documentation for the method you picked

+
+ +
+
+method_options
+

See scipy documentation for the method you picked

+
+ +
+
+method_bounds
+

See scipy documentation for the method you picked

+
+ +
+
+method_constraints
+

See scipy documentation for the method you picked

+
+ +
+
+silent
+

if False, the optimizer prints out all evaluated energies

+
+ +
+
+classmethod available_methods()[source]
+
+
Returns:
+

All tested available methods

+
+
+
+ +
+
+gradient_based_methods = ['L-BFGS-B', 'BFGS', 'CG', 'TNC']
+
+ +
+
+gradient_free_methods = ['NELDER-MEAD', 'COBYLA', 'POWELL', 'SLSQP']
+
+ +
+
+hessian_based_methods = ['TRUST-KRYLOV', 'NEWTON-CG', 'DOGLEG', 'TRUST-NCG', 'TRUST-EXACT', 'TRUST-CONSTR']
+
+ +
+ +
+
+class tequila_code.optimizers.optimizer_scipy.SciPyResults(energy: float = None, history: tequila_code.optimizers.optimizer_base.OptimizerHistory = None, variables: dict = None, scipy_result: scipy.optimize._optimize.OptimizeResult = None)[source]
+

Bases: OptimizerResults

+
+
+scipy_result: OptimizeResult = None
+
+ +
+ +
+
+exception tequila_code.optimizers.optimizer_scipy.TequilaScipyException(msg)[source]
+

Bases: TequilaException

+
+ +
+
+tequila_code.optimizers.optimizer_scipy.available_methods(energy=True, gradient=True, hessian=True) List[str][source]
+

Convenience +:param energy: (Default value = True) +:param gradient: (Default value = True) +:param hessian: (Default value = True)

+
+
Return type:
+

Available methods of the scipy optimizer, a list of strings.

+
+
+
+ +
+
+tequila_code.optimizers.optimizer_scipy.minimize(objective: Objective, gradient: str | Dict[Variable, Objective] = None, hessian: str | Dict[Tuple[Variable, Variable], Objective] = None, initial_values: Dict[Hashable, Real] = None, variables: List[Hashable] = None, samples: int = None, maxiter: int = 100, backend: str = None, backend_options: dict = None, noise: NoiseModel = None, device: str = None, method: str = 'BFGS', tol: float = 0.001, method_options: dict = None, method_bounds: Dict[Hashable, Real] = None, method_constraints=None, silent: bool = False, save_history: bool = True, *args, **kwargs) SciPyResults[source]
+
+
Parameters:
+
    +
  • objective (Objective :) – The tequila objective to optimize

  • +
  • gradient (Union[str, Dict[Variable, Objective], None] : Default value = None):) – ‘2-point’, ‘cs’ or ‘3-point’ for numerical gradient evaluation (does not work in combination with all optimizers), +dictionary of variables and tequila objective to define own gradient, +None for automatic construction (default) +Other options include ‘qng’ to use the quantum natural gradient.

  • +
  • hessian (Union[str, Dict[Variable, Objective], None], optional:) – ‘2-point’, ‘cs’ or ‘3-point’ for numerical gradient evaluation (does not work in combination with all optimizers), +dictionary (keys:tuple of variables, values:tequila objective) to define own gradient, +None for automatic construction (default)

  • +
  • initial_values (Dict[Hashable, numbers.Real], optional:) – Initial values as dictionary of Hashable types (variable keys) and floating point numbers. If given None they will all be set to zero

  • +
  • variables (List[Hashable], optional:) – List of Variables to optimize

  • +
  • samples (int, optional:) – samples/shots to take in every run of the quantum circuits (None activates full wavefunction simulation)

  • +
  • maxiter (int : (Default value = 100):) – max iters to use.

  • +
  • backend (str, optional:) – Simulator backend, will be automatically chosen if set to None

  • +
  • backend_options (dict, optional:) – Additional options for the backend +Will be unpacked and passed to the compiled objective in every call

  • +
  • noise (NoiseModel, optional:) – a NoiseModel to apply to all expectation values in the objective.

  • +
  • method (str : (Default = "BFGS"):) – Optimization method (see scipy documentation, or ‘available methods’)

  • +
  • tol (float : (Default = 1.e-3):) – Convergence tolerance for optimization (see scipy documentation)

  • +
  • method_options (dict, optional:) – Dictionary of options +(see scipy documentation)

  • +
  • method_bounds (Dict[Hashable, Tuple[float, float]], optional:) – bounds for the variables (see scipy documentation)

  • +
  • method_constraints (optional:) – (see scipy documentation

  • +
  • silent (bool :) – No printout if True

  • +
  • save_history (bool:) – Save the history throughout the optimization

  • +
+
+
Returns:
+

the results of optimization

+
+
Return type:
+

SciPyReturnType

+
+
+
+ +
+
+

Module contents

+
+
+tequila_code.optimizers.minimize(objective, method: str = 'bfgs', variables: list = None, initial_values: dict | Number | Callable = 0.0, maxiter: int = None, *args, **kwargs)[source]
+
+
Parameters:
+
    +
  • method (str:) – The optimization method (e.g. bfgs, cobyla, nelder-mead, …) +see ‘tq.optimizers.show_available_methods()’ for an overview

  • +
  • objective (tq.Objective:) – The abstract tequila objective to be optimized

  • +
  • variables (list of names:) – The variables which shall be optimized given as list +Can be passed as list of names or list of tq variables

  • +
  • initial_values (dict:) – Initial values for the optimization, passed as dictionary +with the variable names as keys. +Alternatively zero, random or a single number are accepted

  • +
  • maxiter – maximum number of iterations

  • +
  • kwargs

    further keyword arguments for the actual minimization functions +can also be called directly as tq.minimize_modulename +e.g. tq.minimize_scipy +See their documentation for more details

    +

    example: gradient keyword: +gradient (Default Value: None): +instructions for gradient compilation +can be a dictionary of tequila objectives representing the gradients +or a string/dictionary giving instructions for numerical gradients +examples are

    +
    +
    +

    gradient = ‘2-point’ +gradient = {‘method’:’2-point’, ‘stepsize’: 1.e-4} +gradient = {‘method’:Callable, ‘stepsize’: 1.e-4} +see optimizer_base.py for method examples

    +
    +

    gradient = None: analytical gradients are compiled

    +
    +

  • +
+
+
+
+ +
+
+tequila_code.optimizers.show_available_optimizers(module=None)[source]
+
+
Returns:
+

    +
  • A list of available optimization methods

  • +
  • The list depends on optimization packages installed in your system

  • +
+

+
+
+
+ +
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/py-modindex.html b/docs/sphinx/py-modindex.html new file mode 100644 index 0000000..8818e3f --- /dev/null +++ b/docs/sphinx/py-modindex.html @@ -0,0 +1,270 @@ + + + + + + + + Python Module Index — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + +

Python Module Index

+ +
+ t +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ t
+ tequila_code +
    + tequila_code.circuit +
    + tequila_code.circuit.circuit +
    + tequila_code.circuit.compiler +
    + tequila_code.circuit.gates +
    + tequila_code.circuit.gradient +
    + tequila_code.circuit.noise +
    + tequila_code.circuit.pyzx +
    + tequila_code.circuit.qasm +
    + tequila_code.circuit.qpic +
    + tequila_code.hamiltonian +
    + tequila_code.hamiltonian.paulis +
    + tequila_code.hamiltonian.paulistring +
    + tequila_code.optimizers +
    + tequila_code.optimizers.optimizer_base +
    + tequila_code.optimizers.optimizer_gd +
    + tequila_code.optimizers.optimizer_scipy +
    + tequila_code.quantumchemistry +
    + tequila_code.quantumchemistry.chemistry_tools +
    + tequila_code.quantumchemistry.encodings +
    + tequila_code.quantumchemistry.madness_interface +
    + tequila_code.quantumchemistry.orbital_optimizer +
    + tequila_code.quantumchemistry.psi4_interface +
    + tequila_code.quantumchemistry.pyscf_interface +
    + tequila_code.quantumchemistry.qc_base +
    + tequila_code.simulators +
    + tequila_code.simulators.simulator_api +
    + tequila_code.simulators.simulator_base +
    + tequila_code.simulators.simulator_qulacs +
    + tequila_code.simulators.simulator_qulacs_gpu +
    + tequila_code.simulators.simulator_symbolic +
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/quantumchemistry.html b/docs/sphinx/quantumchemistry.html new file mode 100644 index 0000000..ef33ce3 --- /dev/null +++ b/docs/sphinx/quantumchemistry.html @@ -0,0 +1,2534 @@ + + + + + + + + + Quantum Chemistry — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Quantum Chemistry

+
+

Submodules

+
+
+

chemistry tools module

+
+
+class tequila_code.quantumchemistry.chemistry_tools.ActiveSpaceData(active_orbitals: list = None, reference_orbitals: list = None)[source]
+

Bases: object

+

Small dataclass to keep the overview in active spaces +Class is used internally

+
+
+active_orbitals: list = None
+
+ +
+
+property active_reference_orbitals
+
+ +
+
+property frozen_reference_orbitals
+
+ +
+
+reference_orbitals: list = None
+
+ +
+ +
+
+class tequila_code.quantumchemistry.chemistry_tools.Amplitudes(tIjAb: ndarray = None, tIA: ndarray = None, tiJaB: ndarray = None, tijab: ndarray = None, tIJAB: ndarray = None, tia: ndarray = None)[source]
+

Bases: object

+

Helper class for classical Coupled-Cluster Amplitudes +We adopt the Psi4 notation for consistency +I,A for alpha +i,a for beta

+
+
+classmethod from_closed_shell(cs: ClosedShellAmplitudes)[source]
+

Initialize from closed-shell Amplitude structure

+
+
Parameters:
+

cs (ClosedShellAmplitudes :)

+
+
+
+ +
+
+make_parameter_dictionary(threshold=1e-08)[source]
+
+
Parameters:
+

threshold – (Default value = 1.e-8) +Neglect amplitudes below the threshold

+
+
Return type:
+

Dictionary of tequila variables (hash is in the style of (a,i,b,j))

+
+
+
+ +
+
+tIA: ndarray = None
+
+ +
+
+tIJAB: ndarray = None
+
+ +
+
+tIjAb: ndarray = None
+
+ +
+
+tiJaB: ndarray = None
+
+ +
+
+tia: ndarray = None
+
+ +
+
+tijab: ndarray = None
+
+ +
+ +
+
+class tequila_code.quantumchemistry.chemistry_tools.ClosedShellAmplitudes(tIjAb: ndarray = None, tIA: ndarray = None)[source]
+

Bases: object

+

Helper Class for clasical amplitudes +used internally

+
+
+make_parameter_dictionary(threshold=1e-08, screening=True)[source]
+
+
Parameters:
+

threshold – (Default value = 1.e-8)

+
+
+
+ +
+
+tIA: ndarray = None
+
+ +
+
+tIjAb: ndarray = None
+
+ +
+ +
+
+class tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl(generator, p0, transformation, indices=None, *args, **kwargs)[source]
+

Bases: QubitExcitationImpl

+

Small helper class for Fermionic Excictation Gates +Mainly so that “FermionicGate is displayed when circuits are printed

+
+
+cCRy(target: int, dcontrol: list | int, control: list | int, angle: Real | Variable | Hashable, case: int = 1) QCircuit[source]
+

Compilation of CRy as on https://doi.org/10.1103/PhysRevA.102.062612 +If not control passed, Ry returned +:param case: +:type case: if 1 employs eq. 12 from the paper, if 0 eq. 13

+
+ +
+
+compile(*args, **kwargs)[source]
+
+ +
+
+fermionic_excitation(angle: Real | Variable | Hashable, indices: List, control: int | List = None, opt: bool = True) QCircuit[source]
+

Excitation [(i,j),(k,l)],… compiled following https://doi.org/10.1103/PhysRevA.102.062612 +opt: whether to optimized CNOT H CNOT –> Rz Rz CNOT Rz

+
+ +
+
+format_excitation_indices(idx)[source]
+

Consistent formatting of excitation indices +idx = [(p0,q0),(p1,q1),…,(pn,qn)] +sorted as: p0<p1<pn and pi<qi +:param idx: list of index tuples describing a single(!) fermionic excitation +:return: list of index tuples

+
+ +
+
+format_excitation_variables(idx)[source]
+

Consistent formatting of excitation variable +idx = [(p0,q0),(p1,q1),…,(pn,qn)] +sorted as: pi<qi and p0 < p1 < p2 +:param idx: list of index tuples describing a single(!) fermionic excitation +:return: sign of the variable with re-ordered indices

+
+ +
+
+is_convertable_to_qubit_excitation()[source]
+

spin-paired double excitations (both electrons occupy the same spatial orbital and are excited to another spatial orbital) +in the jordan-wigner representation are identical to 4-qubit excitations which can be compiled more efficient +this function hels to automatically detect those cases

+
+ +
+ +
+
+class tequila_code.quantumchemistry.chemistry_tools.IntegralManager(one_body_integrals, two_body_integrals, basis_name='unknown', orbital_type='unknown', constant_term=0.0, orbital_coefficients=None, active_space=None, overlap_integrals=None, orbitals=None, *args, **kwargs)[source]
+

Bases: object

+

Manage Basis Integrals of Quantum Chemistry +All integrals are held in their original basis, the corresponding mo-coefficients have to be passed down +and are usually held by the QuantumChemistryBaseClass

+
+
+property active_orbitals
+
+ +
+
+property active_reference_orbitals
+
+ +
+
+property active_space
+
+ +
+
+active_space_is_trivial()[source]
+
+ +
+
+basis_is_orthogonal(tolerance=1e-05)[source]
+
+ +
+
+property constant_term
+

rtype: return constant term (usually nuclear repulsion). No active space considered

+
+ +
+
+get_integrals(orbital_coefficients=None, ordering='openfermion', ignore_active_space=False, *args, **kwargs)[source]
+

Get all molecular integrals in given orbital basis (determined by orbital_coefficients in self or the ones passed here) +active space is considered if not explicitly ignored +:param orbital_coefficients: +:type orbital_coefficients: orbital coefficients in the given basis (first index is basis, second index is orbitals). Need to go over full basis (no active space) +:param ordering: +:type ordering: ordering of the two-body integrals (default is openfermion) +:param ignore_active_space: +:type ignore_active_space: ignore active space and give back full integrals

+
+ +
+
+get_orthonormalized_orbital_coefficients()[source]
+

Computes orbitals in this basis that are orthonormal (through loewdin orthonormalization)

+
+
Return type:
+

coefficient matrix of orthonormalized orbitals

+
+
+
+ +
+
+is_unitary(U)[source]
+
+ +
+
+property one_body_integrals
+

rtype: one_body integrals in given basis (using basis functions, not molecular orbitals. No active space considered)

+
+ +
+
+property orbital_coefficients
+

second index is the orbital index, first the basis index +:rtype: orbital coefficient matrix C_{basis,orbital}

+
+ +
+
+property orbitals
+
+ +
+
+property overlap_integrals
+

rtype: Overlap integrals in given basis (using basis functions, not molecular orbitals. No active space considered)

+
+ +
+
+print_basis_info(print_coefficients=True, *args, **kwargs) None[source]
+
+ +
+
+property reference_orbitals
+
+ +
+
+transform_orbitals(U, name=None)[source]
+

Transform orbitals +:param U: +:type U: second index is new orbital indes, first is old orbital index (summed over)

+
+
Returns:
+

updates the structure with new orbitals

+
+
Return type:
+

c = cU

+
+
+
+ +
+
+transform_to_native_orbitals()[source]
+

Transform orbitals to orthonormal functions closest to the native basis

+
+ +
+
+property two_body_integrals
+

returns: * two-body orbitals in given basis (using basis functions, not molecular orbitals. No active space considered) +* ordering is “chem” i.e. Mulliken i.e. integrals_{abcd} = <ac|g|bd>

+
+ +
+
+verify_orbital_coefficients(orbital_coefficients, tolerance=1e-05)[source]
+

Verify if orbital coefficients are valid (i.e. if they define a orthonormal set of orbitals) +:param orbital_coefficients: +:type orbital_coefficients: the orbital coefficients C_ij with i:basis and j:orbitals +:param tolerance:

+
+
Return type:
+

True or False depending if the overlap matrix of the basis is transformed to a unit matrix

+
+
+
+ +
+ +
+
+class tequila_code.quantumchemistry.chemistry_tools.NBodyTensor(elems: ndarray = None, active_indices: list = None, ordering: str = None, size_full: int = None, verify=False)[source]
+

Bases: object

+

Convenience class for handling N-body tensors

+
+
+class Ordering(scheme)[source]
+

Bases: object

+

Convenience to keep track of aliases in odering names for two body integrals +i.e. Mulliken/Chem/1122

+
+

Dirac/Phys/1212 +openfermion/1221

+
+
+
+assign_scheme(scheme)[source]
+
+ +
+
+is_chem()[source]
+
+ +
+
+is_of()[source]
+
+ +
+
+is_phys()[source]
+
+ +
+ +
+
+identify_ordering(trials=25)[source]
+
+ +
+
+reorder(to: str = 'of')[source]
+

Function to reorder tensors according to some convention.

+
+
Parameters:
+

to

Ordering scheme of choice. +‘openfermion’, ‘of’ (default) :

+
+

openfermion - ordering, corresponds to integrals of the type +h^pq_rs = int p(1)* q(2)* O(1,2) r(2) s(1) (O(1,2) +with operators a^pq_rs = a^p a^q a_r a_s (a^p == a^dagger_p) +currently needed for dependencies on openfermion-library

+
+
+
’chem’, ‘c’ :

quantum chemistry ordering, collect particle terms, +more convenient for real-space methods +h^pq_rs = int p(1) q(1) O(1,2) r(2) s(2) +This is output by psi4

+
+
’phys’, ‘p’ :

typical physics ordering, integrals of type +h^pq_rs = int p(1)* q(2)* O(1,2) r(1) s(2) +with operators a^pq_rs = a^p a^q a_s a_r

+
+
+

+
+
+
+ +
+
+set_index_lists()[source]
+

Set passive and full index lists based on class inputs

+
+ +
+
+property shape
+
+ +
+
+sub_lists(idx_lists: list = None) ndarray[source]
+

Get subspace of tensor by a set of index lists +according to hPQ.sub_lists(idx_lists=[p, q]) = [hPQ for P in p and Q in q]

+

This essentially is an implementation of a non-contiguous slicing using numpy.take

+
+
Parameters:
+

idx_lists – List of lists, each defining the desired subspace per axis +Size needs to match order of tensor, and lists successively correspond to axis=0,1,2,…,N

+
+
Returns:
+

Sliced tensor as numpy.ndarray

+
+
Return type:
+

out

+
+
+
+ +
+
+sub_str(name: str) ndarray[source]
+

Get subspace of tensor by a string +Currently is able to resolve an active space, named ‘a’, full space ‘f’, and the complement ‘p’ = ‘f’ - ‘a’. +Full space in this context may also be smaller than actual tensor dimension.

+

The specification of active space in this context only allows to pick a set from a list of orbitals, and +is not able to resolve an active space from irreducible representations.

+

Example for one-body tensor: +hPQ.sub_lists(name=’ap’) = [hPQ for P in active_indices and Q in _passive_indices]

+
+
Parameters:
+

name – String specifying the desired subspace, elements need to be a (active), f (full), p (full - active)

+
+
Returns:
+

Sliced tensor as numpy.ndarray

+
+
Return type:
+

out

+
+
+
+ +
+ +
+
+class tequila_code.quantumchemistry.chemistry_tools.OrbitalData(irrep: str = None, idx_irrep: int = None, idx_total: int = None, idx: int = None, energy: float = None, occ: float = None, pair: tuple = None)[source]
+

Bases: object

+
+
+energy: float = None
+
+ +
+
+idx: int = None
+
+ +
+
+idx_irrep: int = None
+
+ +
+
+idx_total: int = None
+
+ +
+
+irrep: str = None
+
+ +
+
+occ: float = None
+
+ +
+
+pair: tuple = None
+
+ +
+ +
+
+class tequila_code.quantumchemistry.chemistry_tools.ParametersQC(basis_set: str = None, geometry: str = None, description: str = '', multiplicity: int = 1, charge: int = 0, name: str = None, frozen_core: bool = True)[source]
+

Bases: object

+

Specialization of ParametersHamiltonian

+
+
+basis_set: str = None
+
+ +
+
+charge: int = 0
+
+ +
+
+static convert_to_list(geometry)[source]
+

Convert a molecular structure given as a string into a list suitable for openfermion

+
+
+
geometry :

a string specifying a mol. structure. E.g. geometry=”h 0.0 0.0 0.0

+
+
+
+

h 0.0 0.0 1.0”

+
+
+
type

A list with the correct format for openfermion E.g return [ [‘h’,[0.0,0.0,0.0], [..]]

+
+
+
+
+ +
+
+description: str = ''
+
+ +
+
+property filename
+
+ +
+
+static format_element_name(string)[source]
+

OpenFermion uses case sensitive hash tables for chemical elements +I.e. you need to name Lithium: ‘Li’ and ‘li’ or ‘LI’ will not work +this convenience function does the naming +:return: first letter converted to upper rest to lower

+
+
Parameters:
+

string

+
+
+
+ +
+
+frozen_core: bool = True
+
+ +
+
+geometry: str = None
+
+ +
+
+get_atom_number(name)[source]
+
+ +
+
+get_atoms()[source]
+
+ +
+
+get_geometry()[source]
+

Returns the geometry +If a xyz filename was given the file is read out +otherwise it is assumed that the geometry was given as string +which is then reformatted as a list usable as input for openfermion +:return: geometry as list +e.g. [(h,(0.0,0.0,0.35)),(h,(0.0,0.0,-0.35))] +Units: Angstrom!

+
+ +
+
+get_geometry_string() str[source]
+

returns the geometry as a string +:return: geometry string

+
+ +
+
+get_nuc_charge()[source]
+
+ +
+
+get_number_of_core_electrons()[source]
+
+ +
+
+property molecular_data_param: dict
+

Give back all parameters for the MolecularData format from openfermion as dictionary

+
+
Type:
+

return

+
+
+
+ +
+
+multiplicity: int = 1
+
+ +
+
+property n_electrons
+
+ +
+
+name: str = None
+
+ +
+
+static read_xyz_from_file(filename)[source]
+

Read XYZ filetype for molecular structures +https://en.wikipedia.org/wiki/XYZ_file_format +Units: Angstrom!

+
+
Parameters:
+

filename – return:

+
+
+
+ +
+ +
+
+tequila_code.quantumchemistry.chemistry_tools.prepare_product_state(state: BitString) QCircuit[source]
+

Small convenience function

+
+
Parameters:
+
    +
  • state (BitString :) – product state encoded into a bitstring

  • +
  • state

  • +
+
+
Returns:
+

unitary circuit which prepares the product state

+
+
Return type:
+

type

+
+
+
+ +
+
+

encodings module

+

Collections of Fermion-to-Qubit encodings known to tequila +Most are Interfaces to OpenFermion

+
+
+class tequila_code.quantumchemistry.encodings.BravyiKitaev(n_electrons, n_orbitals, up_then_down=False, *args, **kwargs)[source]
+

Bases: EncodingBase

+

Uses OpenFermion::bravyi_kitaev

+
+
+bk_to_me() QCircuit[source]
+
+ +
+
+do_transform(fermion_operator: FermionOperator, *args, **kwargs) QubitOperator[source]
+
+ +
+
+jw_to_me() QCircuit[source]
+
+ +
+
+me_to_bk() QCircuit[source]
+
+ +
+
+me_to_jw() QCircuit[source]
+

This method needs to be implemented to enable default conversions via Jordan-Wigner

+
+ +
+ +
+
+class tequila_code.quantumchemistry.encodings.BravyiKitaevFast(n_electrons, n_orbitals, up_then_down=False, *args, **kwargs)[source]
+

Bases: EncodingBase

+

Uses OpenFermion::bravyi_kitaev_tree

+
+
+do_transform(fermion_operator: FermionOperator, *args, **kwargs) QubitOperator[source]
+
+ +
+
+me_to_jw() QCircuit[source]
+

This method needs to be implemented to enable default conversions via Jordan-Wigner

+
+ +
+ +
+
+class tequila_code.quantumchemistry.encodings.BravyiKitaevTree(n_electrons, n_orbitals, up_then_down=False, *args, **kwargs)[source]
+

Bases: EncodingBase

+

Uses OpenFermion::bravyi_kitaev_tree

+
+
+do_transform(fermion_operator: FermionOperator, *args, **kwargs) QubitOperator[source]
+
+ +
+
+me_to_jw() QCircuit[source]
+

This method needs to be implemented to enable default conversions via Jordan-Wigner

+
+ +
+ +
+
+class tequila_code.quantumchemistry.encodings.EncodingBase(n_electrons, n_orbitals, up_then_down=False, *args, **kwargs)[source]
+

Bases: object

+
+
+bk_to_me() QCircuit[source]
+
+ +
+
+do_transform(fermion_operator: FermionOperator, *args, **kwargs) QubitOperator[source]
+
+ +
+
+down(i)[source]
+
+ +
+
+hcb_to_me() QCircuit[source]
+
+ +
+
+jw_to_me() QCircuit[source]
+
+ +
+
+map_state(state: list, *args, **kwargs) list[source]
+

Expects a state in spin-orbital ordering +Returns the corresponding qubit state in the class encoding +:param state:

+
+

basis-state as occupation number vector in spin orbitals +sorted as: [0_up, 0_down, 1_up, 1_down, … N_up, N_down] +with N being the number of spatial orbitals

+
+
+
Returns:
+

basis-state as qubit state in the corresponding mapping

+
+
+
+ +
+
+me_to_bk() QCircuit[source]
+
+ +
+
+abstract me_to_jw() QCircuit[source]
+

This method needs to be implemented to enable default conversions via Jordan-Wigner

+
+ +
+
+property name
+
+ +
+
+post_processing(op, *args, **kwargs)[source]
+
+ +
+
+property supports_ucc
+
+ +
+
+up(i)[source]
+
+ +
+ +
+
+class tequila_code.quantumchemistry.encodings.JordanWigner(n_electrons, n_orbitals, up_then_down=False, *args, **kwargs)[source]
+

Bases: EncodingBase

+

OpenFermion::jordan_wigner

+
+
+do_transform(fermion_operator: FermionOperator, *args, **kwargs) QubitOperator[source]
+
+ +
+
+hcb_to_me(*args, **kwargs)[source]
+
+ +
+
+jw_to_me() QCircuit[source]
+
+ +
+
+map_state(state: list, *args, **kwargs)[source]
+

Expects a state in spin-orbital ordering +Returns the corresponding qubit state in the class encoding +:param state:

+
+

basis-state as occupation number vector in spin orbitals +sorted as: [0_up, 0_down, 1_up, 1_down, … N_up, N_down] +with N being the number of spatial orbitals

+
+
+
Returns:
+

basis-state as qubit state in the corresponding mapping

+
+
+
+ +
+
+me_to_jw() QCircuit[source]
+

This method needs to be implemented to enable default conversions via Jordan-Wigner

+
+ +
+ +
+
+class tequila_code.quantumchemistry.encodings.TaperedBravyKitaev(n_electrons, n_orbitals, active_fermions=None, active_orbitals=None, *args, **kwargs)[source]
+

Bases: EncodingBase

+
+
+do_transform(fermion_operator: FermionOperator, *args, **kwargs) QubitOperator[source]
+
+ +
+
+map_state(state: list, *args, **kwargs)[source]
+

Expects a state in spin-orbital ordering +Returns the corresponding qubit state in the class encoding +:param state:

+
+

basis-state as occupation number vector in spin orbitals +sorted as: [0_up, 0_down, 1_up, 1_down, … N_up, N_down] +with N being the number of spatial orbitals

+
+
+
Returns:
+

basis-state as qubit state in the corresponding mapping

+
+
+
+ +
+
+me_to_jw() QCircuit[source]
+

This method needs to be implemented to enable default conversions via Jordan-Wigner

+
+ +
+ +
+
+tequila_code.quantumchemistry.encodings.known_encodings()[source]
+
+ +
+
+

madness interface module

+
+
+class tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness(parameters: ParametersQC, transformation: str | Callable = None, active_orbitals: list = 'auto', executable: str = None, n_pno: int = None, n_virt: int = 0, keep_mad_files=False, datadir=None, *args, **kwargs)[source]
+

Bases: QuantumChemistryBase

+
+
+cleanup(warn=False, delete_all_files=False)[source]
+
+ +
+
+compute_energy(method, *args, **kwargs)[source]
+

Call classical methods over PySCF (needs to be installed) or +use as a shortcut to calculate quantum energies (see make_upccgsd_ansatz)

+
+
Parameters:
+
    +
  • method (method name) – classical: HF, MP2, CCSD, CCSD(T), FCI +quantum: SPA-GASD (SPA can be dropped as well as letters in GASD) +examples: GSD is the same as UpCCGSD, SPA alone is equivalent to SPA-D +see make_upccgsd_ansatz of the this class for more information

  • +
  • args

  • +
  • kwargs

  • +
+
+
+
+ +
+
+convert_madness_output_from_bin_to_npy(name, datadir=None)[source]
+
+ +
+
+static find_executable(madness_root_dir=None)[source]
+
+ +
+
+get_pair_orbitals(i: OrbitalData, j: OrbitalData, exclude: List[OrbitalData] = None)[source]
+
+ +
+
+get_virtual_orbitals()[source]
+
+ +
+
+local_qubit_map(hcb=False, up_then_down=False)[source]
+
+ +
+
+make_hardcore_boson_pno_upccd_ansatz(pairs=None, label=None, include_reference=True, direct_compiling=False)[source]
+
+ +
+
+make_pno_upccgsd_ansatz(generalized=False, include_offdiagonals=False, **kwargs)[source]
+
+ +
+
+make_spa_ansatz(label=None, hcb=False)[source]
+

Shortcut for convenience +:param label: label for the angles +:param hcb: if True the circuit will not map from HCB to JW (or other encodings that might be supported in the future)

+
+
Return type:
+

Default SPA ansatz (equivalent to PNO-UpCCD with madness PNOs)

+
+
+
+ +
+
+make_upccgsd_ansatz(name='UpCCGSD', label=None, direct_compiling=None, order=None, neglect_z=None, hcb_optimization=None, include_reference=True, *args, **kwargs)[source]
+

Overwriting baseclass to allow names like : PNO-UpCCD etc +:param label: +:type label: label the variables of the ansatz ( variables will be labelled (indices, X, (label, layer) witch X=D/S) +:param direct_compiling: +:type direct_compiling: Directly compile the first layer (works only for transformation that implement the hcb_to_me function) +:param name: if HCB is included in name: do not map from hard-core Boson to qubit encoding of this molecule

+
+

if SPA is included in name: Use the separable pair ansatz (excitations will be restricted to the PNO structure of the surrogate model) +Excitations: can be “S” (use only singles), “D” (use only doubles), “GSD” (generalized singles and doubles), “GASD” (approximate singles, neglecting Z terms in JW)

+
+
+
Parameters:
+
    +
  • neglect_z (neglect all Z terms in singles excitations generators)

  • +
  • order (repetition of layers, can be given over the name as well, the order needs to be the first in the name then (i.e. 2-UpCCGSD, 2-SPA-GSD, etc))

  • +
  • args

  • +
  • kwargs

  • +
+
+
+
+ +
+
+make_upccgsd_indices(label=None, name='UpCCGD', exclude: list = None, *args, **kwargs)[source]
+
+
Parameters:
+
    +
  • label – label the angles

  • +
  • generalized – if true the complement to UpCCGD is created (otherwise UpCCD)

  • +
  • exclude – list of indices to exclude

  • +
+
+
Returns:
+

All gates missing between PNO-UpCCD and UpCC(G)D

+
+
+
+ +
+
+perturbative_f12_correction(rdm1: ndarray = None, rdm2: ndarray = None, n_ri: int = None, f12_filename: str = 'molecule_f12tensor.bin', **kwargs) float[source]
+

Computes the spin-free [2]_R12 correction, needing only the 1- and 2-RDM of a reference method +Requires either 1-RDM, 2-RDM or information to compute them in kwargs

+
+
Parameters:
+
    +
  • rdm1 – 1-electron reduced density matrix

  • +
  • rdm2 – 2-electron reduced density matrix

  • +
  • gamma – f12-exponent, for a correlation factor f_12 = -1/gamma * exp[-gamma*r_12]

  • +
  • n_ri – dimensionality of RI-basis; if None, then the maximum available via tensors / basis-set is used

  • +
  • f12_filename – when using madness_interface, <q|h|p> and <rs|1/r_12|pq> already available; +need to provide f12-tensor <rs|f_12|pq> as “.bin” from madness or “.npy”, assuming Mulliken ordering

  • +
  • kwargs – e.g. RDM-information via {“U”: QCircuit, “variables”: optimal angles}, needs to be passed if rdm1,rdm2 not +yet computed

  • +
+
+
Return type:
+

the f12 correction for the energy

+
+
+
+ +
+
+plot2cube(orbital, filename=None, *args, **kwargs)[source]
+

plot orbitals to cube file (needs madtequila backend installed) +:param method: if you want to plot frozen orbitals you can hand in a Tequila Orbital structure with idx_total defined +:type method: orbital, the orbital index (starting from 0 on the active orbitals) +:param filename: +:type filename: name of the cubefile (default: mra_orbital_X.cube where X is the total index of the active orbital) +:param args: +:type args: further arguments for plot2cube +:param kwargs further keyword arguments for plot2cube: +:param see here for more https: +:type see here for more https: //github.com/kottmanj/madness/tree/tequila/src/apps/plot

+
+ +
+
+read_tensors(name='molecule', filetype='npy', datadir=None)[source]
+

Try to read files “name_htensor.npy” and “name_gtensor.npy”

+
+ +
+
+run_madness(*args, **kwargs)[source]
+
+ +
+
+write_madness_input(n_pno=None, n_virt=0, filename='input', maxrank=None, n_orbitals=None, *args, **kwargs)[source]
+
+ +
+ +
+
+exception tequila_code.quantumchemistry.madness_interface.TequilaMadnessException(msg)[source]
+

Bases: TequilaException

+
+ +
+
+

orbital optimizer module

+
+
+class tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult(old_molecule: tequila_code.quantumchemistry.qc_base.QuantumChemistryBase = None, molecule: tequila_code.quantumchemistry.qc_base.QuantumChemistryBase = None, mcscf_object: object = None, mcscf_local_data: dict = None, energy: float = None, iterations: int = 0)[source]
+

Bases: object

+
+
+energy: float = None
+
+ +
+
+iterations: int = 0
+
+ +
+
+mcscf_local_data: dict = None
+
+ +
+
+mcscf_object: object = None
+
+ +
+
+mo_coeff = None
+
+ +
+
+molecule: QuantumChemistryBase = None
+
+ +
+
+old_molecule: QuantumChemistryBase = None
+
+ +
+ +
+
+class tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper(n_electrons: int = None, molecule_arguments: dict = None, rdm1: ~numpy.ndarray = None, rdm2: ~numpy.ndarray = None, one_body_integrals: ~numpy.ndarray = None, two_body_integrals: ~numpy.ndarray = None, history: list = <factory>, const_part: float = 0.0, silent: bool = False, vqe_solver: ~typing.Callable = None, circuit: ~tequila.circuit.circuit.QCircuit = None, vqe_solver_arguments: dict = <factory>, molecule_factory: ~typing.Callable = None)[source]
+

Bases: object

+

Wrapper for tequila VQE’s to be compatible with PySCF orbital optimization

+
+
+circuit: QCircuit = None
+
+ +
+
+const_part: float = 0.0
+
+ +
+
+history: list
+
+ +
+
+kernel(h1, h2, *args, **kwargs)[source]
+
+ +
+
+make_rdm12(*args, **kwargs)[source]
+
+ +
+
+molecule_arguments: dict = None
+
+ +
+
+molecule_factory: Callable = None
+
+ +
+
+n_electrons: int = None
+
+ +
+
+one_body_integrals: ndarray = None
+
+ +
+
+rdm1: ndarray = None
+
+ +
+
+rdm2: ndarray = None
+
+ +
+
+reorder(M, ordering, to)[source]
+
+ +
+
+silent: bool = False
+
+ +
+
+two_body_integrals: ndarray = None
+
+ +
+
+vqe_solver: Callable = None
+
+ +
+
+vqe_solver_arguments: dict
+
+ +
+ +
+
+tequila_code.quantumchemistry.orbital_optimizer.optimize_orbitals(molecule, circuit=None, vqe_solver=None, pyscf_arguments=None, silent=False, vqe_solver_arguments=None, initial_guess=None, return_mcscf=False, use_hcb=False, molecule_factory=None, molecule_arguments=None, restrict_to_active_space=True, *args, **kwargs)[source]
+
+
Parameters:
+
    +
  • molecule (The tequila molecule whose orbitals are to be optimized)

  • +
  • circuit (The circuit that defines the ansatz to the wavefunction in the VQE) – can be None, if a customized vqe_solver is passed that can construct a circuit

  • +
  • vqe_solver (The VQE solver (the default - vqe_solver=None - will take the given circuit and construct an expectationvalue out of molecule.make_hamiltonian and the given circuit)) – A customized object can be passed that needs to be callable with the following signature: vqe_solver(H=H, circuit=self.circuit, molecule=molecule, **self.vqe_solver_arguments)

  • +
  • pyscf_arguments (Arguments for the MCSCF structure of PySCF, if None, the defaults are {“max_cycle_macro”:10, “max_cycle_micro”:3} (see here https://pyscf.org/pyscf_api_docs/pyscf.mcscf.html))

  • +
  • silent (silence printout)

  • +
  • use_hcb (indicate if the circuit is in hardcore Boson encoding)

  • +
  • vqe_solver_arguments (Optional arguments for a customized vqe_solver or the default solver) – for the default solver: vqe_solver_arguments={“optimizer_arguments”:A, “restrict_to_hcb”:False} where A holds the kwargs for tq.minimize +restrict_to_hcb keyword controls if the standard (in whatever encoding the molecule structure has) Hamiltonian is constructed or the hardcore_boson hamiltonian

  • +
  • initial_guess (Initial guess for the MCSCF module of PySCF (Matrix of orbital rotation coefficients)) –

    The default (None) is a unit matrix +predefined commands are

    +
    +

    initial_guess=”random” +initial_guess=”random_loc=X_scale=Y” with X and Y being floats +This initialized a random guess using numpy.random.normal(loc=X, scale=Y) with X=0.0 and Y=0.1 as defaults

    +
    +

  • +
  • return_mcscf (return the PySCF MCSCF structure after optimization)

  • +
  • molecule_arguments (arguments to pass to molecule_factory or default molecule constructor | only change if you know what you are doing)

  • +
  • args (just here for convenience)

  • +
  • kwargs (just here for conveniece)

  • +
+
+
Return type:
+

Optimized Tequila Molecule

+
+
+
+ +
+
+

psi4 interface module

+
+
+exception tequila_code.quantumchemistry.psi4_interface.OpenVQEEPySCFException(msg)[source]
+

Bases: TequilaException

+
+ +
+
+class tequila_code.quantumchemistry.psi4_interface.Psi4Results(variables: dict = None, filename: str = None, wfn: psi4.core.Wavefunction | psi4.core.CCWavefunction | psi4.core.CIWavefunction = None, mol: psi4.core.Molecule = None)[source]
+

Bases: object

+
+
+filename: str = None
+
+ +
+
+mol: Molecule = None
+
+ +
+
+variables: dict = None
+
+ +
+
+wfn: Wavefunction | CCWavefunction | CIWavefunction = None
+
+ +
+ +
+
+class tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4(parameters: ParametersQC, transformation: str | Callable = None, active_orbitals=None, reference_orbitals=None, frozen_orbitals=None, *args, **kwargs)[source]
+

Bases: QuantumChemistryBase

+
+
+compute_amplitudes(method: str, options: dict = None, filename: str = None, *args, **kwargs) Amplitudes | ClosedShellAmplitudes[source]
+

Compute closed-shell CC amplitudes

+
+
Parameters:
+
    +
  • method – coupled-cluster methods like cc2, ccsd, cc3, ccsd(t) +Success might depend on backend +got an extra function for MP2

  • +
  • *args

  • +
  • **kwargs

  • +
+
+
+
+ +
+
+compute_ccsd_amplitudes()[source]
+
+ +
+
+compute_energy(method: str = 'fci', options=None, recompute: bool = True, ignore_active_space=False, *args, **kwargs)[source]
+

Call classical methods over PySCF (needs to be installed) or +use as a shortcut to calculate quantum energies (see make_upccgsd_ansatz)

+
+
Parameters:
+
    +
  • method (method name) – classical: HF, MP2, CCSD, CCSD(T), FCI – with pyscf +quantum: UpCCD, UpCCSD, UpCCGSD, k-UpCCGSD, UCCSD, +see make_upccgsd_ansatz of the this class for more information

  • +
  • args

  • +
  • kwargs (for quantum methods, keyword arguments for minimizer)

  • +
+
+
+
+ +
+
+compute_rdms(U: QCircuit = None, variables: Variables = None, spin_free: bool = True, get_rdm1: bool = True, get_rdm2: bool = True, psi4_method: str = None, psi4_options: dict = {}, *args, **kwargs)[source]
+

Same functionality as qc_base.compute_rdms (look there for more information), +plus the additional option to compute 1- and 2-RDM using psi4 by the keyword psi4_rdms

+
+
Parameters:
+
    +
  • U – Quantum Circuit to achieve the desired state psi = U |0rangle, optional if psi4_rdms is set to True

  • +
  • variables – If U is parametrized, then need to hand over a set of fixed variables

  • +
  • spin_free – Set whether matrices should be spin-free (summation over spin) or defined by spin-orbitals

  • +
  • get_rdm1 – Set whether either one or both rdm1, rdm2 should be computed. If both are needed at some point, +it is recommended to compute them at once. +Note that whatever is specified in psi4_options has priority.

  • +
  • get_rdm2 – Set whether either one or both rdm1, rdm2 should be computed. If both are needed at some point, +it is recommended to compute them at once. +Note that whatever is specified in psi4_options has priority.

  • +
  • psi4_method – Method to be run, currently only methods returning a CIWavefuntion are supported +(e.g. “detci” + ex_level in options, or “fci”, “cisdt”, “casscf”, but NOT “cisd”)

  • +
  • psi4_options – Options to be handed over to psi4, containing e.g. excitation level of “detci”-method. +If “detci__opdm” for 1-RDM and “detci__tpdm” for 2-RDM are not included, the keywords get_rdm1, get_rdm2 are +used (if both are specified, prioritizing psi4_options).

  • +
+
+
+
+ +
+
+initialize_integral_manager(*args, **kwargs)[source]
+

Called by self.__init__() with args and kwargs passed through +Override this in derived class such that it returns an intitialized instance of the integral manager

+

In the BaseClass it is required to pass the following with kwargs on init: +- one_body_integrals as matrix +- two_body_integrals as NBTensor of numpy.ndarray (four indices, openfermion ordering) +- nuclear_repulsion (constant part of hamiltonian - optional)

+

Method sets: +- result of self.get_integrals()

+
+ +
+
+property nirrep
+
+ +
+
+orbital_energies(irrep: int | str = None, beta: bool = False, wfn=None)[source]
+

Returns orbital energies of a given irrep +or all orbital energies of all irreps (default)

+
+
Parameters:
+
+
+
Return type:
+

list or orbital energies

+
+
+
+ +
+
+perturbative_f12_correction(rdm1: ndarray = None, rdm2: ndarray = None, gamma: float = 1.4, n_ri: int = None, cabs_type: str = 'active', cabs_options: dict = None, **kwargs) float[source]
+

Computes the spin-free [2]_R12 correction, needing only the 1- and 2-RDM of a reference method +Requires either 1-RDM, 2-RDM or information to compute them in kwargs

+
+
Parameters:
+
    +
  • rdm1 – 1-electron reduced density matrix

  • +
  • rdm2 – 2-electron reduced density matrix

  • +
  • gamma – f12-exponent, for a correlation factor f_12 = -1/gamma * exp[-gamma*r_12]

  • +
  • n_ri – dimensionality of RI-basis; if None, then the maximum available via tensors / basis-set is used

  • +
  • cabs_type

      +
    • either “active” for using a given basis set as is as approximative CBS (complete basis set), and specify

    • +
    +

    OBS (orbital basis) by an active space +- or “cabs+” for CABS+-approach as in

    +
    +

    Valeev, E. F. (2004). Improving on the resolution of the identity in linear R12 ab initio theories. +Chemical Physics Letters, 395(4–6), 190–195. https://doi.org/10.1016/j.cplett.2004.07.061 +-> pass cabs_name in cabs_options

    +
    +

  • +
  • cabs_options – dict, which needs at least {“cabs_name”: some CABS basis set} if cabs_type==”cabs+”

  • +
  • kwargs – e.g. RDM-information via {“U”: QCircuit, “variables”: optimal angles} if computation via VQE, +or {“rdm__psi4_method”: some CI method, “rdm__psi4_options”: dict with psi4 options} if computation via +psi4, compare to psi4_interface.compute_rdms +one of the above needs to be passed if rdm1,rdm2 not yet computed

  • +
+
+
Return type:
+

the f12 correction for the energy

+
+
+
+ +
+
+property point_group
+
+ +
+
+property rdm1: tuple
+

Returns RMD1 if computed with compute_rdms function before

+
+ +
+
+property rdm2: tuple
+

Returns RMD2 if computed with compute_rdms function before +This is returned in Dirac (physics) notation by default (can be changed in compute_rdms with keyword)!

+
+ +
+ +
+
+exception tequila_code.quantumchemistry.psi4_interface.TequilaPsi4Exception(msg)[source]
+

Bases: TequilaException

+
+ +
+
+

pyscf interface module

+
+
+exception tequila_code.quantumchemistry.pyscf_interface.OpenVQEEPySCFException(msg)[source]
+

Bases: TequilaException

+
+ +
+
+class tequila_code.quantumchemistry.pyscf_interface.QuantumChemistryPySCF(parameters: ParametersQC, transformation: str | Callable = None, *args, **kwargs)[source]
+

Bases: QuantumChemistryBase

+
+
+compute_energy(method: str, *args, **kwargs) float[source]
+

Call classical methods over PySCF (needs to be installed) or +use as a shortcut to calculate quantum energies (see make_upccgsd_ansatz)

+
+
Parameters:
+
    +
  • method (method name) – classical: HF, MP2, CCSD, CCSD(T), FCI – with pyscf +quantum: UpCCD, UpCCSD, UpCCGSD, k-UpCCGSD, UCCSD, +see make_upccgsd_ansatz of the this class for more information

  • +
  • args

  • +
  • kwargs (for quantum methods, keyword arguments for minimizer)

  • +
+
+
+
+ +
+
+compute_fci(*args, **kwargs)[source]
+
+ +
+ +
+
+

qc base module

+
+
+class tequila_code.quantumchemistry.qc_base.QuantumChemistryBase(parameters: ParametersQC, transformation: str | Callable = None, active_orbitals: list = None, frozen_orbitals: list = None, orbital_type: str = None, reference_orbitals: list = None, orbitals: list = None, *args, **kwargs)[source]
+

Bases: object

+

Base Class for tequila chemistry functionality +This is what is initialized with tq.Molecule(…) +We try to define all main methods here and only implemented specializations in the derived classes +Derived classes interface specific backends (e.g. Psi4, PySCF and Madness). See PACKAGE_interface.py for more

+
+
+UC(i, j, angle=None, label=None, control=None, assume_real=True, *args, **kwargs)[source]
+

Convenience function for orbital correlator circuit (correlating spatial orbital i and j through a spin-paired double excitation) with standard naming of variables +See arXiv:2207.12421 Eq.22 for UC(1,2)

+
+

Parameters:

+
+
+
indices:

tuple of two spatial(!) orbital indices

+
+
angle:

Numeric or hashable type or tequila objective. Default is None and results +in automatic naming as (“R”,i,j)

+
+
label:

can be passed instead of angle to have auto-naming with label (“R”,i,j,label) +useful for repreating gates with individual variables

+
+
control:

List of possible control qubits

+
+
assume_real:

Assume that the wavefunction will always stay real. +Will reduce potential gradient costs by a factor of 2

+
+
+
+
+
+ +
+
+UR(i, j, angle=None, label=None, control=None, assume_real=True, *args, **kwargs)[source]
+

Convenience function for orbital rotation circuit (rotating spatial orbital i and j) with standard naming of variables +See arXiv:2207.12421 Eq.6 for UR(0,1) +Parameters: +———-

+
+
+
indices:

tuple of two spatial(!) orbital indices

+
+
angle:

Numeric or hashable type or tequila objective. Default is None and results +in automatic naming as (“R”,i,j)

+
+
label:

can be passed instead of angle to have auto-naming with label (“R”,i,j,label) +useful for repreating gates with individual variables

+
+
control:

List of possible control qubits

+
+
assume_real:

Assume that the wavefunction will always stay real. +Will reduce potential gradient costs by a factor of 2

+
+
+
+
+ +
+
+property active_space
+
+ +
+
+compute_amplitudes(method: str, *args, **kwargs)[source]
+

Compute closed-shell CC amplitudes

+
+
Parameters:
+
    +
  • method – coupled-cluster methods like cc2, ccsd, cc3, ccsd(t) +Success might depend on backend +got an extra function for MP2

  • +
  • *args

  • +
  • **kwargs

  • +
+
+
+
+ +
+
+compute_ccsd_amplitudes() ClosedShellAmplitudes[source]
+
+ +
+
+compute_cis_amplitudes()[source]
+

Compute the CIS amplitudes of the molecule +Warning: Not field tested!

+
+ +
+
+compute_constant_part()[source]
+
+ +
+
+compute_energy(method, *args, **kwargs)[source]
+

Call classical methods over PySCF (needs to be installed) or +use as a shortcut to calculate quantum energies (see make_upccgsd_ansatz)

+
+
Parameters:
+
    +
  • method (method name) – classical: HF, MP2, CCSD, CCSD(T), FCI – with pyscf +quantum: UpCCD, UpCCSD, UpCCGSD, k-UpCCGSD, UCCSD, +see make_upccgsd_ansatz of the this class for more information

  • +
  • args

  • +
  • kwargs (for quantum methods, keyword arguments for minimizer)

  • +
+
+
+
+ +
+
+compute_fock_matrix()[source]
+
+ +
+
+compute_mp2_amplitudes(hf_energy=None, return_energy=False) ClosedShellAmplitudes[source]
+

Compute closed-shell mp2 amplitudes (canonical amplitudes only)

+
+\[t(a,i,b,j) = 0.25 * g(a,i,b,j)/(e(i) + e(j) -a(i) - b(j) )\]
+
+
Returns:
+

+
+
+
+ +
+
+compute_one_body_integrals()[source]
+

convenience function

+
+ +
+
+compute_rdms(U: QCircuit = None, variables: Variables = None, spin_free: bool = True, get_rdm1: bool = True, get_rdm2: bool = True, ordering='dirac', use_hcb: bool = False, rdm_trafo: QubitHamiltonian = None, evaluate=True)[source]
+

Computes the one- and two-particle reduced density matrices (rdm1 and rdm2) given +a unitary U. This method uses the standard ordering in physics as denoted below. +Note, that the representation of the density matrices depends on the qubit transformation +used. The Jordan-Wigner encoding corresponds to ‘classical’ second quantized density +matrices in the occupation picture.

+

We only consider real orbitals and thus real-valued RDMs. +The matrices are set as private members _rdm1, _rdm2 and can be accessed via the properties rdm1, rdm2.

+
+
Parameters:
+
    +
  • U – Quantum Circuit to achieve the desired state psi = U |0rangle, non-optional

  • +
  • variables – If U is parametrized, then need to hand over a set of fixed variables

  • +
  • spin_free – Set whether matrices should be spin-free (summation over spin) or defined by spin-orbitals

  • +
  • get_rdm1 – Set whether either one or both rdm1, rdm2 should be computed. If both are needed at some point, +it is recommended to compute them at once.

  • +
  • get_rdm2 – Set whether either one or both rdm1, rdm2 should be computed. If both are needed at some point, +it is recommended to compute them at once.

  • +
  • rdm_trafo – The rdm operators can be transformed, e.g., a^dagger_i a_j -> U^dagger a^dagger_i a_j U, +where U represents the transformation. The default is set to None, implying that U equas the identity.

  • +
  • evaluate – if true, the tequila expectation values are evaluated directly via the tq.simulate command. +the protocol is optimized to avoid repetation of wavefunction simulation +if false, the rdms are returned as tq.QTensors

  • +
+
+
+
+ +
+
+compute_two_body_integrals(ordering='openfermion')[source]
+
+ +
+
+do_make_molecule(*args, **kwargs)[source]
+

Called by self.make_molecule with args and kwargs passed through +Override this in derived class if needed

+
+ +
+
+format_excitation_indices(idx)[source]
+

Consistent formatting of excitation indices +idx = [(p0,q0),(p1,q1),…,(pn,qn)] +sorted as: p0<p1<pn and pi<qi +:param idx: list of index tuples describing a single(!) fermionic excitation +:return: tuple-list of index tuples

+
+ +
+
+classmethod from_openfermion(molecule: MolecularData, transformation: str | Callable = None, *args, **kwargs)[source]
+

Initialize direclty from openfermion MolecularData object

+
+
Parameters:
+

molecule – The openfermion molecule

+
+
Return type:
+

The Tequila molecule

+
+
+
+ +
+
+classmethod from_tequila(molecule, transformation=None, *args, **kwargs)[source]
+
+ +
+
+get_givens_circuit(unitary, tol=1e-12, ordering='Optimized')[source]
+

Constructs a quantum circuit from a given real unitary matrix using Givens rotations.

+

This method decomposes a unitary matrix into a series of Givens and Rz (phase) rotations, +then constructs and returns a quantum circuit that implements this sequence of rotations.

+

Parameters: +- unitary (numpy.array): A real unitary matrix representing the transformation to implement. +- tol (float): A tolerance threshold below which matrix elements are considered zero. +- ordering (list of tuples or ‘Optimized’): Custom ordering of indices for Givens rotations or ‘Optimized’ to generate them automatically.

+

Returns: +- QCircuit: A quantum circuit implementing the series of rotations decomposed from the unitary.

+
+ +
+
+get_integrals(*args, **kwargs)[source]
+

Returns

+
+

options for kwargs: “ordering = [“openfermion”, “chem”, “phys”], ignore_active_space = [True, False]”

+

Tuple with: +constant part (nuclear_repulsion + possible integrated parts from active-spaces) +one_body_integrals +two_body_integrals

+
+
+ +
+
+get_pair_specific_indices(pair_info: str = None, include_singles: bool = True, general_excitations: bool = True) list[source]
+
+

Assuming a pair-specific model, create a pair-specific index list +to be used in make_upccgsd_ansatz(indices = … ) +Excite from a set of references (i) to any pair coming from (i), +i.e. any (i,j)/(j,i). If general excitations are allowed, also +allow excitations from pairs to appendant pairs and reference.

+
+
pair_info

file or list including information about pair structure +references single number, pair double +example: as file: “0,1,11,11,00,10” (hand over file name)

+
+

in file, skip first row assuming some text with information +as list:[‘0’,’1`’,’11’,’11’,’00’,’10’] +~> two reference orbitals 0 and 1, +then two orbitals from pair 11, one from 00, one mixed 10

+
+
+
include_singles

include single excitations

+
+
general_excitations

allow general excitations

+
+
+
+
+
Returns
+

list of indices with pair-specific ansatz

+
+
+
+
+ +
+
+hcb_to_me(U=None, condensed=False)[source]
+

Transform a circuit in the hardcore-boson encoding (HCB) +to the encoding of this molecule +HCB is supposed to be encoded on the first n_orbitals qubits +:param U: +:type U: HCB circuit (using the alpha qubits) +:param condensed: +:type condensed: assume that incoming U is condensed (HCB on the first n_orbitals; and not, as for example in JW on the first n even orbitals)

+
+ +
+
+initialize_integral_manager(*args, **kwargs)[source]
+

Called by self.__init__() with args and kwargs passed through +Override this in derived class such that it returns an intitialized instance of the integral manager

+

In the BaseClass it is required to pass the following with kwargs on init: +- one_body_integrals as matrix +- two_body_integrals as NBTensor of numpy.ndarray (four indices, openfermion ordering) +- nuclear_repulsion (constant part of hamiltonian - optional)

+

Method sets: +- result of self.get_integrals()

+
+ +
+
+is_canonical(verify=False, fock_matrix=None)[source]
+
+ +
+
+is_closed_shell(verify=False)[source]
+
+ +
+
+make_annihilation_op(orbital, coefficient=1.0)[source]
+

Compute annihilation operator on spin-orbital in qubit representation +Spin-orbital order is always (up,down,up,down,…)

+
+ +
+
+make_ansatz(name: str, *args, **kwargs)[source]
+

Automatically calls the right subroutines to construct ansatze implemented in tequila.chemistry +name: namne of the ansatz, examples are: UpCCGSD, UpCCD, SPA, UCCSD, SPA+UpCCD, SPA+GS

+
+ +
+
+make_creation_op(orbital, coefficient=1.0)[source]
+

Compute creation operator on spin-orbital in qubit representation +Spin-orbital order is always (up,down,up,down,…)

+
+ +
+
+make_excitation_gate(indices, angle, control=None, assume_real=True, **kwargs)[source]
+

Initialize a fermionic excitation gate defined as

+
+\[e^{-i\frac{a}{2} G}\]
+

with generator defines by the indices [(p0,q0),(p1,q1),…] +.. math:

+
G = i(\prod_{k} a_{p_k}^\dagger a_{q_k} - h.c.)
+
+
+
+
Parameters:
+
    +
  • indices – List of tuples that define the generator

  • +
  • angle – Numeric or hashable type or tequila objective

  • +
  • control – List of possible control qubits

  • +
  • assume_real – Assume that the wavefunction will always stay real. +Will reduce potential gradient costs by a factor of 2

  • +
+
+
+
+ +
+
+make_excitation_generator(indices: Iterable[Tuple[int, int]], form: str = None, remove_constant_term: bool = True) QubitHamiltonian[source]
+

Notes

+
+
Creates the transformed hermitian generator of UCC type unitaries:

M(a^dagger_{a_0} a_{i_0} a^dagger{a_1}a_{i_1} … - h.c.) +where the qubit map M depends is self.transformation

+
+
+
+
Parameters:
+
    +
  • indices (Iterable[Tuple[int, int]] :) – List of tuples [(a_0, i_0), (a_1, i_1), … ] - recommended format, in spin-orbital notation (alpha odd numbers, beta even numbers) +can also be given as one big list: [a_0, i_0, a_1, i_1 …]

  • +
  • form (str : (Default value None):) – Manipulate the generator to involution or projector +set form=’involution’ or ‘projector’ +the default is no manipulation which gives the standard fermionic excitation operator back

  • +
  • remove_constant_term (bool: (Default value True):) – by default the constant term in the qubit operator is removed since it has no effect on the unitary it generates +if the unitary is controlled this might not be true!

  • +
+
+
Returns:
+

1j*Transformed qubit excitation operator, depends on self.transformation

+
+
Return type:
+

type

+
+
+
+ +
+
+make_hamiltonian(*args, **kwargs) QubitHamiltonian[source]
+
+
Parameters:
+
    +
  • occupied_indices (will be auto-assigned according to specified active space. Can be overridden by passing specific lists (same as in open fermion))

  • +
  • active_indices (will be auto-assigned according to specified active space. Can be overridden by passing specific lists (same as in open fermion))

  • +
+
+
Return type:
+

Qubit Hamiltonian in the Fermion-to-Qubit transformation defined in self.parameters

+
+
+
+ +
+
+make_hardcore_boson_excitation_gate(indices, angle, control=None, assume_real=True, compile_options='optimize')[source]
+

Make excitation generator in the hardcore-boson approximation (all electrons are forced to spin-pairs) +use only in combination with make_hardcore_boson_hamiltonian()

+
+
Parameters:
+
    +
  • indices

  • +
  • angle

  • +
  • control

  • +
  • assume_real

  • +
  • compile_options

  • +
+
+
+
+ +
+
+make_hardcore_boson_hamiltonian(condensed=False)[source]
+
+
Returns:
+

    +
  • Hamiltonian in Hardcore-Boson approximation (electrons are forced into spin-pairs)

  • +
  • Indepdent of Fermion-to-Qubit mapping

  • +
  • condensed (always give Hamiltonian back from qubit 0 to N where N is the number of orbitals)

  • +
  • if condensed=False then JordanWigner would give back the Hamiltonian defined on even qubits between 0 to 2N

  • +
+

+
+
+
+ +
+
+make_hardcore_boson_upccgd_layer(indices: list = 'UpCCGD', label: str = None, assume_real: bool = True, *args, **kwargs)[source]
+
+ +
+
+make_molecular_hamiltonian(occupied_indices=None, active_indices=None)[source]
+
+
Returns:
+

    +
  • Create a MolecularHamiltonian as openfermion Class

  • +
  • (used internally here, not used in tequila)

  • +
+

+
+
+
+ +
+
+make_molecule(*args, **kwargs) MolecularData[source]
+

Creates a molecule in openfermion format by running psi4 and extracting the data +Will check for previous outputfiles before running +Will not recompute if a file was found

+
+
Parameters:
+

parameters – An instance of ParametersQC, which also holds an instance of ParametersPsi4 via parameters.psi4 +The molecule will be saved in parameters.filename, if this file exists before the call the molecule will be imported from the file

+
+
Returns:
+

the molecule in openfermion.MolecularData format

+
+
Return type:
+

type

+
+
+
+ +
+
+make_number_op(orbital)[source]
+

Compute number operator on spin-orbital in qubit representation +Spin-orbital order is always (up,down,up,down,…)

+
+ +
+
+make_orbital_rotation_gate(indices: tuple, *args, **kwargs)[source]
+
+ +
+
+make_s2_op()[source]
+

Compute the spin^2 operator of the molecule in qubit representation

+
+ +
+
+make_sm_op()[source]
+

Compute the spin- operator of the molecule in qubit representation

+
+ +
+
+make_sp_op()[source]
+

Compute the spin+ operator of the molecule in qubit representation

+
+ +
+
+make_spa_ansatz(edges, hcb=False, use_units_of_pi=False, label=None, optimize=None, ladder=True)[source]
+

Separable Pair Ansatz (SPA) for general molecules +see arxiv: +edges: a list of tuples that contain the orbital indices for the specific pairs

+
+

one example: edges=[(0,), (1,2,3), (4,5)] are three pairs, one with a single orbital [0], one with three orbitals [1,2,3] and one with two orbitals [4,5]

+
+

hcb: spa ansatz in the hcb (hardcore-boson) space without transforming to current transformation (e.g. JordanWigner), use this for example in combination with the self.make_hardcore_boson_hamiltonian() and see the article above for more info +use_units_of_pi: circuit angles in units of pi +label: label the variables in the circuit +optimize: optimize the circuit construction (see article). Results in shallow circuit from Ry and CNOT gates +ladder: if true the excitation pattern will be local. E.g. in the pair from orbitals (1,2,3) we will have the excitations 1->2 and 2->3, if set to false we will have standard coupled-cluster style excitations - in this case this would be 1->2 and 1->3

+
+ +
+
+make_sz_op()[source]
+

Compute the spin_z operator of the molecule in qubit representation

+
+ +
+
+make_uccsd_ansatz(trotter_steps: int = 1, initial_amplitudes: str | Amplitudes | ClosedShellAmplitudes = None, include_reference_ansatz=True, parametrized=True, threshold=1e-08, add_singles=None, screening=True, *args, **kwargs) QCircuit[source]
+
+
Parameters:
+
    +
  • initial_amplitudes (Union[str :) – initial amplitudes given as ManyBodyAmplitudes structure or as string +where ‘mp2’, ‘cc2’ or ‘ccsd’ are possible initializations

  • +
  • include_reference_ansatz – Also do the reference ansatz (prepare closed-shell Hartree-Fock) (Default value = True)

  • +
  • parametrized – Initialize with variables, otherwise with static numbers (Default value = True)

  • +
  • trotter_steps (int :)

  • +
  • initial_amplitudes

  • +
  • Amplitudes

  • +
  • ClosedShellAmplitudes] – (Default value = “cc2”)

  • +
+
+
Returns:
+

Parametrized QCircuit

+
+
Return type:
+

type

+
+
+
+ +
+
+make_upccgsd_ansatz(include_reference: bool = True, name: str = 'UpCCGSD', label: str = None, order: int = None, assume_real: bool = True, hcb_optimization: bool = None, spin_adapt_singles: bool = True, neglect_z: bool = False, mix_sd: bool = False, *args, **kwargs)[source]
+

UpGCCSD Ansatz similar as described by Lee et. al.

+
+
Parameters:
+
    +
  • include_reference – include the HF reference state as initial state

  • +
  • indices – pass custom defined set of indices from which the ansatz will be created +List of tuples of tuples spin-indices e.g. [((2*p,2*q),(2*p+1,2*q+1)), …]

  • +
  • label – An additional label that is set with the variables +default is None and no label will be set: variables names will be +(x, (p,q)) for x in range(order) +with a label the variables will be named +(label, (x, (p,q)))

  • +
  • order – Order of the ansatz (default is 1) +determines how often the ordering gets repeated +parameters of repeating layers are independent

  • +
  • assume_real – assume a real wavefunction (that is always the case if the reference state is real) +reduces potential gradient costs from 4 to 2

  • +
  • mix_sd – Changes the ordering from first all doubles and then all singles excitations (DDDDD….SSSS….) to +a mixed order (DS-DS-DS-DS-…) where one DS pair acts on the same MOs. Useful to consider when systems +with high electronic correlation and system high error associated with the no Trotterized UCC.

  • +
+
+
Return type:
+

UpGCCSD ansatz

+
+
+
+ +
+
+make_upccgsd_indices(key, reference_orbitals=None, *args, **kwargs)[source]
+
+ +
+
+make_upccgsd_layer(indices, include_singles: bool = True, include_doubles: bool = True, assume_real: bool = True, label=None, spin_adapt_singles: bool = True, angle_transform=None, mix_sd: bool = False, neglect_z: bool = False, *args, **kwargs)[source]
+
+ +
+
+make_upccgsd_singles(indices='UpCCGSD', spin_adapt_singles=True, label=None, angle_transform=None, assume_real=True, neglect_z=False, *args, **kwargs)[source]
+
+ +
+
+property n_electrons: int
+

rtype: The number of active electrons in this molecule

+
+ +
+
+property n_orbitals: int
+

rtype: The number of active orbitals in this Molecule

+
+ +
+
+n_rotation(i, phi)[source]
+

Creates a quantum circuit that applies a phase rotation based on phi to both components (up and down) of a given qubit.

+

Parameters: +- i (int): The index of the qubit to which the rotation will be applied. +- phi (float): The rotation angle. The actual rotation applied will be multiplied with -2 for both components.

+

Returns: +- QCircuit: A quantum circuit object containing the sequence of rotations applied to the up and down components of the specified qubit.

+
+ +
+
+property orbitals
+
+ +
+
+orthonormalize_basis_orbitals()[source]
+
+ +
+
+perturbative_f12_correction(rdm1: ndarray = None, rdm2: ndarray = None, gamma: float = 1.4, n_ri: int = None, external_info: dict = None, **kwargs) float[source]
+

Computes the spin-free [2]_R12 correction, needing only the 1- and 2-RDM of a reference method +Requires either 1-RDM, 2-RDM or information to compute them in kwargs

+
+
Parameters:
+
    +
  • rdm1 – 1-electron reduced density matrix

  • +
  • rdm2 – 2-electron reduced density matrix

  • +
  • gamma – f12-exponent, for a correlation factor f_12 = -1/gamma * exp[-gamma*r_12]

  • +
  • n_ri – dimensionality of RI-basis; specify only, if want to truncate available RI-basis +if None, then the maximum available via tensors / basis-set is used +must not be larger than size of available RI-basis, and not smaller than size of OBS +for n_ri==dim(OBS), the correction returns zero

  • +
  • external_info – for usage in qc_base, need to provide information where to find one-body tensor f12-tensor <rs|f_12|pq>; +pass dictionary with {“f12_filename”: where to find f12-tensor, “scheme”: ordering scheme of tensor}

  • +
  • kwargs – e.g. RDM-information via {“U”: QCircuit, “variables”: optimal angles}, needs to be passed if rdm1,rdm2 not +yet computed

  • +
+
+
Return type:
+

the f12 correction for the energy

+
+
+
+ +
+
+prepare_hardcore_boson_reference()[source]
+

Prepare reference state in the Hardcore-Boson approximation (eqch qubit represents two spin-paired electrons) +:rtype: tq.QCircuit that prepares the HCB reference

+
+ +
+
+prepare_reference(state=None, *args, **kwargs)[source]
+
+
Return type:
+

A tequila circuit object which prepares the reference of this molecule in the chosen transformation

+
+
+
+ +
+
+print_basis_info()[source]
+
+ +
+
+property rdm1
+

Returns RMD1 if computed with compute_rdms function before

+
+ +
+
+property rdm2
+

Returns RMD2 if computed with compute_rdms function before +This is returned in Dirac (physics) notation by default (can be changed in compute_rdms with keyword)!

+
+ +
+
+rdm_spinsum(sum_rdm1: bool = True, sum_rdm2: bool = True) tuple[source]
+

Given the spin-ful 1- and 2-particle reduced density matrices, compute the spin-free RDMs by spin summation.

+
+
Parameters:
+
    +
  • sum_rdm1 – If set to true, perform spin summation on rdm1, rdm2

  • +
  • sum_rdm2 – If set to true, perform spin summation on rdm1, rdm2

  • +
+
+
Returns:
+

The desired spin-free matrices

+
+
Return type:
+

rdm1_spinsum, rdm2_spinsum

+
+
+
+ +
+
+property reference_orbitals
+
+ +
+
+supports_ucc()[source]
+

check if the current molecule supports UCC operations +(e.g. mol.make_excitation_gate)

+
+ +
+
+transform_orbitals(orbital_coefficients, ignore_active_space=False, name=None, *args, **kwargs)[source]
+
+
Parameters:
+
    +
  • orbital_coefficients (second index is new orbital indes, first is old orbital index (summed over), indices are assumed to be defined on the active space)

  • +
  • ignore_active_space (if true orbital_coefficients are not assumed to be given in the active space)

  • +
  • name (str, name the new orbitals)

  • +
  • args

  • +
  • kwargs

  • +
+
+
Return type:
+

New molecule with transformed orbitals

+
+
+
+ +
+
+use_native_orbitals(inplace=False)[source]
+
+
Returns:
+

    +
  • New molecule in the native (orthonormalized) basis given

  • +
  • e.g. for standard basis sets the orbitals are orthonormalized Gaussian Basis Functions

  • +
+

+
+
+
+ +
+ +
+
+tequila_code.quantumchemistry.qc_base.get_givens_decomposition(unitary, tol=1e-12, ordering='Optimized', return_diagonal=False)[source]
+

Decomposes a real unitary matrix into Givens rotations (theta) and Rz rotations (phi).

+

Parameters: +- unitary (numpy.array): A real unitary matrix to decompose. It cannot be complex. +- tol (float): Tolerance for considering matrix elements as zero. Elements with absolute value less than tol are treated as zero. +- ordering (list of tuples or ‘Optimized’): Custom ordering of indices for Givens rotations or ‘Optimized’ to generate them automatically. +- return_diagonal (bool): If True, the function also returns the diagonal matrix as part of the output.

+

Returns: +- list: A list of tuples, each representing a Givens rotation. Each tuple contains the rotation angle theta and indices (i,j) of the rotation. +- list: A list of tuples, each representing an Rz rotation. Each tuple contains the rotation angle phi and the index (i) of the rotation. +- numpy.array (optional): The diagonal matrix after applying all Givens rotations, returned if return_diagonal is True.

+
+ +
+
+tequila_code.quantumchemistry.qc_base.givens_matrix(n, p, q, theta)[source]
+

Construct a complex Givens rotation matrix of dimension n by theta between rows/columns p and q.

+
+ +
+
+tequila_code.quantumchemistry.qc_base.reconstruct_matrix_from_givens(n, theta_list, phi_list, to_real_if_possible=True, tol=1e-12)[source]
+

Reconstructs a matrix from given Givens rotations and Rz diagonal rotations. +This function is effectively an inverse of get_givens_decomposition, and therefore only works with data in the same format as its output.

+

Parameters: +- n (int): The size of the unitary matrix to be reconstructed. +- theta_list (list of tuples): Each tuple contains (angle, i, j) representing a Givens rotation of angle radians, applied to rows/columns i and j. +- phi_list (list of tuples): Each tuple contains (angle, i), representing an Rz rotation by angle radians applied to the `i`th diagonal element. +- to_real_if_possible (bool): If True, converts the matrix to real if its imaginary part is effectively zero. +- tol (float): The tolerance whether to swap a complex rotation for a sign change.

+

Returns: +- numpy.ndarray: The reconstructed complex or real matrix, depending on the to_real_if_possible flag and matrix composition.

+
+ +
+
+

Module contents

+
+
+tequila_code.quantumchemistry.Molecule(geometry: str = None, basis_set: str = None, transformation: str | Callable = None, orbital_type: str = None, backend: str = None, guess_wfn=None, name: str = None, *args, **kwargs) QuantumChemistryBase[source]
+
+
Parameters:
+
    +
  • geometry – molecular geometry as string or as filename (needs to be in xyz format with .xyz ending)

  • +
  • basis_set – quantum chemistry basis set (sto-3g, cc-pvdz, etc)

  • +
  • transformation – The Fermion to Qubit Transformation (jordan-wigner, bravyi-kitaev, bravyi-kitaev-tree and whatever OpenFermion supports)

  • +
  • backend – quantum chemistry backend (psi4, pyscf)

  • +
  • guess_wfn – pass down a psi4 guess wavefunction to start the scf cycle from +can also be a filename leading to a stored wavefunction

  • +
  • name – name of the molecule, if not given it’s auto-deduced from the geometry +can also be done vice versa (i.e. geometry is then auto-deduced to name.xyz)

  • +
  • args

  • +
  • kwargs

  • +
+
+
Return type:
+

The Fermion to Qubit Transformation (jordan-wigner, bravyi-kitaev, bravyi-kitaev-tree and whatever OpenFermion supports)

+
+
+
+ +
+
+tequila_code.quantumchemistry.MoleculeFromOpenFermion(molecule, transformation: str | Callable = None, backend: str = None, *args, **kwargs) QuantumChemistryBase[source]
+

Initialize a tequila Molecule directly from an openfermion molecule object +:param molecule: The openfermion molecule +:param transformation: The Fermion to Qubit Transformation (jordan-wigner, bravyi-kitaev, bravyi-kitaev-tree and whatever OpenFermion supports) +:param backend: The quantum chemistry backend, can be None in this case

+
+
Return type:
+

The tequila molecule

+
+
+
+ +
+
+tequila_code.quantumchemistry.MoleculeFromTequila(mol, transformation=None, backend=None, *args, **kwargs)[source]
+
+ +
+
+tequila_code.quantumchemistry.show_available_modules()[source]
+
+ +
+
+tequila_code.quantumchemistry.show_supported_modules()[source]
+
+ +
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/docs/sphinx/search.html b/docs/sphinx/search.html new file mode 100644 index 0000000..124a0ba --- /dev/null +++ b/docs/sphinx/search.html @@ -0,0 +1,120 @@ + + + + + + + + Search — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ + + + +
+ +
+ +
+
+ +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/docs/sphinx/searchindex.js b/docs/sphinx/searchindex.js new file mode 100644 index 0000000..dc4088d --- /dev/null +++ b/docs/sphinx/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"alltitles": {"1. Setting Up the Documentation": [[1, "setting-up-the-documentation"]], "2. Writing Docstrings with reStructuredText": [[1, "writing-docstrings-with-restructuredtext"]], "3. Formatting Docstrings": [[1, "formatting-docstrings"]], "4. Building the Documentation": [[1, "building-the-documentation"]], "5. Cleaning the Build Directory": [[1, "cleaning-the-build-directory"]], "Circuit": [[0, null]], "Contents:": [[3, null]], "Documenting Code in reStructuredText for Sphinx": [[1, null]], "Hamiltonian": [[2, null]], "Introduction": [[1, "introduction"]], "Module contents": [[0, "module-tequila_code.circuit"], [2, "module-tequila_code.hamiltonian"], [5, "module-tequila_code.optimizers"], [6, "module-tequila_code.quantumchemistry"], [7, "module-tequila_code.simulators"]], "Optimizers": [[5, null]], "Parameters:": [[6, "parameters"]], "Practical Tutorials": [[3, "practical-tutorials"]], "Quantum Chemistry": [[6, null]], "Simulators": [[7, null]], "Submodules": [[0, "submodules"], [2, "submodules"], [5, "submodules"], [6, "submodules"], [7, "submodules"]], "Tequila Documentation": [[3, null]], "Tequila Library Reference": [[4, null]], "chemistry tools module": [[6, "module-tequila_code.quantumchemistry.chemistry_tools"]], "circuit module": [[0, "module-tequila_code.circuit.circuit"]], "compiler module": [[0, "module-tequila_code.circuit.compiler"]], "encodings module": [[6, "module-tequila_code.quantumchemistry.encodings"]], "gates module": [[0, "module-tequila_code.circuit.gates"]], "gradient module": [[0, "module-tequila_code.circuit.gradient"]], "madness interface module": [[6, "module-tequila_code.quantumchemistry.madness_interface"]], "noise module": [[0, "module-tequila_code.circuit.noise"]], "optimizer base module": [[5, "module-tequila_code.optimizers.optimizer_base"]], "optimizer gpyopt module": [[5, "optimizer-gpyopt-module"]], "optimizer gradient module": [[5, "module-tequila_code.optimizers.optimizer_gd"]], "optimizer scipy module": [[5, "module-tequila_code.optimizers.optimizer_scipy"]], "options for kwargs: \u201cordering = [\u201copenfermion\u201d, \u201cchem\u201d, \u201cphys\u201d], ignore_active_space = [True, False]\u201d": [[6, "options-for-kwargs-ordering-openfermion-chem-phys-ignore-active-space-true-false"]], "orbital optimizer module": [[6, "module-tequila_code.quantumchemistry.orbital_optimizer"]], "paulis module": [[2, "module-tequila_code.hamiltonian.paulis"]], "paulistring module": [[2, "module-tequila_code.hamiltonian.paulistring"]], "psi4 interface module": [[6, "module-tequila_code.quantumchemistry.psi4_interface"]], "pyscf interface module": [[6, "module-tequila_code.quantumchemistry.pyscf_interface"]], "pyzx module": [[0, "module-tequila_code.circuit.pyzx"]], "qasm module": [[0, "module-tequila_code.circuit.qasm"]], "qc base module": [[6, "module-tequila_code.quantumchemistry.qc_base"]], "qpic module": [[0, "module-tequila_code.circuit.qpic"]], "qubit-hamiltonian module": [[2, "qubit-hamiltonian-module"]], "simulator api module": [[7, "module-tequila_code.simulators.simulator_api"]], "simulator base module": [[7, "module-tequila_code.simulators.simulator_base"]], "simulator cirq module": [[7, "simulator-cirq-module"]], "simulator pyquil module": [[7, "simulator-pyquil-module"]], "simulator qibo module": [[7, "simulator-qibo-module"]], "simulator qiskit module": [[7, "simulator-qiskit-module"]], "simulator qlm module": [[7, "simulator-qlm-module"]], "simulator qulacs gpu module": [[7, "module-tequila_code.simulators.simulator_qulacs_gpu"]], "simulator qulacs module": [[7, "module-tequila_code.simulators.simulator_qulacs"]], "simulator symbolic module": [[7, "module-tequila_code.simulators.simulator_symbolic"]]}, "docnames": ["circuit", "docu_instruction", "hamiltonian", "index", "modules", "optimizers", "quantumchemistry", "simulators"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx.ext.viewcode": 1}, "filenames": ["circuit.rst", "docu_instruction.rst", "hamiltonian.rst", "index.rst", "modules.rst", "optimizers.rst", "quantumchemistry.rst", "simulators.rst"], "indexentries": {"abstract_circuit (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.abstract_circuit", false]], "abstract_h (tequila_code.simulators.simulator_base.backendexpectationvalue attribute)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.abstract_H", false]], "abstract_qubits (tequila_code.simulators.simulator_base.backendcircuit property)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.abstract_qubits", false]], "active_key_lookup (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.active_key_lookup", false]], "active_orbitals (tequila_code.quantumchemistry.chemistry_tools.activespacedata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ActiveSpaceData.active_orbitals", false]], "active_orbitals (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.active_orbitals", false]], "active_reference_orbitals (tequila_code.quantumchemistry.chemistry_tools.activespacedata property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ActiveSpaceData.active_reference_orbitals", false]], "active_reference_orbitals (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.active_reference_orbitals", false]], "active_space (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.active_space", false]], "active_space (tequila_code.quantumchemistry.qc_base.quantumchemistrybase property)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.active_space", false]], "active_space_is_trivial() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.active_space_is_trivial", false]], "activespacedata (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ActiveSpaceData", false]], "add_basic_gate() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "id0", false], [7, "tequila_code.simulators.simulator_base.BackendCircuit.add_basic_gate", false]], "add_basic_gate() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.add_basic_gate", false]], "add_controls() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.add_controls", false]], "add_exponential_pauli_gate() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.add_exponential_pauli_gate", false]], "add_gate() (tequila_code.circuit.circuit.moment method)": [[0, "tequila_code.circuit.circuit.Moment.add_gate", false]], "add_measurement() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "id1", false], [7, "tequila_code.simulators.simulator_base.BackendCircuit.add_measurement", false]], "add_measurement() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.add_measurement", false]], "add_noise_to_circuit() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.add_noise_to_circuit", false]], "add_parametrized_gate() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "id2", false], [7, "tequila_code.simulators.simulator_base.BackendCircuit.add_parametrized_gate", false]], "add_parametrized_gate() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.add_parametrized_gate", false]], "all_flags_true() (tequila_code.circuit.compiler.circuitcompiler class method)": [[0, "tequila_code.circuit.compiler.CircuitCompiler.all_flags_true", false]], "alpha (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.alpha", false]], "amplitudedamp() (in module tequila_code.circuit.noise)": [[0, "tequila_code.circuit.noise.AmplitudeDamp", false]], "amplitudes (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes", false]], "angles (tequila_code.optimizers.optimizer_base.optimizerhistory attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.angles", false]], "angles (tequila_code.optimizers.optimizer_base.optimizerresults property)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerResults.angles", false]], "angles_calls (tequila_code.optimizers.optimizer_base.optimizerhistory attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.angles_calls", false]], "apply_custom_gate() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.apply_custom_gate", false]], "apply_gate() (tequila_code.simulators.simulator_symbolic.backendcircuitsymbolic class method)": [[7, "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic.apply_gate", false]], "apply_on_standard_basis() (tequila_code.simulators.simulator_symbolic.backendcircuitsymbolic class method)": [[7, "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic.apply_on_standard_basis", false]], "as_circuit() (tequila_code.circuit.circuit.moment method)": [[0, "tequila_code.circuit.circuit.Moment.as_circuit", false]], "assign_name() (in module tequila_code.circuit.qpic)": [[0, "tequila_code.circuit.qpic.assign_name", false]], "assign_scheme() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor.ordering method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.Ordering.assign_scheme", false]], "available_diis() (tequila_code.optimizers.optimizer_gd.optimizergd class method)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.available_diis", false]], "available_methods() (in module tequila_code.optimizers.optimizer_scipy)": [[5, "tequila_code.optimizers.optimizer_scipy.available_methods", false]], "available_methods() (tequila_code.optimizers.optimizer_gd.optimizergd class method)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.available_methods", false]], "available_methods() (tequila_code.optimizers.optimizer_scipy.optimizerscipy class method)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.available_methods", false]], "backend (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.backend", false]], "backendcircuit (class in tequila_code.simulators.simulator_base)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit", false]], "backendcircuitqulacs (class in tequila_code.simulators.simulator_qulacs)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs", false]], "backendcircuitqulacsgpu (class in tequila_code.simulators.simulator_qulacs_gpu)": [[7, "tequila_code.simulators.simulator_qulacs_gpu.BackendCircuitQulacsGpu", false]], "backendcircuitsymbolic (class in tequila_code.simulators.simulator_symbolic)": [[7, "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic", false]], "backendcircuittype (tequila_code.simulators.simulator_base.backendexpectationvalue attribute)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.BackendCircuitType", false]], "backendcircuittype (tequila_code.simulators.simulator_qulacs.backendexpectationvaluequlacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendExpectationValueQulacs.BackendCircuitType", false]], "backendcircuittype (tequila_code.simulators.simulator_qulacs_gpu.backendexpectationvaluequlacsgpu attribute)": [[7, "tequila_code.simulators.simulator_qulacs_gpu.BackendExpectationValueQulacsGpu.BackendCircuitType", false]], "backendcircuittype (tequila_code.simulators.simulator_symbolic.backendexpectationvaluesymbolic attribute)": [[7, "tequila_code.simulators.simulator_symbolic.BackendExpectationValueSymbolic.BackendCircuitType", false]], "backendexpectationvalue (class in tequila_code.simulators.simulator_base)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue", false]], "backendexpectationvaluequlacs (class in tequila_code.simulators.simulator_qulacs)": [[7, "tequila_code.simulators.simulator_qulacs.BackendExpectationValueQulacs", false]], "backendexpectationvaluequlacsgpu (class in tequila_code.simulators.simulator_qulacs_gpu)": [[7, "tequila_code.simulators.simulator_qulacs_gpu.BackendExpectationValueQulacsGpu", false]], "backendexpectationvaluesymbolic (class in tequila_code.simulators.simulator_symbolic)": [[7, "tequila_code.simulators.simulator_symbolic.BackendExpectationValueSymbolic", false]], "backendtypes (class in tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.BackendTypes", false]], "basis_is_orthogonal() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.basis_is_orthogonal", false]], "basis_set (tequila_code.quantumchemistry.chemistry_tools.parametersqc attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.basis_set", false]], "beta (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.beta", false]], "bitflip() (in module tequila_code.circuit.noise)": [[0, "tequila_code.circuit.noise.BitFlip", false]], "bk_to_me() (tequila_code.quantumchemistry.encodings.bravyikitaev method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaev.bk_to_me", false]], "bk_to_me() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.bk_to_me", false]], "bravyikitaev (class in tequila_code.quantumchemistry.encodings)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaev", false]], "bravyikitaevfast (class in tequila_code.quantumchemistry.encodings)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaevFast", false]], "bravyikitaevtree (class in tequila_code.quantumchemistry.encodings)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaevTree", false]], "c (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.c", false]], "calibrate_lr (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.calibrate_lr", false]], "canonical_depth (tequila_code.circuit.circuit.moment property)": [[0, "tequila_code.circuit.circuit.Moment.canonical_depth", false]], "canonical_depth (tequila_code.circuit.circuit.qcircuit attribute)": [[0, "tequila_code.circuit.circuit.QCircuit.canonical_depth", false]], "canonical_depth (tequila_code.circuit.circuit.qcircuit property)": [[0, "id0", false]], "canonical_moments (tequila_code.circuit.circuit.moment property)": [[0, "tequila_code.circuit.circuit.Moment.canonical_moments", false]], "canonical_moments (tequila_code.circuit.circuit.qcircuit attribute)": [[0, "tequila_code.circuit.circuit.QCircuit.canonical_moments", false]], "canonical_moments (tequila_code.circuit.circuit.qcircuit property)": [[0, "id1", false]], "ccry() (tequila_code.quantumchemistry.chemistry_tools.fermionicgateimpl method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl.cCRy", false]], "change_basis() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.change_basis", false]], "charge (tequila_code.quantumchemistry.chemistry_tools.parametersqc attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.charge", false]], "check_device() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.check_device", false]], "circtype (tequila_code.simulators.simulator_api.backendtypes attribute)": [[7, "tequila_code.simulators.simulator_api.BackendTypes.CircType", false]], "circuit (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.circuit", false]], "circuit (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.circuit", false]], "circuitcompiler (class in tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.CircuitCompiler", false]], "cleanup() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.cleanup", false]], "closedshellamplitudes (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ClosedShellAmplitudes", false]], "cnot() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.CNOT", false]], "compile() (in module tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.compile", false]], "compile() (tequila_code.circuit.gates.qubitexcitationimpl method)": [[0, "tequila_code.circuit.gates.QubitExcitationImpl.compile", false]], "compile() (tequila_code.quantumchemistry.chemistry_tools.fermionicgateimpl method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl.compile", false]], "compile_ch() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_ch", false]], "compile_circuit() (in module tequila_code.circuit)": [[0, "tequila_code.circuit.compile_circuit", false]], "compile_circuit() (in module tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.compile_circuit", false]], "compile_circuit() (tequila_code.circuit.compiler.circuitcompiler method)": [[0, "tequila_code.circuit.compiler.CircuitCompiler.compile_circuit", false]], "compile_controlled_phase() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_controlled_phase", false]], "compile_controlled_power() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_controlled_power", false]], "compile_controlled_rotation() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_controlled_rotation", false]], "compile_exponential_pauli_gate() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_exponential_pauli_gate", false]], "compile_generalized_rotation_gate() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_generalized_rotation_gate", false]], "compile_gradient() (tequila_code.optimizers.optimizer_base.optimizer method)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.compile_gradient", false]], "compile_hessian() (tequila_code.optimizers.optimizer_base.optimizer method)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.compile_hessian", false]], "compile_multitarget() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_multitarget", false]], "compile_objective() (in module tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.compile_objective", false]], "compile_objective() (tequila_code.circuit.compiler.circuitcompiler method)": [[0, "id8", false], [0, "tequila_code.circuit.compiler.CircuitCompiler.compile_objective", false]], "compile_objective() (tequila_code.optimizers.optimizer_base.optimizer method)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.compile_objective", false]], "compile_objective_argument() (tequila_code.circuit.compiler.circuitcompiler method)": [[0, "id9", false], [0, "tequila_code.circuit.compiler.CircuitCompiler.compile_objective_argument", false]], "compile_phase() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_phase", false]], "compile_phase_to_z() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_phase_to_z", false]], "compile_power_base() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_power_base", false]], "compile_power_gate() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_power_gate", false]], "compile_ry() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_ry", false]], "compile_swap() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_swap", false]], "compile_to_function() (in module tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.compile_to_function", false]], "compile_to_single_control() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_to_single_control", false]], "compile_toffoli() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_toffoli", false]], "compile_trotterized_gate() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_trotterized_gate", false]], "compile_y() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compile_y", false]], "compiler() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.compiler", false]], "compiler_arguments (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "id3", false], [7, "tequila_code.simulators.simulator_base.BackendCircuit.compiler_arguments", false]], "compiler_arguments (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.compiler_arguments", false]], "compiler_arguments (tequila_code.simulators.simulator_symbolic.backendcircuitsymbolic attribute)": [[7, "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic.compiler_arguments", false]], "compute_amplitudes() (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 method)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.compute_amplitudes", false]], "compute_amplitudes() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_amplitudes", false]], "compute_ccsd_amplitudes() (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 method)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.compute_ccsd_amplitudes", false]], "compute_ccsd_amplitudes() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_ccsd_amplitudes", false]], "compute_cis_amplitudes() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_cis_amplitudes", false]], "compute_constant_part() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_constant_part", false]], "compute_energy() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.compute_energy", false]], "compute_energy() (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 method)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.compute_energy", false]], "compute_energy() (tequila_code.quantumchemistry.pyscf_interface.quantumchemistrypyscf method)": [[6, "tequila_code.quantumchemistry.pyscf_interface.QuantumChemistryPySCF.compute_energy", false]], "compute_energy() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_energy", false]], "compute_fci() (tequila_code.quantumchemistry.pyscf_interface.quantumchemistrypyscf method)": [[6, "tequila_code.quantumchemistry.pyscf_interface.QuantumChemistryPySCF.compute_fci", false]], "compute_fock_matrix() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_fock_matrix", false]], "compute_mp2_amplitudes() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_mp2_amplitudes", false]], "compute_one_body_integrals() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_one_body_integrals", false]], "compute_rdms() (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 method)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.compute_rdms", false]], "compute_rdms() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_rdms", false]], "compute_two_body_integrals() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.compute_two_body_integrals", false]], "const_part (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.const_part", false]], "constant_term (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.constant_term", false]], "convert_from_pyzx() (in module tequila_code.circuit.pyzx)": [[0, "tequila_code.circuit.pyzx.convert_from_pyzx", false]], "convert_madness_output_from_bin_to_npy() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.convert_madness_output_from_bin_to_npy", false]], "convert_measurements() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.convert_measurements", false]], "convert_measurements() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.convert_measurements", false]], "convert_to_list() (tequila_code.quantumchemistry.chemistry_tools.parametersqc static method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.convert_to_list", false]], "convert_to_numpy (tequila_code.simulators.simulator_symbolic.backendcircuitsymbolic attribute)": [[7, "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic.convert_to_numpy", false]], "convert_to_open_qasm_2() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.convert_to_open_qasm_2", false]], "convert_to_pyzx() (in module tequila_code.circuit.pyzx)": [[0, "tequila_code.circuit.pyzx.convert_to_pyzx", false]], "count_measurements() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.count_measurements", false]], "counter (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.counter", false]], "create_circuit() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "id4", false], [7, "tequila_code.simulators.simulator_base.BackendCircuit.create_circuit", false]], "create_circuit() (tequila_code.simulators.simulator_symbolic.backendcircuitsymbolic method)": [[7, "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic.create_circuit", false]], "crx() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.CRx", false]], "cry() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.CRy", false]], "crz() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.CRz", false]], "cx() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.CX", false]], "cy() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.CY", false]], "cz() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.CZ", false]], "dagger() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.dagger", false]], "decompose_transfer_operator() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.decompose_transfer_operator", false]], "depolarizingerror() (in module tequila_code.circuit.noise)": [[0, "tequila_code.circuit.noise.DepolarizingError", false]], "depth (tequila_code.circuit.circuit.moment property)": [[0, "tequila_code.circuit.circuit.Moment.depth", false]], "depth (tequila_code.circuit.circuit.qcircuit attribute)": [[0, "tequila_code.circuit.circuit.QCircuit.depth", false]], "depth (tequila_code.circuit.circuit.qcircuit property)": [[0, "id2", false]], "description (tequila_code.quantumchemistry.chemistry_tools.parametersqc attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.description", false]], "device (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.device", false]], "device (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.device", false]], "diis (class in tequila_code.optimizers.optimizer_gd)": [[5, "tequila_code.optimizers.optimizer_gd.DIIS", false]], "diis (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.diis", false]], "do_compile_trotterized_gate() (in module tequila_code.circuit.compiler)": [[0, "tequila_code.circuit.compiler.do_compile_trotterized_gate", false]], "do_diis() (tequila_code.optimizers.optimizer_gd.diis method)": [[5, "tequila_code.optimizers.optimizer_gd.DIIS.do_diis", false]], "do_make_molecule() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.do_make_molecule", false]], "do_sample() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.do_sample", false]], "do_sample() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.do_sample", false]], "do_simulate() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.do_simulate", false]], "do_simulate() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.do_simulate", false]], "do_simulate() (tequila_code.simulators.simulator_symbolic.backendcircuitsymbolic method)": [[7, "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic.do_simulate", false]], "do_transform() (tequila_code.quantumchemistry.encodings.bravyikitaev method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaev.do_transform", false]], "do_transform() (tequila_code.quantumchemistry.encodings.bravyikitaevfast method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaevFast.do_transform", false]], "do_transform() (tequila_code.quantumchemistry.encodings.bravyikitaevtree method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaevTree.do_transform", false]], "do_transform() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.do_transform", false]], "do_transform() (tequila_code.quantumchemistry.encodings.jordanwigner method)": [[6, "tequila_code.quantumchemistry.encodings.JordanWigner.do_transform", false]], "do_transform() (tequila_code.quantumchemistry.encodings.taperedbravykitaev method)": [[6, "tequila_code.quantumchemistry.encodings.TaperedBravyKitaev.do_transform", false]], "down() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.down", false]], "draw() (in module tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.draw", false]], "drop_error() (tequila_code.optimizers.optimizer_gd.diis method)": [[5, "tequila_code.optimizers.optimizer_gd.DIIS.drop_error", false]], "drop_first() (tequila_code.optimizers.optimizer_gd.diis method)": [[5, "tequila_code.optimizers.optimizer_gd.DIIS.drop_first", false]], "encodingbase (class in tequila_code.quantumchemistry.encodings)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase", false]], "energies (tequila_code.optimizers.optimizer_base.optimizerhistory attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.energies", false]], "energies_calls (tequila_code.optimizers.optimizer_base.optimizerhistory property)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.energies_calls", false]], "energies_evaluations (tequila_code.optimizers.optimizer_base.optimizerhistory property)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.energies_evaluations", false]], "energy (tequila_code.optimizers.optimizer_base.optimizerresults attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerResults.energy", false]], "energy (tequila_code.quantumchemistry.chemistry_tools.orbitaldata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.OrbitalData.energy", false]], "energy (tequila_code.quantumchemistry.orbital_optimizer.optimizeorbitalsresult attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult.energy", false]], "energy_calls (tequila_code.optimizers.optimizer_base.optimizerhistory attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.energy_calls", false]], "epsilon (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.epsilon", false]], "export_open_qasm() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.export_open_qasm", false]], "export_to() (in module tequila_code.circuit.qpic)": [[0, "tequila_code.circuit.qpic.export_to", false]], "export_to() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.export_to", false]], "export_to_qpic() (in module tequila_code.circuit.qpic)": [[0, "tequila_code.circuit.qpic.export_to_qpic", false]], "exppauli() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.ExpPauli", false]], "expvaluetype (tequila_code.simulators.simulator_api.backendtypes attribute)": [[7, "tequila_code.simulators.simulator_api.BackendTypes.ExpValueType", false]], "extract_angles() (tequila_code.optimizers.optimizer_base.optimizerhistory method)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.extract_angles", false]], "extract_energies() (tequila_code.optimizers.optimizer_base.optimizerhistory method)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.extract_energies", false]], "extract_gradients() (tequila_code.optimizers.optimizer_base.optimizerhistory method)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.extract_gradients", false]], "extract_variables() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.extract_variables", false]], "extract_variables() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.extract_variables", false]], "extract_variables() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.extract_variables", false]], "f (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.f", false]], "fermionic_excitation() (tequila_code.quantumchemistry.chemistry_tools.fermionicgateimpl method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl.fermionic_excitation", false]], "fermionicgateimpl (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl", false]], "filename (tequila_code.quantumchemistry.chemistry_tools.parametersqc property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.filename", false]], "filename (tequila_code.quantumchemistry.psi4_interface.psi4results attribute)": [[6, "tequila_code.quantumchemistry.psi4_interface.Psi4Results.filename", false]], "find_executable() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness static method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.find_executable", false]], "find_unused_qubit() (in module tequila_code.circuit.circuit)": [[0, "tequila_code.circuit.circuit.find_unused_qubit", false]], "format_element_name() (tequila_code.quantumchemistry.chemistry_tools.parametersqc static method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.format_element_name", false]], "format_excitation_indices() (tequila_code.quantumchemistry.chemistry_tools.fermionicgateimpl method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl.format_excitation_indices", false]], "format_excitation_indices() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.format_excitation_indices", false]], "format_excitation_variables() (tequila_code.quantumchemistry.chemistry_tools.fermionicgateimpl method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl.format_excitation_variables", false]], "from_closed_shell() (tequila_code.quantumchemistry.chemistry_tools.amplitudes class method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes.from_closed_shell", false]], "from_dict() (tequila_code.circuit.noise.quantumnoise static method)": [[0, "tequila_code.circuit.noise.QuantumNoise.from_dict", false]], "from_moments() (tequila_code.circuit.circuit.moment static method)": [[0, "tequila_code.circuit.circuit.Moment.from_moments", false]], "from_moments() (tequila_code.circuit.circuit.qcircuit static method)": [[0, "tequila_code.circuit.circuit.QCircuit.from_moments", false]], "from_openfermion() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase class method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.from_openfermion", false]], "from_string() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.from_string", false]], "from_tequila() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase class method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.from_tequila", false]], "frozen_core (tequila_code.quantumchemistry.chemistry_tools.parametersqc attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.frozen_core", false]], "frozen_reference_orbitals (tequila_code.quantumchemistry.chemistry_tools.activespacedata property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ActiveSpaceData.frozen_reference_orbitals", false]], "fully_parametrized() (tequila_code.circuit.circuit.moment method)": [[0, "tequila_code.circuit.circuit.Moment.fully_parametrized", false]], "gamma (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.gamma", false]], "gates (tequila_code.circuit.circuit.qcircuit attribute)": [[0, "tequila_code.circuit.circuit.QCircuit.gates", false]], "gates (tequila_code.circuit.circuit.qcircuit property)": [[0, "id3", false]], "gdresults (class in tequila_code.optimizers.optimizer_gd)": [[5, "tequila_code.optimizers.optimizer_gd.GDResults", false]], "generalizedrotation() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.GeneralizedRotation", false]], "genrot() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.GenRot", false]], "geometry (tequila_code.quantumchemistry.chemistry_tools.parametersqc attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.geometry", false]], "get_angle() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.get_angle", false]], "get_atom_number() (tequila_code.quantumchemistry.chemistry_tools.parametersqc method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.get_atom_number", false]], "get_atoms() (tequila_code.quantumchemistry.chemistry_tools.parametersqc method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.get_atoms", false]], "get_geometry() (tequila_code.quantumchemistry.chemistry_tools.parametersqc method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.get_geometry", false]], "get_geometry_string() (tequila_code.quantumchemistry.chemistry_tools.parametersqc method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.get_geometry_string", false]], "get_givens_circuit() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.get_givens_circuit", false]], "get_givens_decomposition() (in module tequila_code.quantumchemistry.qc_base)": [[6, "tequila_code.quantumchemistry.qc_base.get_givens_decomposition", false]], "get_integrals() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.get_integrals", false]], "get_integrals() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.get_integrals", false]], "get_nuc_charge() (tequila_code.quantumchemistry.chemistry_tools.parametersqc method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.get_nuc_charge", false]], "get_number_of_core_electrons() (tequila_code.quantumchemistry.chemistry_tools.parametersqc method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.get_number_of_core_electrons", false]], "get_orthonormalized_orbital_coefficients() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.get_orthonormalized_orbital_coefficients", false]], "get_pair_orbitals() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.get_pair_orbitals", false]], "get_pair_specific_indices() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.get_pair_specific_indices", false]], "get_qregister() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.get_qregister", false]], "get_virtual_orbitals() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.get_virtual_orbitals", false]], "givens() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Givens", false]], "givens_matrix() (in module tequila_code.quantumchemistry.qc_base)": [[6, "tequila_code.quantumchemistry.qc_base.givens_matrix", false]], "grad() (in module tequila_code.circuit.gradient)": [[0, "tequila_code.circuit.gradient.grad", false]], "gradient_based_methods (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.gradient_based_methods", false]], "gradient_calls (tequila_code.optimizers.optimizer_base.optimizerhistory attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.gradient_calls", false]], "gradient_free_methods (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.gradient_free_methods", false]], "gradient_lookup (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.gradient_lookup", false]], "gradients (tequila_code.optimizers.optimizer_base.optimizerhistory attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.gradients", false]], "h (tequila_code.simulators.simulator_base.backendexpectationvalue attribute)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.H", false]], "h (tequila_code.simulators.simulator_base.backendexpectationvalue property)": [[7, "id6", false]], "h() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.H", false]], "has_noise (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.has_noise", false]], "hcb_to_me() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.hcb_to_me", false]], "hcb_to_me() (tequila_code.quantumchemistry.encodings.jordanwigner method)": [[6, "tequila_code.quantumchemistry.encodings.JordanWigner.hcb_to_me", false]], "hcb_to_me() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.hcb_to_me", false]], "hessian_based_methods (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.hessian_based_methods", false]], "history (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.history", false]], "history (tequila_code.optimizers.optimizer_base.optimizerresults attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerResults.history", false]], "history (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.history", false]], "i() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.I", false]], "identify_ordering() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.identify_ordering", false]], "idx (tequila_code.quantumchemistry.chemistry_tools.orbitaldata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.OrbitalData.idx", false]], "idx_irrep (tequila_code.quantumchemistry.chemistry_tools.orbitaldata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.OrbitalData.idx_irrep", false]], "idx_total (tequila_code.quantumchemistry.chemistry_tools.orbitaldata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.OrbitalData.idx_total", false]], "import_open_qasm() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.import_open_qasm", false]], "import_open_qasm_from_file() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.import_open_qasm_from_file", false]], "initialize_circuit() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.initialize_circuit", false]], "initialize_circuit() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.initialize_circuit", false]], "initialize_hamiltonian() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "id8", false], [7, "tequila_code.simulators.simulator_base.BackendExpectationValue.initialize_hamiltonian", false]], "initialize_hamiltonian() (tequila_code.simulators.simulator_qulacs.backendexpectationvaluequlacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendExpectationValueQulacs.initialize_hamiltonian", false]], "initialize_integral_manager() (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 method)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.initialize_integral_manager", false]], "initialize_integral_manager() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.initialize_integral_manager", false]], "initialize_qubit() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.initialize_qubit", false]], "initialize_state() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.initialize_state", false]], "initialize_state() (tequila_code.simulators.simulator_qulacs_gpu.backendcircuitqulacsgpu method)": [[7, "tequila_code.simulators.simulator_qulacs_gpu.BackendCircuitQulacsGpu.initialize_state", false]], "initialize_unitary() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "id9", false], [7, "tequila_code.simulators.simulator_base.BackendExpectationValue.initialize_unitary", false]], "initialize_variables() (tequila_code.optimizers.optimizer_base.optimizer method)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.initialize_variables", false]], "insert_gates() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.insert_gates", false]], "integralmanager (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager", false]], "irrep (tequila_code.quantumchemistry.chemistry_tools.orbitaldata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.OrbitalData.irrep", false]], "is_canonical() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.is_canonical", false]], "is_chem() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor.ordering method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.Ordering.is_chem", false]], "is_closed_shell() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.is_closed_shell", false]], "is_convertable_to_qubit_excitation() (tequila_code.quantumchemistry.chemistry_tools.fermionicgateimpl method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl.is_convertable_to_qubit_excitation", false]], "is_fully_parametrized() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.is_fully_parametrized", false]], "is_fully_unparametrized() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.is_fully_unparametrized", false]], "is_mixed() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.is_mixed", false]], "is_of() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor.ordering method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.Ordering.is_of", false]], "is_phys() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor.ordering method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.Ordering.is_phys", false]], "is_primitive() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.is_primitive", false]], "is_unitary() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.is_unitary", false]], "iswap() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.iSWAP", false]], "iteration (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.iteration", false]], "iterations (tequila_code.optimizers.optimizer_base.optimizerhistory property)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.iterations", false]], "iterations (tequila_code.quantumchemistry.orbital_optimizer.optimizeorbitalsresult attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult.iterations", false]], "jordanwigner (class in tequila_code.quantumchemistry.encodings)": [[6, "tequila_code.quantumchemistry.encodings.JordanWigner", false]], "jw_to_me() (tequila_code.quantumchemistry.encodings.bravyikitaev method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaev.jw_to_me", false]], "jw_to_me() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.jw_to_me", false]], "jw_to_me() (tequila_code.quantumchemistry.encodings.jordanwigner method)": [[6, "tequila_code.quantumchemistry.encodings.JordanWigner.jw_to_me", false]], "kernel() (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper method)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.kernel", false]], "ketbra() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.KetBra", false]], "known_encodings() (in module tequila_code.quantumchemistry.encodings)": [[6, "tequila_code.quantumchemistry.encodings.known_encodings", false]], "level (tequila_code.circuit.noise.quantumnoise attribute)": [[0, "tequila_code.circuit.noise.QuantumNoise.level", false]], "level (tequila_code.circuit.noise.quantumnoise property)": [[0, "id10", false]], "local_qubit_map() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.local_qubit_map", false]], "lr (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.lr", false]], "make_annihilation_op() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_annihilation_op", false]], "make_ansatz() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_ansatz", false]], "make_creation_op() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_creation_op", false]], "make_excitation_gate() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_excitation_gate", false]], "make_excitation_generator() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_excitation_generator", false]], "make_hamiltonian() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_hamiltonian", false]], "make_hardcore_boson_excitation_gate() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_hardcore_boson_excitation_gate", false]], "make_hardcore_boson_hamiltonian() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_hardcore_boson_hamiltonian", false]], "make_hardcore_boson_pno_upccd_ansatz() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.make_hardcore_boson_pno_upccd_ansatz", false]], "make_hardcore_boson_upccgd_layer() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_hardcore_boson_upccgd_layer", false]], "make_molecular_hamiltonian() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_molecular_hamiltonian", false]], "make_molecule() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_molecule", false]], "make_number_op() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_number_op", false]], "make_orbital_rotation_gate() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_orbital_rotation_gate", false]], "make_parameter_dictionary() (tequila_code.quantumchemistry.chemistry_tools.amplitudes method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes.make_parameter_dictionary", false]], "make_parameter_dictionary() (tequila_code.quantumchemistry.chemistry_tools.closedshellamplitudes method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ClosedShellAmplitudes.make_parameter_dictionary", false]], "make_parameter_map() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.make_parameter_map", false]], "make_pno_upccgsd_ansatz() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.make_pno_upccgsd_ansatz", false]], "make_qubit_map() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.make_qubit_map", false]], "make_rdm12() (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper method)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.make_rdm12", false]], "make_s2_op() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_s2_op", false]], "make_sm_op() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_sm_op", false]], "make_sp_op() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_sp_op", false]], "make_spa_ansatz() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.make_spa_ansatz", false]], "make_spa_ansatz() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_spa_ansatz", false]], "make_sz_op() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_sz_op", false]], "make_uccsd_ansatz() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_uccsd_ansatz", false]], "make_upccgsd_ansatz() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.make_upccgsd_ansatz", false]], "make_upccgsd_ansatz() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_upccgsd_ansatz", false]], "make_upccgsd_indices() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.make_upccgsd_indices", false]], "make_upccgsd_indices() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_upccgsd_indices", false]], "make_upccgsd_layer() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_upccgsd_layer", false]], "make_upccgsd_singles() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.make_upccgsd_singles", false]], "map_qubits() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.map_qubits", false]], "map_qubits() (tequila_code.circuit.gates.qubitexcitationimpl method)": [[0, "tequila_code.circuit.gates.QubitExcitationImpl.map_qubits", false]], "map_state() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.map_state", false]], "map_state() (tequila_code.quantumchemistry.encodings.jordanwigner method)": [[6, "tequila_code.quantumchemistry.encodings.JordanWigner.map_state", false]], "map_state() (tequila_code.quantumchemistry.encodings.taperedbravykitaev method)": [[6, "tequila_code.quantumchemistry.encodings.TaperedBravyKitaev.map_state", false]], "map_variables() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.map_variables", false]], "max_qubit() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.max_qubit", false]], "maxiter (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.maxiter", false]], "mcscf_local_data (tequila_code.quantumchemistry.orbital_optimizer.optimizeorbitalsresult attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult.mcscf_local_data", false]], "mcscf_object (tequila_code.quantumchemistry.orbital_optimizer.optimizeorbitalsresult attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult.mcscf_object", false]], "me_to_bk() (tequila_code.quantumchemistry.encodings.bravyikitaev method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaev.me_to_bk", false]], "me_to_bk() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.me_to_bk", false]], "me_to_jw() (tequila_code.quantumchemistry.encodings.bravyikitaev method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaev.me_to_jw", false]], "me_to_jw() (tequila_code.quantumchemistry.encodings.bravyikitaevfast method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaevFast.me_to_jw", false]], "me_to_jw() (tequila_code.quantumchemistry.encodings.bravyikitaevtree method)": [[6, "tequila_code.quantumchemistry.encodings.BravyiKitaevTree.me_to_jw", false]], "me_to_jw() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.me_to_jw", false]], "me_to_jw() (tequila_code.quantumchemistry.encodings.jordanwigner method)": [[6, "tequila_code.quantumchemistry.encodings.JordanWigner.me_to_jw", false]], "me_to_jw() (tequila_code.quantumchemistry.encodings.taperedbravykitaev method)": [[6, "tequila_code.quantumchemistry.encodings.TaperedBravyKitaev.me_to_jw", false]], "method (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.method", false]], "method_bounds (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.method_bounds", false]], "method_constraints (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.method_constraints", false]], "method_options (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.method_options", false]], "minimize() (in module tequila_code.optimizers)": [[5, "tequila_code.optimizers.minimize", false]], "minimize() (in module tequila_code.optimizers.optimizer_gd)": [[5, "tequila_code.optimizers.optimizer_gd.minimize", false]], "minimize() (in module tequila_code.optimizers.optimizer_scipy)": [[5, "tequila_code.optimizers.optimizer_scipy.minimize", false]], "mo_coeff (tequila_code.quantumchemistry.orbital_optimizer.optimizeorbitalsresult attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult.mo_coeff", false]], "module": [[0, "module-tequila_code.circuit", false], [0, "module-tequila_code.circuit.circuit", false], [0, "module-tequila_code.circuit.compiler", false], [0, "module-tequila_code.circuit.gates", false], [0, "module-tequila_code.circuit.gradient", false], [0, "module-tequila_code.circuit.noise", false], [0, "module-tequila_code.circuit.pyzx", false], [0, "module-tequila_code.circuit.qasm", false], [0, "module-tequila_code.circuit.qpic", false], [2, "module-tequila_code.hamiltonian", false], [2, "module-tequila_code.hamiltonian.paulis", false], [2, "module-tequila_code.hamiltonian.paulistring", false], [5, "module-tequila_code.optimizers", false], [5, "module-tequila_code.optimizers.optimizer_base", false], [5, "module-tequila_code.optimizers.optimizer_gd", false], [5, "module-tequila_code.optimizers.optimizer_scipy", false], [6, "module-tequila_code.quantumchemistry", false], [6, "module-tequila_code.quantumchemistry.chemistry_tools", false], [6, "module-tequila_code.quantumchemistry.encodings", false], [6, "module-tequila_code.quantumchemistry.madness_interface", false], [6, "module-tequila_code.quantumchemistry.orbital_optimizer", false], [6, "module-tequila_code.quantumchemistry.psi4_interface", false], [6, "module-tequila_code.quantumchemistry.pyscf_interface", false], [6, "module-tequila_code.quantumchemistry.qc_base", false], [7, "module-tequila_code.simulators", false], [7, "module-tequila_code.simulators.simulator_api", false], [7, "module-tequila_code.simulators.simulator_base", false], [7, "module-tequila_code.simulators.simulator_qulacs", false], [7, "module-tequila_code.simulators.simulator_qulacs_gpu", false], [7, "module-tequila_code.simulators.simulator_symbolic", false]], "mol (tequila_code.quantumchemistry.psi4_interface.psi4results attribute)": [[6, "tequila_code.quantumchemistry.psi4_interface.Psi4Results.mol", false]], "molecular_data_param (tequila_code.quantumchemistry.chemistry_tools.parametersqc property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.molecular_data_param", false]], "molecule (tequila_code.quantumchemistry.orbital_optimizer.optimizeorbitalsresult attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult.molecule", false]], "molecule() (in module tequila_code.quantumchemistry)": [[6, "tequila_code.quantumchemistry.Molecule", false]], "molecule_arguments (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.molecule_arguments", false]], "molecule_factory (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.molecule_factory", false]], "moleculefromopenfermion() (in module tequila_code.quantumchemistry)": [[6, "tequila_code.quantumchemistry.MoleculeFromOpenFermion", false]], "moleculefromtequila() (in module tequila_code.quantumchemistry)": [[6, "tequila_code.quantumchemistry.MoleculeFromTequila", false]], "moment (class in tequila_code.circuit.circuit)": [[0, "tequila_code.circuit.circuit.Moment", false]], "moments (tequila_code.circuit.circuit.moment property)": [[0, "tequila_code.circuit.circuit.Moment.moments", false]], "moments (tequila_code.circuit.circuit.qcircuit attribute)": [[0, "tequila_code.circuit.circuit.QCircuit.moments", false]], "moments (tequila_code.circuit.circuit.qcircuit property)": [[0, "id4", false]], "moments (tequila_code.optimizers.optimizer_gd.gdresults attribute)": [[5, "tequila_code.optimizers.optimizer_gd.GDResults.moments", false]], "moments_lookup (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.moments_lookup", false]], "moments_trajectory (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.moments_trajectory", false]], "multiplicity (tequila_code.quantumchemistry.chemistry_tools.parametersqc attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.multiplicity", false]], "n_electrons (tequila_code.quantumchemistry.chemistry_tools.parametersqc property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.n_electrons", false]], "n_electrons (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.n_electrons", false]], "n_electrons (tequila_code.quantumchemistry.qc_base.quantumchemistrybase property)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.n_electrons", false]], "n_orbitals (tequila_code.quantumchemistry.qc_base.quantumchemistrybase property)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.n_orbitals", false]], "n_qubits (tequila_code.circuit.circuit.qcircuit attribute)": [[0, "tequila_code.circuit.circuit.QCircuit.n_qubits", false]], "n_qubits (tequila_code.circuit.circuit.qcircuit property)": [[0, "id5", false]], "n_qubits (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.n_qubits", false]], "n_qubits (tequila_code.simulators.simulator_base.backendcircuit property)": [[7, "id5", false]], "n_qubits (tequila_code.simulators.simulator_base.backendexpectationvalue attribute)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.n_qubits", false]], "n_qubits (tequila_code.simulators.simulator_base.backendexpectationvalue property)": [[7, "id10", false]], "n_rotation() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.n_rotation", false]], "name (tequila_code.circuit.noise.quantumnoise attribute)": [[0, "tequila_code.circuit.noise.QuantumNoise.name", false]], "name (tequila_code.circuit.noise.quantumnoise property)": [[0, "id11", false]], "name (tequila_code.quantumchemistry.chemistry_tools.parametersqc attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.name", false]], "name (tequila_code.quantumchemistry.encodings.encodingbase property)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.name", false]], "name_and_params() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.name_and_params", false]], "nbodytensor (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor", false]], "nbodytensor.ordering (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.Ordering", false]], "nextlearningrate() (tequila_code.optimizers.optimizer_gd.optimizergd method)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.nextLearningRate", false]], "nirrep (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 property)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.nirrep", false]], "no_translation (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.no_translation", false]], "no_translation() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.no_translation", false]], "noise (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.noise", false]], "noise (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.noise", false]], "noise_lookup (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.noise_lookup", false]], "noisemodel (class in tequila_code.circuit.noise)": [[0, "tequila_code.circuit.noise.NoiseModel", false]], "noises (tequila_code.circuit.noise.noisemodel attribute)": [[0, "tequila_code.circuit.noise.NoiseModel.noises", false]], "num_iteration (tequila_code.optimizers.optimizer_gd.gdresults attribute)": [[5, "tequila_code.optimizers.optimizer_gd.GDResults.num_iteration", false]], "numbering (tequila_code.circuit.circuit.qcircuit attribute)": [[0, "tequila_code.circuit.circuit.QCircuit.numbering", false]], "numbering (tequila_code.circuit.circuit.qcircuit property)": [[0, "id6", false]], "numbering (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.numbering", false]], "occ (tequila_code.quantumchemistry.chemistry_tools.orbitaldata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.OrbitalData.occ", false]], "old_molecule (tequila_code.quantumchemistry.orbital_optimizer.optimizeorbitalsresult attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult.old_molecule", false]], "one_body_integrals (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.one_body_integrals", false]], "one_body_integrals (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.one_body_integrals", false]], "op_lookup (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.op_lookup", false]], "openvqeepyscfexception": [[6, "tequila_code.quantumchemistry.psi4_interface.OpenVQEEPySCFException", false], [6, "tequila_code.quantumchemistry.pyscf_interface.OpenVQEEPySCFException", false]], "optimize_circuit() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.optimize_circuit", false]], "optimize_circuit() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.optimize_circuit", false]], "optimize_orbitals() (in module tequila_code.quantumchemistry.orbital_optimizer)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.optimize_orbitals", false]], "optimizeorbitalsresult (class in tequila_code.quantumchemistry.orbital_optimizer)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult", false]], "optimizer (class in tequila_code.optimizers.optimizer_base)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer", false]], "optimizergd (class in tequila_code.optimizers.optimizer_gd)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD", false]], "optimizerhistory (class in tequila_code.optimizers.optimizer_base)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory", false]], "optimizerresults (class in tequila_code.optimizers.optimizer_base)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerResults", false]], "optimizerscipy (class in tequila_code.optimizers.optimizer_scipy)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy", false]], "orbital_coefficients (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.orbital_coefficients", false]], "orbital_energies() (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 method)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.orbital_energies", false]], "orbitaldata (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.OrbitalData", false]], "orbitals (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.orbitals", false]], "orbitals (tequila_code.quantumchemistry.qc_base.quantumchemistrybase property)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.orbitals", false]], "orthonormalize_basis_orbitals() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.orthonormalize_basis_orbitals", false]], "overlap_integrals (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.overlap_integrals", false]], "pair (tequila_code.quantumchemistry.chemistry_tools.orbitaldata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.OrbitalData.pair", false]], "parametersqc (class in tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC", false]], "parse_command() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.parse_command", false]], "parse_custom_gate() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.parse_custom_gate", false]], "parse_from_open_qasm_2() (in module tequila_code.circuit.qasm)": [[0, "tequila_code.circuit.qasm.parse_from_open_qasm_2", false]], "pauli() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.pauli", false]], "pauligate() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.PauliGate", false]], "perturbative_f12_correction() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.perturbative_f12_correction", false]], "perturbative_f12_correction() (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 method)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.perturbative_f12_correction", false]], "perturbative_f12_correction() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.perturbative_f12_correction", false]], "phase() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Phase", false]], "phaseamplitudedamp() (in module tequila_code.circuit.noise)": [[0, "tequila_code.circuit.noise.PhaseAmplitudeDamp", false]], "phasedamp() (in module tequila_code.circuit.noise)": [[0, "tequila_code.circuit.noise.PhaseDamp", false]], "phaseflip() (in module tequila_code.circuit.noise)": [[0, "tequila_code.circuit.noise.PhaseFlip", false]], "pick_backend() (in module tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.pick_backend", false]], "plot() (tequila_code.optimizers.optimizer_base.optimizerhistory method)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerHistory.plot", false]], "plot2cube() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.plot2cube", false]], "point_group (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 property)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.point_group", false]], "post_processing() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.post_processing", false]], "powergate() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.PowerGate", false]], "prepare() (tequila_code.optimizers.optimizer_gd.optimizergd method)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.prepare", false]], "prepare_hardcore_boson_reference() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.prepare_hardcore_boson_reference", false]], "prepare_product_state() (in module tequila_code.quantumchemistry.chemistry_tools)": [[6, "tequila_code.quantumchemistry.chemistry_tools.prepare_product_state", false]], "prepare_reference() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.prepare_reference", false]], "print_basis_info() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.print_basis_info", false]], "print_basis_info() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.print_basis_info", false]], "print_level (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.print_level", false]], "prob_length (tequila_code.circuit.noise.quantumnoise attribute)": [[0, "tequila_code.circuit.noise.QuantumNoise.prob_length", false]], "probs (tequila_code.circuit.noise.quantumnoise attribute)": [[0, "tequila_code.circuit.noise.QuantumNoise.probs", false]], "projector() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.Projector", false]], "psi4results (class in tequila_code.quantumchemistry.psi4_interface)": [[6, "tequila_code.quantumchemistry.psi4_interface.Psi4Results", false]], "push() (tequila_code.optimizers.optimizer_gd.diis method)": [[5, "tequila_code.optimizers.optimizer_gd.DIIS.push", false]], "pyscfvqewrapper (class in tequila_code.quantumchemistry.orbital_optimizer)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper", false]], "qcircuit (class in tequila_code.circuit.circuit)": [[0, "tequila_code.circuit.circuit.QCircuit", false]], "qgate() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.QGate", false]], "qm() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.Qm", false]], "qp() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.Qp", false]], "quantumchemistrybase (class in tequila_code.quantumchemistry.qc_base)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase", false]], "quantumchemistrymadness (class in tequila_code.quantumchemistry.madness_interface)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness", false]], "quantumchemistrypsi4 (class in tequila_code.quantumchemistry.psi4_interface)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4", false]], "quantumchemistrypyscf (class in tequila_code.quantumchemistry.pyscf_interface)": [[6, "tequila_code.quantumchemistry.pyscf_interface.QuantumChemistryPySCF", false]], "quantumnoise (class in tequila_code.circuit.noise)": [[0, "tequila_code.circuit.noise.QuantumNoise", false]], "qubit() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.qubit", false]], "qubit_map (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.qubit_map", false]], "qubitexcitation() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.QubitExcitation", false]], "qubitexcitationimpl (class in tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.QubitExcitationImpl", false]], "qubits (tequila_code.circuit.circuit.qcircuit attribute)": [[0, "tequila_code.circuit.circuit.QCircuit.qubits", false]], "qubits (tequila_code.circuit.circuit.qcircuit property)": [[0, "id7", false]], "qubits (tequila_code.simulators.simulator_base.backendcircuit attribute)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.qubits", false]], "rdm1 (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.rdm1", false]], "rdm1 (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 property)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.rdm1", false]], "rdm1 (tequila_code.quantumchemistry.qc_base.quantumchemistrybase property)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.rdm1", false]], "rdm2 (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.rdm2", false]], "rdm2 (tequila_code.quantumchemistry.psi4_interface.quantumchemistrypsi4 property)": [[6, "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4.rdm2", false]], "rdm2 (tequila_code.quantumchemistry.qc_base.quantumchemistrybase property)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.rdm2", false]], "rdm_spinsum() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.rdm_spinsum", false]], "read_tensors() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.read_tensors", false]], "read_xyz_from_file() (tequila_code.quantumchemistry.chemistry_tools.parametersqc static method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ParametersQC.read_xyz_from_file", false]], "reconstruct_matrix_from_givens() (in module tequila_code.quantumchemistry.qc_base)": [[6, "tequila_code.quantumchemistry.qc_base.reconstruct_matrix_from_givens", false]], "reduce_hamiltonians() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.reduce_hamiltonians", false]], "reference_orbitals (tequila_code.quantumchemistry.chemistry_tools.activespacedata attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ActiveSpaceData.reference_orbitals", false]], "reference_orbitals (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.reference_orbitals", false]], "reference_orbitals (tequila_code.quantumchemistry.qc_base.quantumchemistrybase property)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.reference_orbitals", false]], "reorder() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.reorder", false]], "reorder() (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper method)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.reorder", false]], "replace_gate() (tequila_code.circuit.circuit.moment method)": [[0, "tequila_code.circuit.circuit.Moment.replace_gate", false]], "replace_gates() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.replace_gates", false]], "reset() (tequila_code.optimizers.optimizer_gd.diis method)": [[5, "tequila_code.optimizers.optimizer_gd.DIIS.reset", false]], "reset_history() (tequila_code.optimizers.optimizer_base.optimizer method)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.reset_history", false]], "reset_momenta() (tequila_code.optimizers.optimizer_gd.optimizergd method)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.reset_momenta", false]], "reset_momenta_for() (tequila_code.optimizers.optimizer_gd.optimizergd method)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.reset_momenta_for", false]], "reset_stepper() (tequila_code.optimizers.optimizer_gd.optimizergd method)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.reset_stepper", false]], "retrieve_device() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.retrieve_device", false]], "rho (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.rho", false]], "rotationgate() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.RotationGate", false]], "rp() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Rp", false]], "run_madness() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.run_madness", false]], "rx() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Rx", false]], "ry() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Ry", false]], "rz() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Rz", false]], "s() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.S", false]], "sample() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.sample", false]], "sample() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.sample", false]], "sample() (tequila_code.simulators.simulator_qulacs.backendexpectationvaluequlacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendExpectationValueQulacs.sample", false]], "sample_all_z_hamiltonian() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.sample_all_z_hamiltonian", false]], "sample_paulistring() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.sample_paulistring", false]], "sample_paulistring() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.sample_paulistring", false]], "samples (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.samples", false]], "save_history (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.save_history", false]], "scipy_result (tequila_code.optimizers.optimizer_scipy.scipyresults attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.SciPyResults.scipy_result", false]], "scipyresults (class in tequila_code.optimizers.optimizer_scipy)": [[5, "tequila_code.optimizers.optimizer_scipy.SciPyResults", false]], "set_index_lists() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.set_index_lists", false]], "shape (tequila_code.quantumchemistry.chemistry_tools.nbodytensor property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.shape", false]], "show_available_modules() (in module tequila_code.quantumchemistry)": [[6, "tequila_code.quantumchemistry.show_available_modules", false]], "show_available_optimizers() (in module tequila_code.optimizers)": [[5, "tequila_code.optimizers.show_available_optimizers", false]], "show_available_simulators() (in module tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.show_available_simulators", false]], "show_supported_modules() (in module tequila_code.quantumchemistry)": [[6, "tequila_code.quantumchemistry.show_supported_modules", false]], "silent (tequila_code.optimizers.optimizer_base.optimizer attribute)": [[5, "tequila_code.optimizers.optimizer_base.Optimizer.silent", false]], "silent (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.silent", false]], "silent (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.silent", false]], "simulate() (in module tequila_code.simulators.simulator_api)": [[7, "tequila_code.simulators.simulator_api.simulate", false]], "simulate() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.simulate", false]], "simulate() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.simulate", false]], "simulate() (tequila_code.simulators.simulator_qulacs.backendexpectationvaluequlacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendExpectationValueQulacs.simulate", false]], "sm() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.Sm", false]], "sort_gates() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.sort_gates", false]], "sp() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.Sp", false]], "standard_gate_set() (tequila_code.circuit.compiler.circuitcompiler class method)": [[0, "tequila_code.circuit.compiler.CircuitCompiler.standard_gate_set", false]], "step() (tequila_code.optimizers.optimizer_gd.optimizergd method)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.step", false]], "step_lookup (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.step_lookup", false]], "sub_lists() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.sub_lists", false]], "sub_str() (tequila_code.quantumchemistry.chemistry_tools.nbodytensor method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.sub_str", false]], "supports_ucc (tequila_code.quantumchemistry.encodings.encodingbase property)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.supports_ucc", false]], "supports_ucc() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.supports_ucc", false]], "swap() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.SWAP", false]], "t() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.T", false]], "taperedbravykitaev (class in tequila_code.quantumchemistry.encodings)": [[6, "tequila_code.quantumchemistry.encodings.TaperedBravyKitaev", false]], "tequila_code.circuit": [[0, "module-tequila_code.circuit", false]], "tequila_code.circuit.circuit": [[0, "module-tequila_code.circuit.circuit", false]], "tequila_code.circuit.compiler": [[0, "module-tequila_code.circuit.compiler", false]], "tequila_code.circuit.gates": [[0, "module-tequila_code.circuit.gates", false]], "tequila_code.circuit.gradient": [[0, "module-tequila_code.circuit.gradient", false]], "tequila_code.circuit.noise": [[0, "module-tequila_code.circuit.noise", false]], "tequila_code.circuit.pyzx": [[0, "module-tequila_code.circuit.pyzx", false]], "tequila_code.circuit.qasm": [[0, "module-tequila_code.circuit.qasm", false]], "tequila_code.circuit.qpic": [[0, "module-tequila_code.circuit.qpic", false]], "tequila_code.hamiltonian": [[2, "module-tequila_code.hamiltonian", false]], "tequila_code.hamiltonian.paulis": [[2, "module-tequila_code.hamiltonian.paulis", false]], "tequila_code.hamiltonian.paulistring": [[2, "module-tequila_code.hamiltonian.paulistring", false]], "tequila_code.optimizers": [[5, "module-tequila_code.optimizers", false]], "tequila_code.optimizers.optimizer_base": [[5, "module-tequila_code.optimizers.optimizer_base", false]], "tequila_code.optimizers.optimizer_gd": [[5, "module-tequila_code.optimizers.optimizer_gd", false]], "tequila_code.optimizers.optimizer_scipy": [[5, "module-tequila_code.optimizers.optimizer_scipy", false]], "tequila_code.quantumchemistry": [[6, "module-tequila_code.quantumchemistry", false]], "tequila_code.quantumchemistry.chemistry_tools": [[6, "module-tequila_code.quantumchemistry.chemistry_tools", false]], "tequila_code.quantumchemistry.encodings": [[6, "module-tequila_code.quantumchemistry.encodings", false]], "tequila_code.quantumchemistry.madness_interface": [[6, "module-tequila_code.quantumchemistry.madness_interface", false]], "tequila_code.quantumchemistry.orbital_optimizer": [[6, "module-tequila_code.quantumchemistry.orbital_optimizer", false]], "tequila_code.quantumchemistry.psi4_interface": [[6, "module-tequila_code.quantumchemistry.psi4_interface", false]], "tequila_code.quantumchemistry.pyscf_interface": [[6, "module-tequila_code.quantumchemistry.pyscf_interface", false]], "tequila_code.quantumchemistry.qc_base": [[6, "module-tequila_code.quantumchemistry.qc_base", false]], "tequila_code.simulators": [[7, "module-tequila_code.simulators", false]], "tequila_code.simulators.simulator_api": [[7, "module-tequila_code.simulators.simulator_api", false]], "tequila_code.simulators.simulator_base": [[7, "module-tequila_code.simulators.simulator_base", false]], "tequila_code.simulators.simulator_qulacs": [[7, "module-tequila_code.simulators.simulator_qulacs", false]], "tequila_code.simulators.simulator_qulacs_gpu": [[7, "module-tequila_code.simulators.simulator_qulacs_gpu", false]], "tequila_code.simulators.simulator_symbolic": [[7, "module-tequila_code.simulators.simulator_symbolic", false]], "tequilacompilerexception": [[0, "tequila_code.circuit.compiler.TequilaCompilerException", false]], "tequilamadnessexception": [[6, "tequila_code.quantumchemistry.madness_interface.TequilaMadnessException", false]], "tequilaoptimizerexception": [[5, "tequila_code.optimizers.optimizer_base.TequilaOptimizerException", false]], "tequilapsi4exception": [[6, "tequila_code.quantumchemistry.psi4_interface.TequilaPsi4Exception", false]], "tequilaqulacsexception": [[7, "tequila_code.simulators.simulator_qulacs.TequilaQulacsException", false]], "tequilaqulacsgpuexception": [[7, "tequila_code.simulators.simulator_qulacs_gpu.TequilaQulacsGpuException", false]], "tequilascipyexception": [[5, "tequila_code.optimizers.optimizer_scipy.TequilaScipyException", false]], "tia (tequila_code.quantumchemistry.chemistry_tools.amplitudes attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes.tIA", false], [6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes.tia", false]], "tia (tequila_code.quantumchemistry.chemistry_tools.closedshellamplitudes attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ClosedShellAmplitudes.tIA", false]], "tijab (tequila_code.quantumchemistry.chemistry_tools.amplitudes attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes.tIJAB", false], [6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes.tIjAb", false], [6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes.tiJaB", false], [6, "tequila_code.quantumchemistry.chemistry_tools.Amplitudes.tijab", false]], "tijab (tequila_code.quantumchemistry.chemistry_tools.closedshellamplitudes attribute)": [[6, "tequila_code.quantumchemistry.chemistry_tools.ClosedShellAmplitudes.tIjAb", false]], "to_networkx() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.to_networkx", false]], "toffoli() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Toffoli", false]], "tol (tequila_code.optimizers.optimizer_gd.optimizergd attribute)": [[5, "tequila_code.optimizers.optimizer_gd.OptimizerGD.tol", false]], "tol (tequila_code.optimizers.optimizer_scipy.optimizerscipy attribute)": [[5, "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy.tol", false]], "transform_orbitals() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.transform_orbitals", false]], "transform_orbitals() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.transform_orbitals", false]], "transform_to_native_orbitals() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.transform_to_native_orbitals", false]], "trotterized() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Trotterized", false]], "two_body_integrals (tequila_code.quantumchemistry.chemistry_tools.integralmanager property)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.two_body_integrals", false]], "two_body_integrals (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.two_body_integrals", false]], "u (tequila_code.simulators.simulator_base.backendexpectationvalue attribute)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.U", false]], "u (tequila_code.simulators.simulator_base.backendexpectationvalue property)": [[7, "id7", false]], "u() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.U", false]], "u1() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.u1", false]], "u2() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.u2", false]], "u3() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.u3", false]], "uc() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.UC", false]], "up() (tequila_code.quantumchemistry.encodings.encodingbase method)": [[6, "tequila_code.quantumchemistry.encodings.EncodingBase.up", false]], "update() (tequila_code.optimizers.optimizer_gd.diis method)": [[5, "tequila_code.optimizers.optimizer_gd.DIIS.update", false]], "update_variables() (tequila_code.simulators.simulator_base.backendcircuit method)": [[7, "tequila_code.simulators.simulator_base.BackendCircuit.update_variables", false]], "update_variables() (tequila_code.simulators.simulator_base.backendexpectationvalue method)": [[7, "id11", false], [7, "tequila_code.simulators.simulator_base.BackendExpectationValue.update_variables", false]], "update_variables() (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs method)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.update_variables", false]], "update_variables() (tequila_code.simulators.simulator_symbolic.backendcircuitsymbolic method)": [[7, "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic.update_variables", false]], "ur() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.UR", false]], "use_mapping (tequila_code.simulators.simulator_base.backendexpectationvalue attribute)": [[7, "tequila_code.simulators.simulator_base.BackendExpectationValue.use_mapping", false]], "use_mapping (tequila_code.simulators.simulator_qulacs.backendexpectationvaluequlacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendExpectationValueQulacs.use_mapping", false]], "use_native_orbitals() (tequila_code.quantumchemistry.qc_base.quantumchemistrybase method)": [[6, "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase.use_native_orbitals", false]], "variables (tequila_code.optimizers.optimizer_base.optimizerresults attribute)": [[5, "tequila_code.optimizers.optimizer_base.OptimizerResults.variables", false]], "variables (tequila_code.quantumchemistry.psi4_interface.psi4results attribute)": [[6, "tequila_code.quantumchemistry.psi4_interface.Psi4Results.variables", false]], "variables (tequila_code.simulators.simulator_qulacs.backendcircuitqulacs attribute)": [[7, "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs.variables", false]], "verify() (tequila_code.circuit.circuit.qcircuit method)": [[0, "tequila_code.circuit.circuit.QCircuit.verify", false]], "verify_orbital_coefficients() (tequila_code.quantumchemistry.chemistry_tools.integralmanager method)": [[6, "tequila_code.quantumchemistry.chemistry_tools.IntegralManager.verify_orbital_coefficients", false]], "vqe_solver (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.vqe_solver", false]], "vqe_solver_arguments (tequila_code.quantumchemistry.orbital_optimizer.pyscfvqewrapper attribute)": [[6, "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper.vqe_solver_arguments", false]], "wfn (tequila_code.quantumchemistry.psi4_interface.psi4results attribute)": [[6, "tequila_code.quantumchemistry.psi4_interface.Psi4Results.wfn", false]], "with_gate() (tequila_code.circuit.circuit.moment method)": [[0, "tequila_code.circuit.circuit.Moment.with_gate", false]], "with_gates() (tequila_code.circuit.circuit.moment method)": [[0, "tequila_code.circuit.circuit.Moment.with_gates", false]], "without_noise_on_level() (tequila_code.circuit.noise.noisemodel method)": [[0, "tequila_code.circuit.noise.NoiseModel.without_noise_on_level", false]], "without_noise_op() (tequila_code.circuit.noise.noisemodel method)": [[0, "tequila_code.circuit.noise.NoiseModel.without_noise_op", false]], "wrap_gate() (tequila_code.circuit.circuit.moment static method)": [[0, "tequila_code.circuit.circuit.Moment.wrap_gate", false]], "wrap_gate() (tequila_code.circuit.circuit.qcircuit static method)": [[0, "tequila_code.circuit.circuit.QCircuit.wrap_gate", false]], "wrap_noise() (tequila_code.circuit.noise.noisemodel static method)": [[0, "tequila_code.circuit.noise.NoiseModel.wrap_noise", false]], "write_madness_input() (tequila_code.quantumchemistry.madness_interface.quantumchemistrymadness method)": [[6, "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness.write_madness_input", false]], "x() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.X", false]], "x() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.X", false]], "y() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Y", false]], "y() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.Y", false]], "z() (in module tequila_code.circuit.gates)": [[0, "tequila_code.circuit.gates.Z", false]], "z() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.Z", false]], "zero() (in module tequila_code.hamiltonian.paulis)": [[2, "tequila_code.hamiltonian.paulis.Zero", false]]}, "objects": {"tequila_code": [[0, 0, 0, "-", "circuit"], [2, 0, 0, "-", "hamiltonian"], [5, 0, 0, "-", "optimizers"], [6, 0, 0, "-", "quantumchemistry"], [7, 0, 0, "-", "simulators"]], "tequila_code.circuit": [[0, 0, 0, "-", "circuit"], [0, 4, 1, "", "compile_circuit"], [0, 0, 0, "-", "compiler"], [0, 0, 0, "-", "gates"], [0, 0, 0, "-", "gradient"], [0, 0, 0, "-", "noise"], [0, 0, 0, "-", "pyzx"], [0, 0, 0, "-", "qasm"], [0, 0, 0, "-", "qpic"]], "tequila_code.circuit.circuit": [[0, 1, 1, "", "Moment"], [0, 1, 1, "", "QCircuit"], [0, 4, 1, "", "find_unused_qubit"]], "tequila_code.circuit.circuit.Moment": [[0, 2, 1, "", "add_gate"], [0, 2, 1, "", "as_circuit"], [0, 3, 1, "", "canonical_depth"], [0, 3, 1, "", "canonical_moments"], [0, 3, 1, "", "depth"], [0, 2, 1, "", "from_moments"], [0, 2, 1, "", "fully_parametrized"], [0, 3, 1, "", "moments"], [0, 2, 1, "", "replace_gate"], [0, 2, 1, "", "with_gate"], [0, 2, 1, "", "with_gates"], [0, 2, 1, "", "wrap_gate"]], "tequila_code.circuit.circuit.QCircuit": [[0, 2, 1, "", "add_controls"], [0, 3, 1, "id0", "canonical_depth"], [0, 3, 1, "id1", "canonical_moments"], [0, 2, 1, "", "dagger"], [0, 3, 1, "id2", "depth"], [0, 2, 1, "", "export_to"], [0, 2, 1, "", "extract_variables"], [0, 2, 1, "", "from_moments"], [0, 3, 1, "id3", "gates"], [0, 2, 1, "", "insert_gates"], [0, 2, 1, "", "is_fully_parametrized"], [0, 2, 1, "", "is_fully_unparametrized"], [0, 2, 1, "", "is_mixed"], [0, 2, 1, "", "is_primitive"], [0, 2, 1, "", "make_parameter_map"], [0, 2, 1, "", "map_qubits"], [0, 2, 1, "", "map_variables"], [0, 2, 1, "", "max_qubit"], [0, 3, 1, "id4", "moments"], [0, 3, 1, "id5", "n_qubits"], [0, 3, 1, "id6", "numbering"], [0, 3, 1, "id7", "qubits"], [0, 2, 1, "", "replace_gates"], [0, 2, 1, "", "sort_gates"], [0, 2, 1, "", "to_networkx"], [0, 2, 1, "", "verify"], [0, 2, 1, "", "wrap_gate"]], "tequila_code.circuit.compiler": [[0, 1, 1, "", "CircuitCompiler"], [0, 5, 1, "", "TequilaCompilerException"], [0, 4, 1, "", "change_basis"], [0, 4, 1, "", "compile_ch"], [0, 4, 1, "", "compile_controlled_phase"], [0, 4, 1, "", "compile_controlled_power"], [0, 4, 1, "", "compile_controlled_rotation"], [0, 4, 1, "", "compile_exponential_pauli_gate"], [0, 4, 1, "", "compile_generalized_rotation_gate"], [0, 4, 1, "", "compile_multitarget"], [0, 4, 1, "", "compile_phase"], [0, 4, 1, "", "compile_phase_to_z"], [0, 4, 1, "", "compile_power_base"], [0, 4, 1, "", "compile_power_gate"], [0, 4, 1, "", "compile_ry"], [0, 4, 1, "", "compile_swap"], [0, 4, 1, "", "compile_to_single_control"], [0, 4, 1, "", "compile_toffoli"], [0, 4, 1, "", "compile_trotterized_gate"], [0, 4, 1, "", "compile_y"], [0, 4, 1, "", "compiler"], [0, 4, 1, "", "do_compile_trotterized_gate"]], "tequila_code.circuit.compiler.CircuitCompiler": [[0, 2, 1, "", "all_flags_true"], [0, 2, 1, "", "compile_circuit"], [0, 2, 1, "id8", "compile_objective"], [0, 2, 1, "id9", "compile_objective_argument"], [0, 2, 1, "", "standard_gate_set"]], "tequila_code.circuit.gates": [[0, 4, 1, "", "CNOT"], [0, 4, 1, "", "CRx"], [0, 4, 1, "", "CRy"], [0, 4, 1, "", "CRz"], [0, 4, 1, "", "CX"], [0, 4, 1, "", "CY"], [0, 4, 1, "", "CZ"], [0, 4, 1, "", "ExpPauli"], [0, 4, 1, "", "GenRot"], [0, 4, 1, "", "GeneralizedRotation"], [0, 4, 1, "", "Givens"], [0, 4, 1, "", "H"], [0, 4, 1, "", "PauliGate"], [0, 4, 1, "", "Phase"], [0, 4, 1, "", "PowerGate"], [0, 4, 1, "", "QGate"], [0, 4, 1, "", "QubitExcitation"], [0, 1, 1, "", "QubitExcitationImpl"], [0, 4, 1, "", "RotationGate"], [0, 4, 1, "", "Rp"], [0, 4, 1, "", "Rx"], [0, 4, 1, "", "Ry"], [0, 4, 1, "", "Rz"], [0, 4, 1, "", "S"], [0, 4, 1, "", "SWAP"], [0, 4, 1, "", "T"], [0, 4, 1, "", "Toffoli"], [0, 4, 1, "", "Trotterized"], [0, 4, 1, "", "U"], [0, 4, 1, "", "X"], [0, 4, 1, "", "Y"], [0, 4, 1, "", "Z"], [0, 4, 1, "", "iSWAP"], [0, 4, 1, "", "u1"], [0, 4, 1, "", "u2"], [0, 4, 1, "", "u3"]], "tequila_code.circuit.gates.QubitExcitationImpl": [[0, 2, 1, "", "compile"], [0, 2, 1, "", "map_qubits"]], "tequila_code.circuit.gradient": [[0, 4, 1, "", "grad"]], "tequila_code.circuit.noise": [[0, 4, 1, "", "AmplitudeDamp"], [0, 4, 1, "", "BitFlip"], [0, 4, 1, "", "DepolarizingError"], [0, 1, 1, "", "NoiseModel"], [0, 4, 1, "", "PhaseAmplitudeDamp"], [0, 4, 1, "", "PhaseDamp"], [0, 4, 1, "", "PhaseFlip"], [0, 1, 1, "", "QuantumNoise"]], "tequila_code.circuit.noise.NoiseModel": [[0, 6, 1, "", "noises"], [0, 2, 1, "", "without_noise_on_level"], [0, 2, 1, "", "without_noise_op"], [0, 2, 1, "", "wrap_noise"]], "tequila_code.circuit.noise.QuantumNoise": [[0, 2, 1, "", "from_dict"], [0, 3, 1, "id10", "level"], [0, 3, 1, "id11", "name"], [0, 6, 1, "", "prob_length"], [0, 6, 1, "", "probs"]], "tequila_code.circuit.pyzx": [[0, 4, 1, "", "convert_from_pyzx"], [0, 4, 1, "", "convert_to_pyzx"]], "tequila_code.circuit.qasm": [[0, 4, 1, "", "apply_custom_gate"], [0, 4, 1, "", "convert_to_open_qasm_2"], [0, 4, 1, "", "export_open_qasm"], [0, 4, 1, "", "get_angle"], [0, 4, 1, "", "get_qregister"], [0, 4, 1, "", "import_open_qasm"], [0, 4, 1, "", "import_open_qasm_from_file"], [0, 4, 1, "", "name_and_params"], [0, 4, 1, "", "parse_command"], [0, 4, 1, "", "parse_custom_gate"], [0, 4, 1, "", "parse_from_open_qasm_2"]], "tequila_code.circuit.qpic": [[0, 4, 1, "", "assign_name"], [0, 4, 1, "", "export_to"], [0, 4, 1, "", "export_to_qpic"]], "tequila_code.hamiltonian": [[2, 0, 0, "-", "paulis"], [2, 0, 0, "-", "paulistring"]], "tequila_code.hamiltonian.paulis": [[2, 4, 1, "", "I"], [2, 4, 1, "", "KetBra"], [2, 4, 1, "", "Projector"], [2, 4, 1, "", "Qm"], [2, 4, 1, "", "Qp"], [2, 4, 1, "", "Sm"], [2, 4, 1, "", "Sp"], [2, 4, 1, "", "X"], [2, 4, 1, "", "Y"], [2, 4, 1, "", "Z"], [2, 4, 1, "", "Zero"], [2, 4, 1, "", "decompose_transfer_operator"], [2, 4, 1, "", "from_string"], [2, 4, 1, "", "pauli"]], "tequila_code.optimizers": [[5, 4, 1, "", "minimize"], [5, 0, 0, "-", "optimizer_base"], [5, 0, 0, "-", "optimizer_gd"], [5, 0, 0, "-", "optimizer_scipy"], [5, 4, 1, "", "show_available_optimizers"]], "tequila_code.optimizers.optimizer_base": [[5, 1, 1, "", "Optimizer"], [5, 1, 1, "", "OptimizerHistory"], [5, 1, 1, "", "OptimizerResults"], [5, 5, 1, "", "TequilaOptimizerException"]], "tequila_code.optimizers.optimizer_base.Optimizer": [[5, 6, 1, "", "backend"], [5, 2, 1, "", "compile_gradient"], [5, 2, 1, "", "compile_hessian"], [5, 2, 1, "", "compile_objective"], [5, 6, 1, "", "device"], [5, 6, 1, "", "history"], [5, 2, 1, "", "initialize_variables"], [5, 6, 1, "", "maxiter"], [5, 6, 1, "", "noise"], [5, 6, 1, "", "print_level"], [5, 2, 1, "", "reset_history"], [5, 6, 1, "", "samples"], [5, 6, 1, "", "save_history"], [5, 6, 1, "", "silent"]], "tequila_code.optimizers.optimizer_base.OptimizerHistory": [[5, 6, 1, "", "angles"], [5, 6, 1, "", "angles_calls"], [5, 6, 1, "", "energies"], [5, 3, 1, "", "energies_calls"], [5, 3, 1, "", "energies_evaluations"], [5, 6, 1, "", "energy_calls"], [5, 2, 1, "", "extract_angles"], [5, 2, 1, "", "extract_energies"], [5, 2, 1, "", "extract_gradients"], [5, 6, 1, "", "gradient_calls"], [5, 6, 1, "", "gradients"], [5, 3, 1, "", "iterations"], [5, 2, 1, "", "plot"]], "tequila_code.optimizers.optimizer_base.OptimizerResults": [[5, 3, 1, "", "angles"], [5, 6, 1, "", "energy"], [5, 6, 1, "", "history"], [5, 6, 1, "", "variables"]], "tequila_code.optimizers.optimizer_gd": [[5, 1, 1, "", "DIIS"], [5, 1, 1, "", "GDResults"], [5, 1, 1, "", "OptimizerGD"], [5, 4, 1, "", "minimize"]], "tequila_code.optimizers.optimizer_gd.DIIS": [[5, 2, 1, "", "do_diis"], [5, 2, 1, "", "drop_error"], [5, 2, 1, "", "drop_first"], [5, 2, 1, "", "push"], [5, 2, 1, "", "reset"], [5, 2, 1, "", "update"]], "tequila_code.optimizers.optimizer_gd.GDResults": [[5, 6, 1, "", "moments"], [5, 6, 1, "", "num_iteration"]], "tequila_code.optimizers.optimizer_gd.OptimizerGD": [[5, 6, 1, "", "active_key_lookup"], [5, 6, 1, "", "alpha"], [5, 2, 1, "", "available_diis"], [5, 2, 1, "", "available_methods"], [5, 6, 1, "", "beta"], [5, 6, 1, "", "c"], [5, 6, 1, "", "calibrate_lr"], [5, 6, 1, "", "diis"], [5, 6, 1, "", "epsilon"], [5, 6, 1, "", "f"], [5, 6, 1, "", "gamma"], [5, 6, 1, "", "gradient_lookup"], [5, 6, 1, "", "iteration"], [5, 6, 1, "", "lr"], [5, 6, 1, "", "moments_lookup"], [5, 6, 1, "", "moments_trajectory"], [5, 2, 1, "", "nextLearningRate"], [5, 2, 1, "", "prepare"], [5, 2, 1, "", "reset_momenta"], [5, 2, 1, "", "reset_momenta_for"], [5, 2, 1, "", "reset_stepper"], [5, 6, 1, "", "rho"], [5, 2, 1, "", "step"], [5, 6, 1, "", "step_lookup"], [5, 6, 1, "", "tol"]], "tequila_code.optimizers.optimizer_scipy": [[5, 1, 1, "", "OptimizerSciPy"], [5, 1, 1, "", "SciPyResults"], [5, 5, 1, "", "TequilaScipyException"], [5, 4, 1, "", "available_methods"], [5, 4, 1, "", "minimize"]], "tequila_code.optimizers.optimizer_scipy.OptimizerSciPy": [[5, 2, 1, "", "available_methods"], [5, 6, 1, "", "gradient_based_methods"], [5, 6, 1, "", "gradient_free_methods"], [5, 6, 1, "", "hessian_based_methods"], [5, 6, 1, "", "method"], [5, 6, 1, "", "method_bounds"], [5, 6, 1, "", "method_constraints"], [5, 6, 1, "", "method_options"], [5, 6, 1, "", "silent"], [5, 6, 1, "", "tol"]], "tequila_code.optimizers.optimizer_scipy.SciPyResults": [[5, 6, 1, "", "scipy_result"]], "tequila_code.quantumchemistry": [[6, 4, 1, "", "Molecule"], [6, 4, 1, "", "MoleculeFromOpenFermion"], [6, 4, 1, "", "MoleculeFromTequila"], [6, 0, 0, "-", "chemistry_tools"], [6, 0, 0, "-", "encodings"], [6, 0, 0, "-", "madness_interface"], [6, 0, 0, "-", "orbital_optimizer"], [6, 0, 0, "-", "psi4_interface"], [6, 0, 0, "-", "pyscf_interface"], [6, 0, 0, "-", "qc_base"], [6, 4, 1, "", "show_available_modules"], [6, 4, 1, "", "show_supported_modules"]], "tequila_code.quantumchemistry.chemistry_tools": [[6, 1, 1, "", "ActiveSpaceData"], [6, 1, 1, "", "Amplitudes"], [6, 1, 1, "", "ClosedShellAmplitudes"], [6, 1, 1, "", "FermionicGateImpl"], [6, 1, 1, "", "IntegralManager"], [6, 1, 1, "", "NBodyTensor"], [6, 1, 1, "", "OrbitalData"], [6, 1, 1, "", "ParametersQC"], [6, 4, 1, "", "prepare_product_state"]], "tequila_code.quantumchemistry.chemistry_tools.ActiveSpaceData": [[6, 6, 1, "", "active_orbitals"], [6, 3, 1, "", "active_reference_orbitals"], [6, 3, 1, "", "frozen_reference_orbitals"], [6, 6, 1, "", "reference_orbitals"]], "tequila_code.quantumchemistry.chemistry_tools.Amplitudes": [[6, 2, 1, "", "from_closed_shell"], [6, 2, 1, "", "make_parameter_dictionary"], [6, 6, 1, "", "tIA"], [6, 6, 1, "", "tIJAB"], [6, 6, 1, "", "tIjAb"], [6, 6, 1, "", "tiJaB"], [6, 6, 1, "", "tia"], [6, 6, 1, "", "tijab"]], "tequila_code.quantumchemistry.chemistry_tools.ClosedShellAmplitudes": [[6, 2, 1, "", "make_parameter_dictionary"], [6, 6, 1, "", "tIA"], [6, 6, 1, "", "tIjAb"]], "tequila_code.quantumchemistry.chemistry_tools.FermionicGateImpl": [[6, 2, 1, "", "cCRy"], [6, 2, 1, "", "compile"], [6, 2, 1, "", "fermionic_excitation"], [6, 2, 1, "", "format_excitation_indices"], [6, 2, 1, "", "format_excitation_variables"], [6, 2, 1, "", "is_convertable_to_qubit_excitation"]], "tequila_code.quantumchemistry.chemistry_tools.IntegralManager": [[6, 3, 1, "", "active_orbitals"], [6, 3, 1, "", "active_reference_orbitals"], [6, 3, 1, "", "active_space"], [6, 2, 1, "", "active_space_is_trivial"], [6, 2, 1, "", "basis_is_orthogonal"], [6, 3, 1, "", "constant_term"], [6, 2, 1, "", "get_integrals"], [6, 2, 1, "", "get_orthonormalized_orbital_coefficients"], [6, 2, 1, "", "is_unitary"], [6, 3, 1, "", "one_body_integrals"], [6, 3, 1, "", "orbital_coefficients"], [6, 3, 1, "", "orbitals"], [6, 3, 1, "", "overlap_integrals"], [6, 2, 1, "", "print_basis_info"], [6, 3, 1, "", "reference_orbitals"], [6, 2, 1, "", "transform_orbitals"], [6, 2, 1, "", "transform_to_native_orbitals"], [6, 3, 1, "", "two_body_integrals"], [6, 2, 1, "", "verify_orbital_coefficients"]], "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor": [[6, 1, 1, "", "Ordering"], [6, 2, 1, "", "identify_ordering"], [6, 2, 1, "", "reorder"], [6, 2, 1, "", "set_index_lists"], [6, 3, 1, "", "shape"], [6, 2, 1, "", "sub_lists"], [6, 2, 1, "", "sub_str"]], "tequila_code.quantumchemistry.chemistry_tools.NBodyTensor.Ordering": [[6, 2, 1, "", "assign_scheme"], [6, 2, 1, "", "is_chem"], [6, 2, 1, "", "is_of"], [6, 2, 1, "", "is_phys"]], "tequila_code.quantumchemistry.chemistry_tools.OrbitalData": [[6, 6, 1, "", "energy"], [6, 6, 1, "", "idx"], [6, 6, 1, "", "idx_irrep"], [6, 6, 1, "", "idx_total"], [6, 6, 1, "", "irrep"], [6, 6, 1, "", "occ"], [6, 6, 1, "", "pair"]], "tequila_code.quantumchemistry.chemistry_tools.ParametersQC": [[6, 6, 1, "", "basis_set"], [6, 6, 1, "", "charge"], [6, 2, 1, "", "convert_to_list"], [6, 6, 1, "", "description"], [6, 3, 1, "", "filename"], [6, 2, 1, "", "format_element_name"], [6, 6, 1, "", "frozen_core"], [6, 6, 1, "", "geometry"], [6, 2, 1, "", "get_atom_number"], [6, 2, 1, "", "get_atoms"], [6, 2, 1, "", "get_geometry"], [6, 2, 1, "", "get_geometry_string"], [6, 2, 1, "", "get_nuc_charge"], [6, 2, 1, "", "get_number_of_core_electrons"], [6, 3, 1, "", "molecular_data_param"], [6, 6, 1, "", "multiplicity"], [6, 3, 1, "", "n_electrons"], [6, 6, 1, "", "name"], [6, 2, 1, "", "read_xyz_from_file"]], "tequila_code.quantumchemistry.encodings": [[6, 1, 1, "", "BravyiKitaev"], [6, 1, 1, "", "BravyiKitaevFast"], [6, 1, 1, "", "BravyiKitaevTree"], [6, 1, 1, "", "EncodingBase"], [6, 1, 1, "", "JordanWigner"], [6, 1, 1, "", "TaperedBravyKitaev"], [6, 4, 1, "", "known_encodings"]], "tequila_code.quantumchemistry.encodings.BravyiKitaev": [[6, 2, 1, "", "bk_to_me"], [6, 2, 1, "", "do_transform"], [6, 2, 1, "", "jw_to_me"], [6, 2, 1, "", "me_to_bk"], [6, 2, 1, "", "me_to_jw"]], "tequila_code.quantumchemistry.encodings.BravyiKitaevFast": [[6, 2, 1, "", "do_transform"], [6, 2, 1, "", "me_to_jw"]], "tequila_code.quantumchemistry.encodings.BravyiKitaevTree": [[6, 2, 1, "", "do_transform"], [6, 2, 1, "", "me_to_jw"]], "tequila_code.quantumchemistry.encodings.EncodingBase": [[6, 2, 1, "", "bk_to_me"], [6, 2, 1, "", "do_transform"], [6, 2, 1, "", "down"], [6, 2, 1, "", "hcb_to_me"], [6, 2, 1, "", "jw_to_me"], [6, 2, 1, "", "map_state"], [6, 2, 1, "", "me_to_bk"], [6, 2, 1, "", "me_to_jw"], [6, 3, 1, "", "name"], [6, 2, 1, "", "post_processing"], [6, 3, 1, "", "supports_ucc"], [6, 2, 1, "", "up"]], "tequila_code.quantumchemistry.encodings.JordanWigner": [[6, 2, 1, "", "do_transform"], [6, 2, 1, "", "hcb_to_me"], [6, 2, 1, "", "jw_to_me"], [6, 2, 1, "", "map_state"], [6, 2, 1, "", "me_to_jw"]], "tequila_code.quantumchemistry.encodings.TaperedBravyKitaev": [[6, 2, 1, "", "do_transform"], [6, 2, 1, "", "map_state"], [6, 2, 1, "", "me_to_jw"]], "tequila_code.quantumchemistry.madness_interface": [[6, 1, 1, "", "QuantumChemistryMadness"], [6, 5, 1, "", "TequilaMadnessException"]], "tequila_code.quantumchemistry.madness_interface.QuantumChemistryMadness": [[6, 2, 1, "", "cleanup"], [6, 2, 1, "", "compute_energy"], [6, 2, 1, "", "convert_madness_output_from_bin_to_npy"], [6, 2, 1, "", "find_executable"], [6, 2, 1, "", "get_pair_orbitals"], [6, 2, 1, "", "get_virtual_orbitals"], [6, 2, 1, "", "local_qubit_map"], [6, 2, 1, "", "make_hardcore_boson_pno_upccd_ansatz"], [6, 2, 1, "", "make_pno_upccgsd_ansatz"], [6, 2, 1, "", "make_spa_ansatz"], [6, 2, 1, "", "make_upccgsd_ansatz"], [6, 2, 1, "", "make_upccgsd_indices"], [6, 2, 1, "", "perturbative_f12_correction"], [6, 2, 1, "", "plot2cube"], [6, 2, 1, "", "read_tensors"], [6, 2, 1, "", "run_madness"], [6, 2, 1, "", "write_madness_input"]], "tequila_code.quantumchemistry.orbital_optimizer": [[6, 1, 1, "", "OptimizeOrbitalsResult"], [6, 1, 1, "", "PySCFVQEWrapper"], [6, 4, 1, "", "optimize_orbitals"]], "tequila_code.quantumchemistry.orbital_optimizer.OptimizeOrbitalsResult": [[6, 6, 1, "", "energy"], [6, 6, 1, "", "iterations"], [6, 6, 1, "", "mcscf_local_data"], [6, 6, 1, "", "mcscf_object"], [6, 6, 1, "", "mo_coeff"], [6, 6, 1, "", "molecule"], [6, 6, 1, "", "old_molecule"]], "tequila_code.quantumchemistry.orbital_optimizer.PySCFVQEWrapper": [[6, 6, 1, "", "circuit"], [6, 6, 1, "", "const_part"], [6, 6, 1, "", "history"], [6, 2, 1, "", "kernel"], [6, 2, 1, "", "make_rdm12"], [6, 6, 1, "", "molecule_arguments"], [6, 6, 1, "", "molecule_factory"], [6, 6, 1, "", "n_electrons"], [6, 6, 1, "", "one_body_integrals"], [6, 6, 1, "", "rdm1"], [6, 6, 1, "", "rdm2"], [6, 2, 1, "", "reorder"], [6, 6, 1, "", "silent"], [6, 6, 1, "", "two_body_integrals"], [6, 6, 1, "", "vqe_solver"], [6, 6, 1, "", "vqe_solver_arguments"]], "tequila_code.quantumchemistry.psi4_interface": [[6, 5, 1, "", "OpenVQEEPySCFException"], [6, 1, 1, "", "Psi4Results"], [6, 1, 1, "", "QuantumChemistryPsi4"], [6, 5, 1, "", "TequilaPsi4Exception"]], "tequila_code.quantumchemistry.psi4_interface.Psi4Results": [[6, 6, 1, "", "filename"], [6, 6, 1, "", "mol"], [6, 6, 1, "", "variables"], [6, 6, 1, "", "wfn"]], "tequila_code.quantumchemistry.psi4_interface.QuantumChemistryPsi4": [[6, 2, 1, "", "compute_amplitudes"], [6, 2, 1, "", "compute_ccsd_amplitudes"], [6, 2, 1, "", "compute_energy"], [6, 2, 1, "", "compute_rdms"], [6, 2, 1, "", "initialize_integral_manager"], [6, 3, 1, "", "nirrep"], [6, 2, 1, "", "orbital_energies"], [6, 2, 1, "", "perturbative_f12_correction"], [6, 3, 1, "", "point_group"], [6, 3, 1, "", "rdm1"], [6, 3, 1, "", "rdm2"]], "tequila_code.quantumchemistry.pyscf_interface": [[6, 5, 1, "", "OpenVQEEPySCFException"], [6, 1, 1, "", "QuantumChemistryPySCF"]], "tequila_code.quantumchemistry.pyscf_interface.QuantumChemistryPySCF": [[6, 2, 1, "", "compute_energy"], [6, 2, 1, "", "compute_fci"]], "tequila_code.quantumchemistry.qc_base": [[6, 1, 1, "", "QuantumChemistryBase"], [6, 4, 1, "", "get_givens_decomposition"], [6, 4, 1, "", "givens_matrix"], [6, 4, 1, "", "reconstruct_matrix_from_givens"]], "tequila_code.quantumchemistry.qc_base.QuantumChemistryBase": [[6, 2, 1, "", "UC"], [6, 2, 1, "", "UR"], [6, 3, 1, "", "active_space"], [6, 2, 1, "", "compute_amplitudes"], [6, 2, 1, "", "compute_ccsd_amplitudes"], [6, 2, 1, "", "compute_cis_amplitudes"], [6, 2, 1, "", "compute_constant_part"], [6, 2, 1, "", "compute_energy"], [6, 2, 1, "", "compute_fock_matrix"], [6, 2, 1, "", "compute_mp2_amplitudes"], [6, 2, 1, "", "compute_one_body_integrals"], [6, 2, 1, "", "compute_rdms"], [6, 2, 1, "", "compute_two_body_integrals"], [6, 2, 1, "", "do_make_molecule"], [6, 2, 1, "", "format_excitation_indices"], [6, 2, 1, "", "from_openfermion"], [6, 2, 1, "", "from_tequila"], [6, 2, 1, "", "get_givens_circuit"], [6, 2, 1, "", "get_integrals"], [6, 2, 1, "", "get_pair_specific_indices"], [6, 2, 1, "", "hcb_to_me"], [6, 2, 1, "", "initialize_integral_manager"], [6, 2, 1, "", "is_canonical"], [6, 2, 1, "", "is_closed_shell"], [6, 2, 1, "", "make_annihilation_op"], [6, 2, 1, "", "make_ansatz"], [6, 2, 1, "", "make_creation_op"], [6, 2, 1, "", "make_excitation_gate"], [6, 2, 1, "", "make_excitation_generator"], [6, 2, 1, "", "make_hamiltonian"], [6, 2, 1, "", "make_hardcore_boson_excitation_gate"], [6, 2, 1, "", "make_hardcore_boson_hamiltonian"], [6, 2, 1, "", "make_hardcore_boson_upccgd_layer"], [6, 2, 1, "", "make_molecular_hamiltonian"], [6, 2, 1, "", "make_molecule"], [6, 2, 1, "", "make_number_op"], [6, 2, 1, "", "make_orbital_rotation_gate"], [6, 2, 1, "", "make_s2_op"], [6, 2, 1, "", "make_sm_op"], [6, 2, 1, "", "make_sp_op"], [6, 2, 1, "", "make_spa_ansatz"], [6, 2, 1, "", "make_sz_op"], [6, 2, 1, "", "make_uccsd_ansatz"], [6, 2, 1, "", "make_upccgsd_ansatz"], [6, 2, 1, "", "make_upccgsd_indices"], [6, 2, 1, "", "make_upccgsd_layer"], [6, 2, 1, "", "make_upccgsd_singles"], [6, 3, 1, "", "n_electrons"], [6, 3, 1, "", "n_orbitals"], [6, 2, 1, "", "n_rotation"], [6, 3, 1, "", "orbitals"], [6, 2, 1, "", "orthonormalize_basis_orbitals"], [6, 2, 1, "", "perturbative_f12_correction"], [6, 2, 1, "", "prepare_hardcore_boson_reference"], [6, 2, 1, "", "prepare_reference"], [6, 2, 1, "", "print_basis_info"], [6, 3, 1, "", "rdm1"], [6, 3, 1, "", "rdm2"], [6, 2, 1, "", "rdm_spinsum"], [6, 3, 1, "", "reference_orbitals"], [6, 2, 1, "", "supports_ucc"], [6, 2, 1, "", "transform_orbitals"], [6, 2, 1, "", "use_native_orbitals"]], "tequila_code.simulators": [[7, 0, 0, "-", "simulator_api"], [7, 0, 0, "-", "simulator_base"], [7, 0, 0, "-", "simulator_qulacs"], [7, 0, 0, "-", "simulator_qulacs_gpu"], [7, 0, 0, "-", "simulator_symbolic"]], "tequila_code.simulators.simulator_api": [[7, 1, 1, "", "BackendTypes"], [7, 4, 1, "", "compile"], [7, 4, 1, "", "compile_circuit"], [7, 4, 1, "", "compile_objective"], [7, 4, 1, "", "compile_to_function"], [7, 4, 1, "", "draw"], [7, 4, 1, "", "pick_backend"], [7, 4, 1, "", "show_available_simulators"], [7, 4, 1, "", "simulate"]], "tequila_code.simulators.simulator_api.BackendTypes": [[7, 6, 1, "", "CircType"], [7, 6, 1, "", "ExpValueType"]], "tequila_code.simulators.simulator_base": [[7, 1, 1, "", "BackendCircuit"], [7, 1, 1, "", "BackendExpectationValue"]], "tequila_code.simulators.simulator_base.BackendCircuit": [[7, 6, 1, "", "abstract_circuit"], [7, 3, 1, "", "abstract_qubits"], [7, 2, 1, "id0", "add_basic_gate"], [7, 2, 1, "id1", "add_measurement"], [7, 2, 1, "id2", "add_parametrized_gate"], [7, 2, 1, "", "check_device"], [7, 6, 1, "", "circuit"], [7, 6, 1, "id3", "compiler_arguments"], [7, 2, 1, "", "convert_measurements"], [7, 2, 1, "id4", "create_circuit"], [7, 6, 1, "", "device"], [7, 2, 1, "", "do_sample"], [7, 2, 1, "", "do_simulate"], [7, 2, 1, "", "extract_variables"], [7, 2, 1, "", "initialize_circuit"], [7, 2, 1, "", "initialize_qubit"], [7, 2, 1, "", "make_qubit_map"], [7, 3, 1, "id5", "n_qubits"], [7, 6, 1, "", "no_translation"], [7, 6, 1, "", "noise"], [7, 2, 1, "", "optimize_circuit"], [7, 2, 1, "", "qubit"], [7, 6, 1, "", "qubit_map"], [7, 6, 1, "", "qubits"], [7, 2, 1, "", "retrieve_device"], [7, 2, 1, "", "sample"], [7, 2, 1, "", "sample_all_z_hamiltonian"], [7, 2, 1, "", "sample_paulistring"], [7, 2, 1, "", "simulate"], [7, 2, 1, "", "update_variables"]], "tequila_code.simulators.simulator_base.BackendExpectationValue": [[7, 6, 1, "", "BackendCircuitType"], [7, 3, 1, "id6", "H"], [7, 3, 1, "id7", "U"], [7, 6, 1, "", "abstract_H"], [7, 2, 1, "", "count_measurements"], [7, 2, 1, "", "extract_variables"], [7, 2, 1, "id8", "initialize_hamiltonian"], [7, 2, 1, "id9", "initialize_unitary"], [7, 3, 1, "id10", "n_qubits"], [7, 2, 1, "", "reduce_hamiltonians"], [7, 2, 1, "", "sample"], [7, 2, 1, "", "sample_paulistring"], [7, 2, 1, "", "simulate"], [7, 2, 1, "id11", "update_variables"], [7, 6, 1, "", "use_mapping"]], "tequila_code.simulators.simulator_qulacs": [[7, 1, 1, "", "BackendCircuitQulacs"], [7, 1, 1, "", "BackendExpectationValueQulacs"], [7, 5, 1, "", "TequilaQulacsException"]], "tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs": [[7, 2, 1, "", "add_basic_gate"], [7, 2, 1, "", "add_exponential_pauli_gate"], [7, 2, 1, "", "add_measurement"], [7, 2, 1, "", "add_noise_to_circuit"], [7, 2, 1, "", "add_parametrized_gate"], [7, 6, 1, "", "compiler_arguments"], [7, 2, 1, "", "convert_measurements"], [7, 6, 1, "", "counter"], [7, 2, 1, "", "do_sample"], [7, 2, 1, "", "do_simulate"], [7, 6, 1, "", "has_noise"], [7, 2, 1, "", "initialize_circuit"], [7, 2, 1, "", "initialize_state"], [7, 2, 1, "", "no_translation"], [7, 6, 1, "", "noise_lookup"], [7, 6, 1, "", "numbering"], [7, 6, 1, "", "op_lookup"], [7, 2, 1, "", "optimize_circuit"], [7, 2, 1, "", "update_variables"], [7, 6, 1, "", "variables"]], "tequila_code.simulators.simulator_qulacs.BackendExpectationValueQulacs": [[7, 6, 1, "", "BackendCircuitType"], [7, 2, 1, "", "initialize_hamiltonian"], [7, 2, 1, "", "sample"], [7, 2, 1, "", "simulate"], [7, 6, 1, "", "use_mapping"]], "tequila_code.simulators.simulator_qulacs_gpu": [[7, 1, 1, "", "BackendCircuitQulacsGpu"], [7, 1, 1, "", "BackendExpectationValueQulacsGpu"], [7, 5, 1, "", "TequilaQulacsGpuException"]], "tequila_code.simulators.simulator_qulacs_gpu.BackendCircuitQulacsGpu": [[7, 2, 1, "", "initialize_state"]], "tequila_code.simulators.simulator_qulacs_gpu.BackendExpectationValueQulacsGpu": [[7, 6, 1, "", "BackendCircuitType"]], "tequila_code.simulators.simulator_symbolic": [[7, 1, 1, "", "BackendCircuitSymbolic"], [7, 1, 1, "", "BackendExpectationValueSymbolic"]], "tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic": [[7, 2, 1, "", "apply_gate"], [7, 2, 1, "", "apply_on_standard_basis"], [7, 6, 1, "", "compiler_arguments"], [7, 6, 1, "", "convert_to_numpy"], [7, 2, 1, "", "create_circuit"], [7, 2, 1, "", "do_simulate"], [7, 2, 1, "", "update_variables"]], "tequila_code.simulators.simulator_symbolic.BackendExpectationValueSymbolic": [[7, 6, 1, "", "BackendCircuitType"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "property", "Python property"], "4": ["py", "function", "Python function"], "5": ["py", "exception", "Python exception"], "6": ["py", "attribute", "Python attribute"]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:property", "4": "py:function", "5": "py:exception", "6": "py:attribute"}, "terms": {"": [0, 1, 2, 3, 4, 5, 6, 7], "0": [0, 1, 2, 5, 6, 7], "00": [2, 6], "001": 5, "01": 2, "03429v2": 0, "05": [5, 6], "05938": 0, "06": 2, "061": 6, "062612": 6, "07": [5, 6], "08": 6, "0_down": 6, "0_up": 6, "0rangl": 6, "1": [0, 2, 5, 6, 7], "10": [0, 2, 5, 6], "100": 5, "1016": 6, "102": 6, "1039": 0, "11": [2, 6], "1103": 6, "1122": 6, "12": 6, "1212": 6, "1221": 6, "12421": 6, "13": 6, "1707": 0, "190": 6, "195": 6, "1_down": 6, "1_up": 6, "1e": [2, 5, 6], "1j": 6, "2": [0, 2, 5, 6], "2004": 6, "2011": 0, "2017": 0, "22": 6, "2207": 6, "25": 6, "2n": 6, "2pi": 5, "3": [0, 2, 5, 6], "35": 6, "395": 6, "3g": 6, "4": [0, 5, 6, 7], "5": [0, 6], "5theta": 0, "6": [2, 6], "7": 5, "8": [5, 6], "9": 5, "99": 5, "999": 5, "A": [0, 1, 5, 6], "At": 1, "For": [0, 1, 5], "If": [0, 1, 5, 6, 7], "In": [1, 6, 7], "It": [5, 6], "NOT": [5, 6], "No": [5, 6], "Not": [0, 6, 7], "The": [0, 1, 2, 5, 6, 7], "To": 1, "Will": [5, 6, 7], "__call__": 5, "__init__": [1, 6, 7], "_build": 1, "_optim": 5, "_passive_indic": 6, "_r12": 6, "_rdm1": 6, "_rdm2": 6, "a1": 6, "a_": 6, "a_0": 6, "a_1": 6, "a_j": 6, "a_r": 6, "ab": [5, 6], "abcd": 6, "abil": 0, "abl": 6, "abort": 5, "about": [0, 3, 5, 6, 7], "abov": [0, 6], "absolut": 6, "abstract": [0, 5, 6, 7], "abstract_circuit": [0, 4, 7], "abstract_h": [4, 7], "abstract_hamiltonian": 7, "abstract_qubit": [4, 7], "ac": 6, "acceler": 5, "accept": 5, "access": 6, "accomplish": 5, "accord": 6, "achiev": 6, "act": [0, 2, 6, 7], "action": 7, "activ": [0, 5, 6], "active_angl": 5, "active_fermion": 6, "active_indic": 6, "active_key_lookup": [4, 5], "active_orbit": [4, 6], "active_reference_orbit": [4, 6], "active_spac": [4, 6], "active_space_is_trivi": [4, 6], "activespacedata": [4, 6], "actual": [5, 6], "ad": [0, 2, 7], "adagrad": 5, "adam": 5, "add": [0, 1, 7], "add_basic_g": [4, 7], "add_control": [0, 4], "add_exponential_pauli_g": [4, 7], "add_gat": [0, 4], "add_measur": [4, 7], "add_noise_to_circuit": [4, 7], "add_numb": 1, "add_parametrized_g": [4, 7], "add_singl": 6, "addit": [5, 6], "addition": 3, "adjoint": 0, "adjust": [0, 5], "adopt": 6, "affect": [0, 5], "after": 6, "again": 7, "al": [0, 6], "algorithm": 5, "alia": 7, "alias": 6, "all": [0, 1, 2, 5, 6, 7], "all_flags_tru": [0, 4], "allow": [0, 5, 6], "alon": 6, "alpha": [4, 5, 6], "alreadi": [6, 7], "also": [0, 1, 2, 5, 6], "alter": 5, "altern": [0, 5], "alwai": [0, 6], "always_use_gener": 0, "among": 0, "amplitud": [0, 4, 6], "amplitudedamp": [0, 4], "an": [0, 2, 5, 6, 7], "analogi": 0, "analyt": 5, "angl": [0, 4, 5, 6], "angle_transform": 6, "angles_cal": [4, 5], "angstrom": 6, "ani": [0, 5, 6], "annihil": 6, "anoth": [5, 6], "ansatz": 6, "anyth": 7, "ap": 6, "api": 4, "app": 6, "appear": 7, "append": 6, "appli": [0, 5, 6, 7], "applic": [0, 7], "apply_custom_g": [0, 4], "apply_g": [4, 7], "apply_on_standard_basi": [4, 7], "approach": 6, "approxim": 6, "ar": [0, 1, 2, 3, 5, 6, 7], "arg": [0, 2, 5, 6, 7], "argument": [0, 5, 6, 7], "arithmet": 1, "arrai": [2, 6, 7], "articl": 6, "arxiv": [0, 6], "as_circuit": [0, 4], "assign": [6, 7], "assign_nam": [0, 4], "assign_schem": [4, 6], "associ": 6, "assum": [0, 6], "assume_r": [0, 6], "attach": 5, "attempt": [0, 5], "attribut": [0, 1, 5, 7], "auto": [5, 6], "autodoc": 1, "autogener": 7, "automat": [1, 5, 6, 7], "autopick": 5, "avail": [3, 5, 6, 7], "available_dii": [4, 5], "available_method": [4, 5], "averag": 7, "avoid": 6, "axi": [0, 5, 6], "b": [1, 5, 6], "back": [0, 5, 6, 7], "backend": [0, 2, 4, 5, 6, 7], "backend_opt": 5, "backend_result": 7, "backendcircuit": [4, 7], "backendcircuitqulac": [4, 7], "backendcircuitqulacsgpu": [4, 7], "backendcircuitsymbol": [4, 7], "backendcircuittyp": [4, 7], "backendexpectationvalu": [4, 7], "backendexpectationvaluequlac": [4, 7], "backendexpectationvaluequlacsgpu": [4, 7], "backendexpectationvaluesymbol": [4, 7], "backendtyp": [4, 7], "barrier": 0, "base": [0, 4], "baseclass": 6, "baselin": 5, "basi": [0, 6, 7], "basic": 1, "basis_is_orthogon": [4, 6], "basis_nam": 6, "basis_set": [4, 6], "basisfunct": 7, "bd": 6, "beam": 0, "been": 5, "befor": [0, 1, 5, 6], "begin": 0, "being": [0, 5, 6, 7], "bell": 2, "below": 6, "beta": [4, 5, 6], "beta2": 5, "beta_2": 5, "between": [0, 5, 6, 7], "bfg": 5, "big": 6, "bin": 6, "bishop": 0, "bit": 0, "bitflip": [0, 4], "bitnumb": 0, "bitstr": [2, 6, 7], "bk_to_m": [4, 6], "black": 0, "blank": 5, "blob": 0, "block": 7, "bodi": 6, "bool": [0, 2, 5, 6, 7], "boolean": 5, "boson": 6, "both": [0, 5, 6], "bound": 5, "bra": 2, "bravyi": 6, "bravyi_kitaev": 6, "bravyi_kitaev_tre": 6, "bravyikitaev": [4, 6], "bravyikitaevfast": [4, 6], "bravyikitaevtre": [4, 6], "break": 0, "build": [0, 5, 7], "built": [0, 1, 7], "c": [4, 5, 6], "c_": 6, "c_ij": 6, "cab": 6, "cabs_nam": 6, "cabs_opt": 6, "cabs_typ": 6, "calcul": [1, 5, 6], "calculu": 0, "calibr": 5, "calibrate_lr": [4, 5], "call": [0, 5, 6, 7], "callabl": [5, 6, 7], "can": [0, 2, 5, 6, 7], "cannot": [1, 6], "canon": 6, "canonical_depth": [0, 4], "canonical_mo": [0, 4], "capabl": 3, "care": 2, "carrier": 0, "case": [6, 7], "casscf": 6, "cb": 6, "cc": 6, "cc2": 6, "cc3": 6, "cc_max": [0, 7], "ccry": [4, 6], "ccsd": 6, "ccwavefunct": 6, "certain": 0, "cg": 5, "ch_gate": 0, "chang": [0, 5, 6, 7], "change_basi": [0, 4], "channel": [0, 7], "charg": [4, 6], "cheaper": 0, "check": [0, 6, 7], "check_devic": [4, 7], "chemic": 6, "chemistri": [0, 3, 4], "chemistry_tool": 6, "choic": 6, "choos": [5, 7], "chose": 7, "chosen": [5, 6, 7], "chuang": 0, "ci": 6, "circtyp": [4, 7], "circuit": [3, 4, 5, 6, 7], "circuitcompil": [0, 4], "cirq": 4, "cisd": 6, "cisdt": 6, "ciwavefunct": 6, "ciwavefunt": 6, "clasic": 6, "class": [0, 1, 5, 6, 7], "classic": 6, "classmethod": [0, 5, 6, 7], "cleanup": [4, 6], "close": 6, "closedshellamplitud": [4, 6], "closest": 6, "cluster": 6, "cnot": [0, 4, 6], "co": 0, "cobyla": 5, "code": 0, "coeffici": [0, 6], "collect": 6, "column": 6, "com": [0, 6], "combin": [0, 5, 6], "come": 6, "command": [0, 6], "comment": 1, "common": 0, "comp_grad_obj": 5, "compar": 6, "compat": 6, "compil": [4, 5, 6, 7], "compile_ch": [0, 4], "compile_circuit": [0, 4, 7], "compile_controlled_phas": [0, 4], "compile_controlled_pow": [0, 4], "compile_controlled_rot": [0, 4], "compile_exponential_pauli_g": [0, 4], "compile_generalized_rotation_g": [0, 4], "compile_gradi": [4, 5], "compile_hessian": [4, 5], "compile_i": [0, 4], "compile_multitarget": [0, 4], "compile_object": [0, 4, 5, 7], "compile_objective_argu": [0, 4], "compile_opt": [0, 6], "compile_phas": [0, 4], "compile_phase_to_z": [0, 4], "compile_power_bas": [0, 4], "compile_power_g": [0, 4], "compile_ri": [0, 4], "compile_swap": [0, 4], "compile_to_funct": [4, 7], "compile_to_single_control": [0, 4], "compile_toffoli": [0, 4], "compile_trotterized_g": [0, 4], "compiler_argu": [4, 7], "complement": 6, "complet": 6, "complex": 6, "compon": 6, "composit": 6, "comprehens": 3, "comput": 6, "compute_amplitud": [4, 6], "compute_ccsd_amplitud": [4, 6], "compute_cis_amplitud": [4, 6], "compute_constant_part": [4, 6], "compute_energi": [4, 6], "compute_fci": [4, 6], "compute_fock_matrix": [4, 6], "compute_mp2_amplitud": [4, 6], "compute_one_body_integr": [4, 6], "compute_rdm": [4, 6], "compute_two_body_integr": [4, 6], "condens": 6, "conf": 1, "conflict": 0, "connect": 0, "consid": 6, "consist": [6, 7], "const_part": [4, 6], "constant": 6, "constant_term": [4, 6], "constr": 5, "construct": [0, 5, 6], "constructor": [6, 7], "contain": [0, 1, 5, 6, 7], "content": 4, "context": 6, "contigu": 6, "control": [0, 5, 6], "control_qubit": 0, "controlled_exponential_pauli": [0, 7], "controlled_phas": [0, 7], "controlled_pow": [0, 7], "controlled_rot": [0, 7], "conveni": [0, 2, 5, 6, 7], "conveniec": 6, "convent": [0, 6], "converg": 5, "convers": 6, "convert": [0, 6, 7], "convert_from_pyzx": [0, 4], "convert_madness_output_from_bin_to_npi": [4, 6], "convert_measur": [4, 7], "convert_to_list": [4, 6], "convert_to_numpi": [4, 7], "convert_to_open_qasm_2": [0, 4], "convert_to_pyzx": [0, 4], "core": 6, "correct": [0, 6], "correctli": 3, "correl": 6, "correspond": [0, 6, 7], "cost": 6, "cotton": 6, "count": 7, "count_measur": [4, 7], "counter": [4, 7], "coupl": 6, "cplett": 6, "creat": [0, 2, 6, 7], "create_circuit": [4, 7], "creation": 6, "cross": [0, 1], "crx": [0, 4], "cry": [0, 4, 6], "crz": [0, 4], "cu": 6, "cube": 6, "cubefil": 6, "current": [2, 5, 6], "custom": [0, 5, 6], "custom_circuit": 0, "custom_gates_map": 0, "cx": [0, 4], "cy": [0, 4], "cycl": 6, "cz": [0, 4], "d": [0, 6], "d0sc06627c": 0, "dagger": [0, 2, 4, 6], "dagger_": 6, "dagger_i": 6, "dagger_p": 6, "damp": 0, "data": [1, 6, 7], "dataclass": 6, "datadir": 6, "dcontrol": 6, "ddddd": 6, "debug": 7, "decid": 0, "decompos": [0, 6], "decompose_control_gener": 0, "decompose_transfer_oper": [2, 4], "decor": 0, "deduc": 6, "def": 1, "default": [0, 2, 5, 6, 7], "defin": [0, 2, 5, 6, 7], "delete_all_fil": 6, "delta": 5, "denomin": 1, "denot": 6, "densiti": 6, "depend": [0, 5, 6, 7], "depolar": 0, "depolarizingerror": [0, 4], "depth": [0, 4, 7], "deriv": [5, 6, 7], "descent": 5, "describ": [0, 1, 6], "descript": [1, 4, 6], "desir": [0, 2, 6], "detail": [3, 5, 7], "detci": 6, "detci__opdm": 6, "detci__tpdm": 6, "detect": 6, "determin": [0, 6, 7], "devic": [4, 5, 7], "diagon": 6, "dicationari": 7, "dict": [0, 5, 6, 7], "dictionari": [0, 5, 6, 7], "differ": [0, 1, 5], "differenti": [0, 5], "dii": [4, 5], "dim": 6, "dimens": 6, "dimension": 6, "dirac": 6, "direclti": 6, "direct": 1, "direct_compil": 6, "directli": [5, 6], "diretli": 2, "displai": [6, 7], "distinct": 7, "distinguish": 0, "divid": [0, 1], "divis": [1, 5], "do": [5, 6, 7], "do_compile_trotterized_g": [0, 4], "do_dii": [4, 5], "do_make_molecul": [4, 6], "do_sampl": [4, 7], "do_simul": [4, 7], "do_transform": [4, 6], "doabl": 5, "doc": 0, "document": [2, 5, 7], "doe": [0, 5, 6, 7], "dogleg": 5, "doi": [0, 6], "done": [0, 6], "doubl": 6, "down": [2, 4, 6, 7], "draw": [4, 7], "drop": [5, 6], "drop_error": [4, 5], "drop_first": [4, 5], "dure": [0, 5], "e": [0, 2, 5, 6, 7], "e_0": 0, "e_1": 0, "each": [0, 1, 3, 5, 6], "edg": [0, 6], "effect": [0, 1, 6, 7], "effici": [6, 7], "eg": 5, "eigenvalu": 0, "eigenvalues_magnitud": 0, "either": [5, 6], "electron": 6, "elem": 6, "element": [2, 5, 6], "els": [0, 5], "emploi": [5, 6, 7], "empti": [0, 7], "emul": [5, 7], "emulatedli": 7, "en": 6, "enabl": [0, 1, 6], "encod": [0, 4], "encodingbas": [4, 6], "end": [0, 6], "energi": [4, 5, 6], "energies_cal": [4, 5], "energies_evalu": [4, 5], "energy_cal": [4, 5], "ensur": 1, "entir": [0, 5, 7], "enumer": 7, "environ": 7, "epsilon": [4, 5], "eq": 6, "eqch": 6, "equa": 6, "equal": 0, "equip": 7, "equival": [0, 6], "eras": 5, "error": [5, 6], "error_vector": 5, "essenti": 6, "et": [0, 6], "etc": [0, 5, 6], "evalu": [5, 6, 7], "even": [0, 6], "everi": [0, 5], "everyth": [0, 5], "ex_level": 6, "exact": 5, "exampl": [1, 5, 6], "except": [0, 1, 5, 6, 7], "excess": 0, "excict": 6, "excit": [0, 6], "exclud": [6, 7], "exclude_symbol": 7, "execut": [6, 7], "exist": 6, "exp": [0, 6], "expect": [5, 6, 7], "expectationvalu": [0, 6, 7], "experi": 0, "explain": 1, "explicitli": 6, "expon": [0, 6], "exponenti": [0, 7], "exponential_pauli": [0, 7], "export": 0, "export_open_qasm": [0, 4], "export_to": [0, 4], "export_to_qp": [0, 4], "exppauli": [0, 4, 7], "exppauligateimpl": 7, "expvaluetyp": [4, 7], "ext": 1, "extens": 1, "external_info": 6, "extra": [5, 6], "extract": [1, 6, 7], "extract_angl": [4, 5], "extract_energi": [4, 5], "extract_gradi": [4, 5], "extract_vari": [0, 4, 7], "f": [0, 4, 5, 6], "f12": 6, "f12_filenam": 6, "f_12": 6, "facto": 5, "factor": [0, 1, 5, 6], "factori": [5, 6], "fals": [0, 2, 5, 7], "faster": [0, 7], "fci": 6, "featur": 7, "fermion": [0, 6], "fermion_oper": 6, "fermionic_excit": [4, 6], "fermionicg": 6, "fermionicgateimpl": [4, 6], "fermionoper": 6, "field": [6, 7], "file": [0, 1, 5, 6], "filenam": [0, 4, 5, 6, 7], "filepath": 0, "filetyp": [0, 6], "find": 6, "find_execut": [4, 6], "find_unused_qubit": [0, 4], "fine": 5, "first": [0, 1, 5, 6], "fix": [0, 6, 7], "flag": 6, "flip": 0, "float": [0, 1, 2, 5, 6, 7], "fock": 6, "fock_matrix": 6, "follow": [0, 1, 5, 6], "forc": 6, "form": [0, 6], "format": [0, 5, 6], "format_element_nam": [4, 6], "format_excitation_indic": [4, 6], "format_excitation_vari": [4, 6], "former": 5, "formula": [0, 5], "found": [6, 7], "four": 6, "frac": [0, 2, 6], "free": 6, "from": [0, 1, 2, 5, 6, 7], "from_closed_shel": [4, 6], "from_dict": [0, 4], "from_moment": [0, 4], "from_openfermion": [4, 6], "from_str": [2, 4], "from_tequila": [4, 6], "frozen": 6, "frozen_cor": [4, 6], "frozen_orbit": 6, "frozen_reference_orbit": [4, 6], "ful": 6, "full": [5, 6, 7], "fullfil": 0, "fully_parametr": [0, 4], "func": 1, "function": [0, 1, 3, 5, 6, 7], "fundament": 0, "further": [5, 6], "futur": 6, "g": [0, 2, 5, 6, 7], "gambetta": 0, "gamma": [4, 5, 6], "gasd": 6, "gate": [2, 4, 6, 7], "gate_custom": 0, "gatecolor1": 0, "gatecolor2": 0, "gaussian": 6, "gd": 5, "gdresult": [4, 5], "gener": [0, 1, 2, 5, 6, 7], "general_excit": 6, "generalized_rot": [0, 7], "generalizedrot": [0, 4], "generalizedrotationimpl": 0, "genrot": [0, 4], "geometr": 1, "geometri": [4, 6], "get": [0, 5, 6, 7], "get_angl": [0, 4], "get_atom": [4, 6], "get_atom_numb": [4, 6], "get_geometri": [4, 6], "get_geometry_str": [4, 6], "get_givens_circuit": [4, 6], "get_givens_decomposit": [4, 6], "get_integr": [4, 6], "get_nuc_charg": [4, 6], "get_number_of_core_electron": [4, 6], "get_orthonormalized_orbital_coeffici": [4, 6], "get_pair_orbit": [4, 6], "get_pair_specific_indic": [4, 6], "get_qregist": [0, 4], "get_rdm1": 6, "get_rdm2": 6, "get_virtual_orbit": [4, 6], "github": [0, 6], "give": [2, 5, 6, 7], "given": [0, 1, 2, 4, 5, 6, 7], "givens_matrix": [4, 6], "go": 6, "googl": 1, "got": 6, "gpu": 4, "gpyopt": 4, "grad": [0, 4], "grad_obj": 5, "gradient": [4, 6], "gradient_based_method": [4, 5], "gradient_cal": [4, 5], "gradient_free_method": [4, 5], "gradient_lookup": [4, 5], "gradient_mod": 0, "grain": 5, "graph": 0, "greedili": 0, "group_togeth": 0, "gsd": 6, "guess": 6, "guess_wfn": 6, "guid": 1, "guo": 0, "h": [0, 2, 4, 6, 7], "h1": 6, "h2": 6, "ha": [0, 5, 6, 7], "hadamard": 0, "hadamard_pow": [0, 7], "hamiltonian": [3, 4, 6, 7], "hand": 6, "handl": 6, "happen": 0, "hard": 6, "hardcor": 6, "hardcore_boson": 6, "hartre": 6, "has_nois": [4, 7], "hash": 6, "hashabl": [0, 5, 6, 7], "have": [0, 1, 5, 6, 7], "hcb": 6, "hcb_optim": 6, "hcb_to_m": [4, 6], "header": [0, 1], "hel": 6, "held": 6, "helper": [0, 6, 7], "henc": 5, "here": [1, 6, 7], "hermitian": [2, 6], "hessian": 5, "hessian_based_method": [4, 5], "hf": 6, "hf_energi": 6, "high": 6, "highest": 0, "histori": [4, 5, 6], "hold": [6, 7], "how": [1, 2, 3, 5, 6, 7], "hpq": 6, "html": [1, 6, 7], "http": [0, 6], "hyperparamet": 5, "i": [0, 1, 2, 4, 5, 6, 7], "i_0": 6, "i_1": 6, "id": 5, "ident": 6, "identifi": 7, "identify_ord": [4, 6], "idx": [4, 6], "idx_irrep": [4, 6], "idx_list": 6, "idx_tot": [4, 6], "iff": 7, "ignor": [2, 6], "illustr": 3, "imaginari": 6, "implement": 6, "impli": 6, "import": [0, 6], "import_open_qasm": [0, 4], "import_open_qasm_from_fil": [0, 4], "improv": [0, 6, 7], "includ": [0, 1, 3, 5, 6], "include_doubl": 6, "include_offdiagon": 6, "include_refer": 6, "include_reference_ansatz": 6, "include_singl": 6, "incom": 6, "ind": 6, "indepd": 6, "independ": 6, "index": [0, 6], "indic": [0, 5, 6, 7], "individu": [5, 6, 7], "info": 6, "inform": [1, 3, 5, 6, 7], "informaton": 7, "inherit": [0, 5, 7], "inheritor": [5, 7], "init": [0, 5, 6], "initi": [0, 1, 2, 5, 6, 7], "initial_amplitud": 6, "initial_guess": 6, "initial_st": 7, "initial_valu": 5, "initialize_circuit": [4, 7], "initialize_hamiltonian": [4, 7], "initialize_integral_manag": [4, 6], "initialize_qubit": [4, 7], "initialize_st": [4, 7], "initialize_unitari": [4, 7], "initialize_vari": [4, 5], "initio": 6, "inpl": 0, "inplac": 6, "input": 6, "insert": 0, "insert_g": [0, 4], "instal": [5, 6, 7], "instanc": [1, 6, 7], "instanti": 7, "instead": [6, 7], "instruct": [3, 5, 7], "int": [0, 1, 2, 5, 6, 7], "integ": [0, 2, 5, 7], "integr": [1, 5, 6, 7], "integralmanag": [4, 6], "integrals_": 6, "inter": 7, "interfac": [0, 4], "intern": [6, 7], "interpret": [0, 5], "intiti": 6, "invers": 6, "involut": 6, "irreduc": 6, "irrep": [4, 6], "irrepord": 6, "is_canon": [4, 6], "is_chem": [4, 6], "is_closed_shel": [4, 6], "is_convertable_to_qubit_excit": [4, 6], "is_fully_parametr": [0, 4], "is_fully_unparametr": [0, 4], "is_mix": [0, 4], "is_of": [4, 6], "is_phi": [4, 6], "is_primit": [0, 4], "is_unitari": [4, 6], "iswap": [0, 4], "item": 5, "iter": [4, 5, 6, 7], "its": [0, 6, 7], "itself": 5, "ivar": 1, "j": [0, 6], "jordan": 6, "jordan_wign": 6, "jordanwign": [4, 6], "jupyt": 7, "just": [0, 5, 6, 7], "jw": 6, "jw_to_m": [4, 6], "k": 6, "keep": [0, 6], "keep_mad_fil": 6, "kei": [0, 5, 6, 7], "kernel": [4, 6], "ket": 2, "ketbra": [2, 4], "keyword": [0, 5, 6, 7], "kitaev": 6, "know": 6, "known": 6, "known_encod": [4, 6], "kottmanj": 6, "krau": 0, "krauss": 0, "krylov": 5, "kwarg": [0, 2, 5, 7], "l": [0, 5, 6], "label": 6, "ladder": 6, "lambd": 0, "lambda": 0, "lamnd": 0, "langl": 2, "languag": [1, 7], "larger": [6, 7], "largest": 5, "last": 5, "latter": 5, "layer": [0, 6], "lead": 6, "learn": 5, "least": 6, "leav": 0, "lee": 6, "left": 2, "length": 1, "less": 6, "letter": 6, "level": [0, 1, 4, 6], "li": 6, "librari": [0, 3, 6], "lightweight": 1, "like": [0, 5, 6, 7], "likelihood": 0, "linear": 6, "list": [0, 2, 5, 6, 7], "literatur": 5, "lithium": 6, "loc": 6, "local": 6, "local_qubit_map": [4, 6], "loewdin": 6, "look": 6, "lookup": 5, "lower": 6, "lr": [4, 5], "lvert": 2, "m": [0, 6], "mad": 4, "made": 5, "madness_interfac": 6, "madness_root_dir": 6, "madtequila": 6, "magnitud": [0, 5], "mai": [0, 5, 6, 7], "main": 6, "mainli": 6, "make": [0, 1, 6], "make_annihilation_op": [4, 6], "make_ansatz": [4, 6], "make_creation_op": [4, 6], "make_excitation_g": [4, 6], "make_excitation_gener": [4, 6], "make_hamiltonian": [4, 6], "make_hardcore_boson_excitation_g": [4, 6], "make_hardcore_boson_hamiltonian": [4, 6], "make_hardcore_boson_pno_upccd_ansatz": [4, 6], "make_hardcore_boson_upccgd_lay": [4, 6], "make_molecul": [4, 6], "make_molecular_hamiltonian": [4, 6], "make_number_op": [4, 6], "make_orbital_rotation_g": [4, 6], "make_parameter_dictionari": [4, 6], "make_parameter_map": [0, 4], "make_pno_upccgsd_ansatz": [4, 6], "make_qubit_map": [4, 7], "make_rdm12": [4, 6], "make_s2_op": [4, 6], "make_sm_op": [4, 6], "make_sp_op": [4, 6], "make_spa_ansatz": [4, 6], "make_sz_op": [4, 6], "make_uccsd_ansatz": [4, 6], "make_upccgsd_ansatz": [4, 6], "make_upccgsd_indic": [4, 6], "make_upccgsd_lay": [4, 6], "make_upccgsd_singl": [4, 6], "manag": 6, "mani": [5, 7], "manipul": 6, "manybodyamplitud": 6, "map": [0, 5, 6, 7], "map_qubit": [0, 4], "map_stat": [4, 6], "map_vari": [0, 4], "mark_parametrized_g": 0, "markup": 1, "master": [0, 6], "match": 6, "math": [0, 2, 6], "matplotlib": 5, "matric": [0, 6], "matrix": 6, "matter": [0, 7], "max": 5, "max_block_s": 7, "max_cycle_macro": 6, "max_cycle_micro": 6, "max_qubit": [0, 4], "maximum": [5, 6, 7], "maxit": [4, 5], "maxrank": 6, "mcscf": 6, "mcscf_local_data": [4, 6], "mcscf_object": [4, 6], "me_to_bk": [4, 6], "me_to_jw": [4, 6], "mead": 5, "mean": 5, "measur": 7, "member": 6, "method": [1, 4, 5, 6, 7], "method_bound": [4, 5], "method_constraint": [4, 5], "method_opt": [4, 5], "might": 6, "min_vector": 5, "minim": [0, 4, 5, 6], "minimize_modulenam": 5, "minimize_scipi": 5, "miss": 6, "mix": 6, "mix_sd": 6, "mo": 6, "mo_coeff": [4, 6], "modal": 5, "model": [6, 7], "modul": [1, 3, 4], "mol": [4, 6], "molecul": [4, 6], "molecular": 6, "molecular_data_param": [4, 6], "moleculardata": 6, "molecularhamiltonian": 6, "molecule_argu": [4, 6], "molecule_f12tensor": 6, "molecule_factori": [4, 6], "moleculefromopenfermion": [4, 6], "moleculefromtequila": [4, 6], "moment": [0, 4, 5], "momenta": 5, "moments_lookup": [4, 5], "moments_trajectori": [4, 5], "more": [0, 1, 5, 6, 7], "most": [0, 6], "mp2": 6, "mra_orbital_x": 6, "msg": [0, 5, 6, 7], "mulliken": 6, "multicontrol": 0, "multipl": [0, 4, 6, 7], "multipli": [0, 1, 2, 6], "multitarget": [0, 7], "must": [0, 5, 6, 7], "mutat": 0, "my_circuit": 0, "mymodul": 1, "n": [0, 6], "n_down": 6, "n_electron": [4, 6], "n_orbit": [4, 6], "n_pno": 6, "n_qubit": [0, 2, 4, 7], "n_ri": 6, "n_rotat": [4, 6], "n_up": 6, "n_virt": 6, "name": [0, 1, 4, 5, 6, 7], "name_and_param": [0, 4], "name_gtensor": 6, "name_htensor": 6, "namn": 6, "napoleon": 1, "nativ": [6, 7], "natur": 5, "nbodytensor": [4, 6], "nbtensor": 6, "ncg": 5, "ndarrai": [5, 6, 7], "ndii": 5, "necesarri": 7, "necessari": [5, 7], "necessarili": [2, 7], "need": [0, 1, 2, 5, 6, 7], "neglect": [2, 6], "neglect_z": 6, "nelder": 5, "nest": 0, "nesterov": 5, "networkx": 0, "new": [0, 5, 6, 7], "newton": 5, "nextlearningr": [4, 5], "nielsen": 0, "nirrep": [4, 6], "no_compil": 0, "no_transl": [4, 7], "node": 0, "nois": [4, 5, 7], "noise_lookup": [4, 7], "noise_model": 7, "noisemodel": [0, 4, 5, 7], "noisi": 7, "non": [0, 6, 7], "none": [0, 2, 5, 6, 7], "nonlinearli": 5, "normal": [2, 6], "notat": 6, "note": [0, 2, 6, 7], "notebook": 7, "npy": 6, "nuclear": 6, "nuclear_repuls": 6, "nullspac": 0, "num_iter": [4, 5], "number": [0, 1, 4, 5, 6, 7], "numer": [0, 1, 5, 6], "numpi": [1, 6, 7], "o": 6, "ob": 6, "obj": 0, "object": [0, 5, 6, 7], "occ": [4, 6], "occup": 6, "occupi": 6, "occupied_indic": 6, "occur": 0, "odd": 6, "oder": 6, "often": 6, "old": [0, 6], "old_molecul": [4, 6], "onc": [1, 5, 6], "one": [0, 2, 5, 6, 7], "one_bodi": 6, "one_body_integr": [4, 6], "ones": 6, "onli": [0, 2, 5, 6, 7], "onto": [0, 2, 7], "op": [6, 7], "op_lookup": [4, 7], "open": [0, 6], "openfermion": 2, "openfermion_format": 2, "openqasm": 0, "openvqeepyscfexcept": [4, 6], "oper": [0, 1, 2, 6, 7], "opt": 6, "optim": [0, 3, 4, 7], "optimize_circuit": [4, 7], "optimize_orbit": [4, 6], "optimizeorbitalsresult": [4, 6], "optimizer_argu": 6, "optimizer_bas": 5, "optimizer_gd": 5, "optimizer_scipi": 5, "optimizeresult": 5, "optimizergd": [4, 5], "optimizerhistori": [4, 5], "optimizerresult": [4, 5], "optimizerscipi": [4, 5], "optimz": 5, "option": [0, 1, 5, 7], "orbit": 4, "orbital_coeffici": [4, 6], "orbital_energi": [4, 6], "orbital_optim": 6, "orbital_typ": 6, "orbitaldata": [4, 6], "order": [0, 4, 5, 7], "org": [0, 6], "origin": [0, 6, 7], "original_c": 5, "original_lr": 5, "orthonorm": 6, "orthonormalize_basis_orbit": [4, 6], "other": [0, 1, 5, 6, 7], "otherwis": [6, 7], "otim": 0, "out": [5, 6, 7], "output": [6, 7], "outputfil": 6, "over": [5, 6, 7], "overlap": 6, "overlap_integr": [4, 6], "overrid": 6, "overridden": 6, "overview": [3, 5, 6], "overwrit": [6, 7], "overwritten": 7, "ovverrid": 7, "own": [5, 7], "p": [0, 5, 6], "p0": [0, 6], "p1": [0, 6], "p2": [0, 6], "p_k": 6, "packag": 5, "package_interfac": 6, "pair": [0, 4, 5, 6], "pair_info": 6, "paper": [0, 6], "param": [0, 1, 5, 6, 7], "param_vector": 5, "paramet": [0, 1, 2, 5, 7], "parameter": 0, "parameter_map": 0, "parametermap": 0, "parametershamiltonian": 6, "parameterspsi4": 6, "parametersqc": [4, 6], "parametr": [0, 6, 7], "parametricquantumcircuit": 7, "parametrizedgateimpl": 0, "parametrizedquantumcircuit": 7, "paremtr": 0, "pars": 0, "parse_command": [0, 4], "parse_custom_g": [0, 4], "parse_from_open_qasm_2": [0, 4], "part": [0, 1, 2, 6, 7], "particl": 6, "pass": [0, 2, 5, 6, 7], "passiv": [5, 6], "passive_angl": 5, "pattern": 6, "pauli": [0, 4, 7], "paulig": [0, 4], "paulistr": [0, 4, 7], "pdf": 0, "per": 6, "perform": [0, 1, 5, 6, 7], "perhap": [5, 7], "perspect": 0, "perturbative_f12_correct": [4, 6], "ph": 0, "phase": [0, 4, 6, 7], "phase_to_z": [0, 7], "phaseamplitudedamp": [0, 4], "phasedamp": [0, 4], "phaseflip": [0, 4], "phi": [0, 6], "phi_list": 6, "physic": 6, "physreva": 6, "pi": [0, 6], "pick": [5, 6, 7], "pick_backend": [4, 7], "pictur": 6, "plot": [4, 5, 6], "plot2cub": [4, 6], "plu": 6, "pmatrix": 0, "pn": 6, "png": 0, "pno": 6, "point": [5, 6, 7], "point_group": [4, 6], "posit": 0, "possibl": [0, 6], "post_process": [4, 6], "potenti": [0, 5, 6], "powel": 5, "power": [0, 7], "powerg": [0, 4], "pq": 6, "pq_r": 6, "predefin": 6, "prefer": 7, "prepar": [4, 5, 6, 7], "prepare_hardcore_boson_refer": [4, 6], "prepare_product_st": [4, 6], "prepare_refer": [4, 6], "present": 1, "pretti": 7, "prevent": [0, 5, 7], "previou": 6, "previous": [0, 1], "print": [0, 5, 6, 7], "print_basis_info": [4, 6], "print_coeffici": 6, "print_level": [4, 5], "printout": [5, 6], "prior": 7, "priorit": 6, "prioriti": 6, "privat": 6, "prob": [0, 4], "prob_length": [0, 4], "probabl": 0, "procedur": 7, "process": 1, "prod_": 6, "produc": 7, "product": [1, 6], "progress": 5, "project": [1, 2], "projector": [0, 2, 4, 6], "proper": 0, "properli": [0, 7], "properti": [0, 5, 6, 7], "protocol": 6, "provid": [0, 3, 6, 7], "psi": [2, 6], "psi4": 4, "psi4_interfac": 6, "psi4_method": 6, "psi4_opt": 6, "psi4_rdm": 6, "psi4manu": 6, "psi4result": [4, 6], "psicod": 6, "psithonmol": 6, "puls": 0, "pure": 7, "purpos": 1, "push": [4, 5], "pvdz": 6, "py": [0, 1, 5, 6], "pyquil": 4, "pyscf": 4, "pyscf_api_doc": 6, "pyscf_argu": 6, "pyscf_interfac": 6, "pyscfvqewrapp": [4, 6], "pyzx": 4, "q": [0, 6], "q0": 6, "q1": 6, "q_k": 6, "qasm": 4, "qasm_cod": 0, "qc": 4, "qc_base": 6, "qcircuit": [0, 4, 6, 7], "qgate": [0, 4, 7], "qgateimpl": [0, 7], "qi": 6, "qibo": 4, "qiskit": 4, "qlm": 4, "qm": [2, 4], "qn": 6, "qng": 5, "qp": [2, 4], "qpic": [4, 7], "qpic_doc": 0, "qreg": 0, "qregist": 0, "qregisters_valu": 0, "qtensor": [0, 6, 7], "quant": 0, "quantiz": 6, "quantomat": 0, "quantum": [0, 3, 4, 5], "quantumchemistri": 6, "quantumchemistrybas": [4, 6], "quantumchemistrybaseclass": 6, "quantumchemistrymad": [4, 6], "quantumchemistrypsi4": [4, 6], "quantumchemistrypyscf": [4, 6], "quantumcircuit": 7, "quantumnois": [0, 4], "quantumst": 7, "qubit": [0, 4, 6, 7], "qubit_map": [0, 4, 7], "qubit_nam": 0, "qubitexcit": [0, 4], "qubitexcitationimpl": [0, 4, 6], "qubithamiltonian": [0, 2, 6], "qubitoper": [2, 6], "qubitwavefunct": [2, 7], "question": 7, "qulac": 4, "r": [0, 5, 6], "r12": 6, "r_": 0, "r_12": 6, "r_x": 0, "r_z": 0, "rac": 0, "radian": 6, "rais": [0, 1, 7], "random": [0, 5, 6], "random_loc": 6, "randomli": 5, "rang": 6, "rangl": 2, "rate": 5, "rdm": 6, "rdm1": [4, 6], "rdm1_spinsum": 6, "rdm2": [4, 6], "rdm2_spinsum": 6, "rdm__psi4_method": 6, "rdm__psi4_opt": 6, "rdm_spinsum": [4, 6], "rdm_trafo": 6, "re": 6, "reach": 5, "read": [0, 6], "read_out_qubit": 7, "read_tensor": [4, 6], "read_xyz_from_fil": [4, 6], "readi": 5, "real": [0, 5, 6, 7], "realli": 7, "realnumb": 7, "rebuild": 1, "receiv": 0, "reciev": 5, "recommend": [1, 5, 6], "recomput": 6, "reconstruct": 6, "reconstruct_matrix_from_given": [4, 6], "recreat": 7, "rectangl": 1, "redirect": 5, "reduc": [6, 7], "reduce_hamiltonian": [4, 7], "reduct": 7, "refer": [0, 1, 3, 5, 6], "referenc": 1, "reference_orbit": [4, 6], "reformat": 6, "regist": 5, "registr": 5, "regular": 5, "reiniti": 0, "relav": 5, "relev": 5, "remov": [0, 1, 5, 6], "remove_constant_term": 6, "render": [5, 7], "reorder": [4, 6], "repeat": 6, "repet": 6, "repetit": 6, "replac": [0, 5], "replace_g": [0, 4], "repreat": 6, "repres": [0, 1, 2, 5, 6, 7], "represent": 6, "repuls": 6, "requir": [5, 6, 7], "resepct": 5, "reset": [4, 5], "reset_histori": [4, 5], "reset_momenta": [4, 5], "reset_momenta_for": [4, 5], "reset_stepp": [4, 5], "resolut": 6, "resolv": 6, "respect": 0, "rest": 6, "restrict": 6, "restrict_to_active_spac": 6, "restrict_to_hcb": 6, "resullt": 7, "result": [0, 1, 2, 5, 6, 7], "retrieve_devic": [4, 7], "return": [0, 1, 2, 5, 6, 7], "return_diagon": 6, "return_energi": 6, "return_mcscf": 6, "rho": [4, 5], "ri": 6, "rid": 0, "right": [2, 6], "rigor": 0, "rmd1": 6, "rmd2": 6, "rmsprop": 5, "rotat": [0, 6], "rotationg": [0, 4], "row": 6, "rp": [0, 4], "rtype": [0, 1, 5, 6, 7], "rule": 0, "run": [5, 6, 7], "run_mad": [4, 6], "rvert": 2, "rvert_": 2, "rx": [0, 4], "ry": [0, 4, 6], "ry_gat": 0, "rz": [0, 4, 6], "sai": 5, "said": 5, "same": [0, 6, 7], "sampl": [4, 5, 7], "sample_all_z_hamiltonian": [4, 7], "sample_paulistr": [4, 7], "save": [0, 5, 6, 7], "save_histori": [4, 5], "scale": [5, 6], "scf": 6, "scheme": 6, "schuld": 0, "scipi": 4, "scipy_result": [4, 5], "scipyresult": [4, 5], "scipyreturntyp": 5, "scratch": 1, "screen": 6, "second": [0, 1, 5, 6], "section": 1, "see": [0, 1, 2, 5, 6, 7], "seen": 7, "segregr": 5, "select": 7, "self": [0, 1, 5, 6, 7], "sensit": 6, "separ": 6, "sequenc": [5, 6, 7], "seri": 6, "set": [0, 5, 6, 7], "set_index_list": [4, 6], "sever": [5, 7], "sgd": 5, "shall": [0, 5, 7], "shallow": 6, "shape": [4, 6], "shell": 6, "shift": 0, "shortcut": 6, "shot": 5, "should": [0, 2, 5, 6, 7], "show_available_method": 5, "show_available_modul": [4, 6], "show_available_optim": [4, 5], "show_available_simul": [4, 7], "show_supported_modul": [4, 6], "sigma_": 0, "sigma_i": 2, "sigma_x": 2, "sigma_z": 2, "sign": [0, 6], "signatur": 6, "silenc": 6, "silent": [4, 5, 6, 7], "sim": 0, "similar": [0, 1, 6, 7], "simpl": 1, "simpli": 5, "simul": [0, 3, 4, 5, 6], "simulatedli": 5, "simulator_api": 7, "simulator_bas": 7, "simulator_qulac": 7, "simulator_qulacs_gpu": 7, "simulator_symbol": 7, "simultan": 0, "sin": 0, "sinc": [0, 6], "singl": [0, 2, 5, 6, 7], "size": [5, 6, 7], "size_ful": 6, "skip": 6, "slice": 6, "slsqp": 5, "sm": [2, 4], "small": [2, 5, 6], "smaller": [2, 5, 6], "smolin": 0, "so": [0, 2, 6, 7], "solver": 6, "some": [0, 5, 6, 7], "sort": [0, 6], "sort_gat": [0, 4], "sought": 5, "sourc": [0, 2, 5, 6, 7], "sp": [2, 4], "spa": 6, "space": 6, "spatial": 6, "special": [5, 6, 7], "specif": [0, 1, 5, 6, 7], "specifi": [0, 5, 6, 7], "spin": 6, "spin_adapt_singl": 6, "spin_fre": 6, "spin_z": 6, "spsa": 5, "sqrt": 0, "src": [0, 6], "ssss": 6, "stabil": 5, "stai": 6, "standard": [0, 5, 6], "standard_gate_set": [0, 4], "start": [1, 5, 6], "state": [0, 2, 6, 7], "static": [0, 6], "step": [0, 4, 5], "step_lookup": [4, 5], "stepper": 5, "steprat": 5, "stepsiz": 5, "sto": 6, "stop": 5, "store": [5, 6, 7], "str": [0, 1, 2, 5, 6, 7], "string": [0, 2, 5, 6, 7], "strqua": 2, "structur": [0, 1, 2, 5, 6, 7], "style": [0, 1, 6], "sub_list": [4, 6], "sub_str": [4, 6], "subcircuit": 0, "submodul": 4, "subroutin": [6, 7], "subspac": 6, "substitut": 0, "success": 6, "suggest": 5, "suitabl": 6, "sum": [1, 6, 7], "sum_rdm1": 6, "sum_rdm2": 6, "summat": 6, "suppli": 7, "support": [0, 1, 6, 7], "supports_ucc": [4, 6], "suppos": 6, "sure": [0, 1], "surrog": 6, "swap": [0, 4, 6, 7], "symbol": [0, 4], "sympi": 7, "system": [5, 6, 7], "t": [0, 4, 5, 6], "tabl": [5, 6], "take": [0, 5, 6, 7], "taken": 7, "talli": 5, "taperedbravykitaev": [4, 6], "target": [0, 6, 7], "target_qubit": 7, "tell": 7, "tensor": 6, "tequila": [0, 2, 5, 6, 7], "tequila_cod": [0, 2, 5, 6, 7], "tequilacompilerexcept": [0, 4], "tequilaexcept": [0, 5, 6, 7], "tequilamadnessexcept": [4, 6], "tequilaoptimizerexcept": [4, 5], "tequilapsi4except": [4, 6], "tequilaqulacsexcept": [4, 7], "tequilaqulacsgpuexcept": [4, 7], "tequilascipyexcept": [4, 5], "term": [0, 5, 6, 7], "termin": 5, "test": [5, 6], "tex": 0, "text": [0, 6], "textcolor1": 0, "textcolor2": 0, "th": 6, "than": [0, 2, 5, 6, 7], "thei": [0, 5, 6], "them": [0, 1, 3, 6], "themselv": 0, "theori": 6, "therefor": 6, "therefrom": 7, "thereof": 7, "theta": [0, 6], "theta_list": 6, "thi": [0, 1, 2, 3, 5, 6, 7], "third": 0, "those": [0, 2, 5, 6, 7], "three": [0, 6], "threshold": [2, 6], "through": 6, "throughout": 5, "thu": 6, "tia": [4, 6], "tijab": [4, 6], "time": 5, "tnc": 5, "to_networkx": [0, 4], "to_real_if_poss": 6, "todo": [0, 7], "toffoli": [0, 4, 7], "togeth": [0, 1, 2], "tol": [4, 5, 6], "toler": [5, 6], "tool": [4, 7], "top": 1, "total": [0, 6], "touch": 0, "tq": [0, 2, 5, 6], "trace": 7, "track": 6, "transfer": 2, "transform": [0, 6, 7], "transform_orbit": [4, 6], "transform_to_native_orbit": [4, 6], "translat": 7, "treat": [0, 6], "tree": 6, "trial": 6, "trotter": [0, 4, 6, 7], "trotter_step": 6, "true": [0, 2, 5, 7], "truncat": 6, "trust": 5, "truth": 0, "try": 6, "tupl": [5, 6, 7], "turn": 0, "two": [0, 1, 5, 6], "two_body_integr": [4, 6], "type": [0, 2, 5, 6, 7], "typic": 6, "u": [0, 4, 6, 7], "u0": 0, "u1": [0, 4], "u2": [0, 4], "u3": [0, 4], "u_": 0, "uc": [4, 6], "ucc": 6, "uccsd": 6, "unaffect": 0, "uncompil": 5, "under": 0, "underli": 7, "union": [0, 5, 6], "unit": [2, 6, 7], "unitari": [0, 6, 7], "unknown": 6, "unpack": 5, "unparametr": [0, 7], "unrestrict": 0, "unscal": 5, "until": 5, "unus": 0, "unwant": 0, "up": [0, 4, 6], "up_then_down": 6, "upcc": 6, "upccd": 6, "upccgd": 6, "upccgsd": 6, "upccsd": 6, "updat": [4, 5, 6], "update_vari": [4, 7], "upgccsd": 6, "upon": [0, 7], "upper": 6, "ur": [4, 6], "us": [0, 1, 2, 5, 6, 7], "usabl": 6, "usag": 6, "use_hcb": 6, "use_map": [4, 7], "use_native_orbit": [4, 6], "use_units_of_pi": 6, "user": [5, 7], "usual": [0, 5, 6], "utilis": 3, "valeev": 6, "valid": [6, 7], "valu": [0, 1, 2, 5, 6, 7], "valueerror": 0, "vari": [5, 7], "variabl": [0, 4, 5, 6, 7], "variat": 5, "varieti": 5, "variou": 5, "vector": [5, 6], "verifi": [0, 4, 6, 7], "verify_orbital_coeffici": [4, 6], "versa": 6, "version": [0, 2, 5, 7], "via": [0, 6, 7], "vice": 6, "visibl": 0, "vqe": 6, "vqe_solv": [4, 6], "vqe_solver_argu": [4, 6], "w": [0, 5], "wa": 6, "wai": [0, 5], "want": 6, "warn": 6, "wave": 7, "wavefunct": [0, 2, 5, 6, 7], "we": 6, "websit": 3, "welcom": 3, "well": [0, 1, 6], "wfn": [2, 4, 6], "wfn1": 2, "wfn2": 2, "what": [0, 5, 6, 7], "whatev": [5, 6], "when": [2, 5, 6, 7], "where": [0, 6, 7], "whether": [0, 5, 6, 7], "which": [0, 1, 2, 5, 6, 7], "white": 0, "whole": 0, "whose": [0, 5, 6], "why": 0, "width": 1, "wigner": 6, "wiki": 6, "wikipedia": 6, "wipe": 5, "witch": 6, "with_gat": [0, 4], "within": 0, "without": [0, 6], "without_noise_on_level": [0, 4], "without_noise_op": [0, 4], "word": 7, "work": [5, 6], "would": 6, "wrap": [0, 5], "wrap_gat": [0, 4], "wrap_nois": [0, 4], "wrapper": [0, 6, 7], "write_madness_input": [4, 6], "www": 6, "x": [0, 1, 2, 4, 6], "x_scale": 6, "xyz": 6, "xyz_file_format": 6, "xz": 0, "y": [0, 1, 2, 4, 6], "y_gate": 0, "yet": 6, "you": [1, 5, 6], "your": [1, 5], "z": [0, 2, 4, 6, 7], "zero": [1, 2, 4, 5, 6, 7], "zerodivisionerror": 1, "zx": 0, "zx_calculu": 0}, "titles": ["Circuit", "Documenting Code in reStructuredText for Sphinx", "Hamiltonian", "Tequila Documentation", "Tequila Library Reference", "Optimizers", "Quantum Chemistry", "Simulators"], "titleterms": {"1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "api": 7, "base": [5, 6, 7], "build": 1, "chem": 6, "chemistri": 6, "circuit": 0, "cirq": 7, "clean": 1, "code": 1, "compil": 0, "content": [0, 2, 3, 5, 6, 7], "directori": 1, "docstr": 1, "document": [1, 3], "encod": 6, "fals": 6, "format": 1, "gate": 0, "gpu": 7, "gpyopt": 5, "gradient": [0, 5], "hamiltonian": 2, "ignore_active_spac": 6, "interfac": 6, "introduct": 1, "kwarg": 6, "librari": 4, "mad": 6, "modul": [0, 2, 5, 6, 7], "nois": 0, "openfermion": 6, "optim": [5, 6], "option": 6, "orbit": 6, "order": 6, "paramet": 6, "pauli": 2, "paulistr": 2, "phy": 6, "practic": 3, "psi4": 6, "pyquil": 7, "pyscf": 6, "pyzx": 0, "qasm": 0, "qc": 6, "qibo": 7, "qiskit": 7, "qlm": 7, "qpic": 0, "quantum": 6, "qubit": 2, "qulac": 7, "refer": 4, "restructuredtext": 1, "scipi": 5, "set": 1, "simul": 7, "sphinx": 1, "submodul": [0, 2, 5, 6, 7], "symbol": 7, "tequila": [3, 4], "tool": 6, "true": 6, "tutori": 3, "up": 1, "write": 1}}) \ No newline at end of file diff --git a/docs/sphinx/simulators.html b/docs/sphinx/simulators.html new file mode 100644 index 0000000..703c0e5 --- /dev/null +++ b/docs/sphinx/simulators.html @@ -0,0 +1,1513 @@ + + + + + + + + + Simulators — Tequila Documentation 13.9.2024 documentation + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Simulators

+
+

Submodules

+
+
+

simulator api module

+
+
+class tequila_code.simulators.simulator_api.BackendTypes(CircType, ExpValueType)
+

Bases: tuple

+
+
+CircType
+

Alias for field number 0

+
+ +
+
+ExpValueType
+

Alias for field number 1

+
+ +
+ +
+
+tequila_code.simulators.simulator_api.compile(objective: Objective | QCircuit | QTensor, variables: Dict[Variable | Hashable, Real] = None, samples: int = None, backend: str = None, noise: NoiseModel = None, device: str = None, *args, **kwargs) BackendCircuit | Objective[source]
+

Compile a tequila objective or circuit to a backend

+
+
Parameters:
+
    +
  • objective (Objective:) – tequila objective or circuit

  • +
  • variables (dict, optional:) – The variables of the objective given as dictionary +with keys as tequila Variables and values the corresponding real numbers

  • +
  • samples (int, optional:) – if None a full wavefunction simulation is performed, otherwise a fixed number of samples is simulated

  • +
  • backend (str, optional:) – specify the backend or give None for automatic assignment

  • +
  • noise (NoiseModel, optional:) – the noise model to apply to the objective or QCircuit.

  • +
  • device (optional:) – a device on which (or in emulation of which) to sample the circuit.

  • +
+
+
Returns:
+

the compiled object.

+
+
Return type:
+

simulators.BackendCircuit or Objective

+
+
+
+ +
+
+tequila_code.simulators.simulator_api.compile_circuit(abstract_circuit: QCircuit, variables: Dict[Variable, RealNumber] = None, backend: str = None, samples: int = None, noise: NoiseModel = None, device: str = None, *args, **kwargs) BackendCircuit[source]
+

compile a circuit to render it callable and return it. +:param abstract_circuit: the circuit to compile +:type abstract_circuit: QCircuit: +:param variables: the variables to compile the circuit with. +:type variables: dict, optional: +:param backend: the backend to compile the circuit to. +:type backend: str, optional: +:param samples: only matters if not None; compile the circuit for sampling/verify backend can do so +:type samples: int, optional: +:param device: the device on which the circuit should (perhaps emulatedly) sample. +:type device: optional: +:param noise: the noise to apply to the circuit +:type noise: str or NoiseModel, optional: +:param args: +:param kwargs:

+
+
Returns:
+

the compiled circuit.

+
+
Return type:
+

BackendCircuit

+
+
+
+ +
+
+tequila_code.simulators.simulator_api.compile_objective(objective: Objective, variables: Dict[Variable, Real] = None, backend: str = None, samples: int = None, device: str = None, noise: NoiseModel = None, *args, **kwargs) Objective[source]
+

compile an objective to render it callable and return it. +:param objective: the objective to compile +:type objective: Objective: +:param variables: the variables to compile the objective with. Will autogenerate zeros for all variables if not supplied. +:type variables: dict, optional: +:param backend: the backend to compile the objective to. +:type backend: str, optional: +:param samples: only matters if not None; compile the objective for sampling/verify backend can do so +:type samples: int, optional: +:param device: the device on which the objective should (perhaps emulatedly) sample. +:type device: optional: +:param noise: the noise to apply to all circuits in the objective. +:type noise: str or NoiseModel, optional: +:param args: +:param kwargs:

+
+
Returns:
+

the compiled objective.

+
+
Return type:
+

Objective

+
+
+
+ +
+
+tequila_code.simulators.simulator_api.compile_to_function(objective: Objective | QCircuit, *args, **kwargs) BackendCircuit | Objective[source]
+

Notes

+

Same as compile but gives back callable wrapper +where parameters are passed down as arguments instead of dictionaries +the order of those arguments is the order of the parameter dictionary +given here. If not given it is the order returned by objective.extract_variables()

+

See compile for more information on the parameters of this function

+
+
Returns:
+

wrapper over a compiled objective/circuit +can be called like: function(0.0,1.0,…,samples=None)

+
+
Return type:
+

BackendCircuit or Objective

+
+
+
+ +
+
+tequila_code.simulators.simulator_api.draw(objective, variables=None, backend: str = None, name=None, *args, **kwargs)[source]
+

Pretty output (depends on installed backends) for jupyter notebooks +or similar HTML environments

+
+
Parameters:
+
    +
  • objective – the tequila objective to print out

  • +
  • variables (optional:) – Give variables if the objective is parametrized (not necesarry for displaying)

  • +
  • name (optional:) – Name the objective (changes circuit filenames for qpic backend)

  • +
  • backend (str, optional:) – chose preferred backend (of None or not found it will be automatically picked)

  • +
+
+
+
+ +
+
+tequila_code.simulators.simulator_api.pick_backend(backend: str = None, samples: int = None, noise: NoiseModel = None, device=None, exclude_symbolic: bool = True) str[source]
+

choose, or verify, a backend for the user. +:param backend: what backend to choose or verify. if None: choose for the user. +:type backend: str, optional: +:param samples: if int and not None, choose (verify) a simulator which supports sampling. +:type samples: int, optional: +:param noise: if not None, choose (verify) a simulator supports the specified noise. +:type noise: str or NoiseModel, optional: +:param device: verify that a given backend supports the specified device. MUST specify backend, if not None.

+
+

if None: do not emulate or use real device.

+
+
+
Parameters:
+

exclude_symbolic (bool, optional:) – whether or not to exclude the tequila debugging simulator from the available simulators, when choosing.

+
+
Returns:
+

the name of the chosen (or verified) backend.

+
+
Return type:
+

str

+
+
+
+ +
+
+tequila_code.simulators.simulator_api.show_available_simulators()[source]
+
+ +
+
+tequila_code.simulators.simulator_api.simulate(objective: Objective | QCircuit | QTensor, variables: Dict[Variable | Hashable, Real] = None, samples: int = None, backend: str = None, noise: NoiseModel = None, device: str = None, *args, **kwargs) Real | QubitWaveFunction[source]
+

Simulate a tequila objective or circuit

+
+
Parameters:
+
    +
  • objective (Objective:) – tequila objective or circuit

  • +
  • variables (Dict:) – The variables of the objective given as dictionary +with keys as tequila Variables/hashable types and values the corresponding real numbers

  • +
  • samples (int, optional:) – if None a full wavefunction simulation is performed, otherwise a fixed number of samples is simulated

  • +
  • backend (str, optional:) – specify the backend or give None for automatic assignment

  • +
  • noise (NoiseModel, optional:) – specify a noise model to apply to simulation/sampling

  • +
  • device – a device upon which (or in emulation of which) to sample

  • +
  • *args

  • +
  • **kwargs – read_out_qubits = list[int] (define the qubits which shall be measured, has only effect on pure QCircuit simulation with samples)

  • +
+
+
Returns:
+

the result of simulation.

+
+
Return type:
+

float or QubitWaveFunction

+
+
+
+ +
+
+

simulator base module

+
+
+class tequila_code.simulators.simulator_base.BackendCircuit(abstract_circuit: QCircuit, variables, noise=None, device=None, qubit_map=None, optimize_circuit=True, *args, **kwargs)[source]
+

Bases: object

+

Base class for circuits compiled to run on specific backends.

+
+
+no_translation
+

set this attribute in the derived __init__ to prevent translation of abstract_circuits +needed for simulators that use native tequila types. +Default is false

+
+ +
+
+abstract_circuit
+

the tequila circuit from which the backend circuit is built.

+
+ +
+
+circuit
+

the compiled circuit in the backend language.

+
+ +
+
+compiler_arguments
+

dictionary of arguments for compilation needed for chosen backend. Overwritten by inheritors.

+
+ +
+
+device
+

instantiated device (or None) for executing circuits.

+
+ +
+
+n_qubits
+

the number of qubits this circuit operates on.

+
+ +
+
+noise
+

the NoiseModel applied to this circuit when sampled.

+
+ +
+
+qubit_map
+

the mapping from tequila qubits to the qubits of the backend circuit. +Dicationary with keys being integers that enumerate the abstract qubits of the abstract_circuit +and values being data-structures holding number and instance where number enumerates the +backend qubits and instance is the instance of a backend qubit

+
+ +
+
+qubits
+

a list of the qubits operated on by the circuit.

+
+ +
+
+create_circuit()[source]
+

generate a backend circuit from an abstract tequila circuit

+
+ +
+
+check_device:
+

see if a given device is valid for the backend.

+
+ +
+
+retrieve_device:
+

get an instance of or necessary informaton about a device, for emulation or use.

+
+ +
+
+add_parametrized_gate()[source]
+

add a parametrized gate to a backend circuit.

+
+ +
+
+add_basic_gate()[source]
+

add an unparametrized gate to a backend circuit.

+
+ +
+
+add_measurement()[source]
+

add a measurement gate to a backend circuit.

+
+ +
+
+initialize_circuit:
+

generate an empty circuit object for the backend.

+
+ +
+
+update_variables:
+

overwrite the saved values of variables for backend execution.

+
+ +
+
+simulate:
+

perform simulation, simulated sampling, or execute the circuit, e.g. with some hamiltonian for measurement.

+
+ +
+
+sample_paulistring:
+

sample a circuit with one paulistring of a larger hamiltonian

+
+ +
+
+sample:
+

sample a circuit, measuring an entire hamiltonian.

+
+ +
+
+do_sample:
+

subroutine for sampling. must be overwritten by inheritors.

+
+ +
+
+do_simulate:
+

subroutine for wavefunction simulation. must be overwritten by inheritors.

+
+ +
+
+convert_measurements:
+

transform the result of simulation from the backend return type.

+
+ +
+
+make_qubit_map:
+

create a dictionary to map the tequila qubit ordering to the backend qubits.

+
+ +
+
+optimize_circuit:
+

use backend features to improve circuit depth.

+
+ +
+
+extract_variables:
+

return a list of the variables in the abstract tequila circuit this backend circuit corresponds to.

+
+ +
+
+property abstract_qubits: Iterable[Integral]
+
+ +
+
+add_basic_gate(gate, circuit, *args, **kwargs)[source]
+
+ +
+
+add_measurement(circuit, target_qubits, *args, **kwargs)[source]
+
+ +
+
+add_parametrized_gate(gate, circuit, *args, **kwargs)[source]
+
+ +
+
+check_device(device)[source]
+

Verify if a device can be used in the selected backend. Overwritten by inheritors. +:param device: the device to verify.

+
+
Raises:
+

TequilaException

+
+
+
+ +
+
+compiler_arguments = {'cc_max': True, 'controlled_exponential_pauli': True, 'controlled_phase': True, 'controlled_power': True, 'controlled_rotation': True, 'exponential_pauli': True, 'generalized_rotation': True, 'hadamard_power': True, 'multitarget': True, 'phase': True, 'phase_to_z': True, 'power': True, 'swap': True, 'toffoli': True, 'trotterized': True}
+
+ +
+
+convert_measurements(backend_result) QubitWaveFunction[source]
+
+ +
+
+create_circuit(abstract_circuit: QCircuit, circuit=None, *args, **kwargs)[source]
+

build the backend specific circuit from the abstract tequila circuit.

+
+
Parameters:
+
    +
  • abstract_circuit (QCircuit:) – the circuit to build in the backend

  • +
  • circuit (BackendCircuitType (optional):) – Add to this already initialized circuit (not all backends support + operation)

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

The circuit, compiled to the backend.

+
+
Return type:
+

type varies

+
+
+
+ +
+
+do_sample(samples, circuit, noise, abstract_qubits=None, *args, **kwargs) QubitWaveFunction[source]
+

helper function for sampling. MUST be overwritten by inheritors.

+
+
Parameters:
+
    +
  • samples (int:) – the number of samples to take

  • +
  • circuit – the circuit to sample from. +Note: +Not necessarily self.circuit!

  • +
  • noise – the noise to apply to the sampled circuit.

  • +
  • abstract_qubits – specify which qubits to measure. Default is all

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

the result of sampling.

+
+
Return type:
+

QubitWaveFunction

+
+
+
+ +
+
+do_simulate(variables, initial_state, *args, **kwargs) QubitWaveFunction[source]
+

helper for simulation. MUST be overwritten by inheritors.

+
+
Parameters:
+
    +
  • variables – the variables with which the circuit may be simulated.

  • +
  • initial_state – the initial state in which the system is in prior to the application of the circuit.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

the result of simulating the circuit.

+
+
Return type:
+

QubitWaveFunction

+
+
+
+ +
+
+extract_variables() Dict[str, Real][source]
+

extract the tequila variables from the circuit. +:returns: the variables of the circuit. +:rtype: dict

+
+ +
+
+initialize_circuit(*args, **kwargs)[source]
+
+ +
+
+initialize_qubit(number: int)[source]
+

In case the backend has its own Qubit Types, +this function should be overwritten by inheritors.

+
+
Parameters:
+

number – the qubit number

+
+
Return type:
+

Initialized backend qubit type

+
+
+
+ +
+
+make_qubit_map(qubits: dict)[source]
+

Build the mapping between abstract qubits.

+

Must be overwritten by inheritors to do anything other than check the validity of the map. +:param qubits: the qubits to map onto.

+
+

If given as a dictionary, the map is already defined +If given as a list the map will be those qubits mapped to 0 …. n_qubit-1 of the backend

+
+
+
Returns:
+

the dictionary that maps the qubits of the abstract circuits to an ordered sequence of integers. +keys are the abstract qubit integers +values are the backend qubits +those are data structures which contain name and instance +where number is the qubit identifier and instance the instance of the backend qubit +if the backend does not require a special object for qubits the instance should be the same as number

+
+
Return type:
+

Dict

+
+
+
+ +
+
+property n_qubits: Integral
+
+ +
+
+optimize_circuit(circuit, *args, **kwargs)[source]
+

Optimize a circuit using backend tools. Should be overwritten by inheritors. +:param circuit: the circuit to optimize +:param args: +:param kwargs:

+
+
Returns:
+

Optimized version of the circuit.

+
+
Return type:
+

Type

+
+
+
+ +
+
+qubit(abstract_qubit)[source]
+

Convenience. Gives back a qubit instance of the corresponding backend +:param abstract_qubit: the abstract tequila qubit

+
+
Return type:
+

instance of backend qubit

+
+
+
+ +
+
+retrieve_device(device)[source]
+

get the instantiated backend device object, from user provided object (e.g, a string).

+

Must be overwritten by inheritors, to use devices.

+
+
Parameters:
+

device – object which points to the device in question, to be returned.

+
+
Returns:
+

varies by backend.

+
+
Return type:
+

Type

+
+
+
+ +
+
+sample(variables, samples, read_out_qubits=None, circuit=None, *args, **kwargs)[source]
+

Sample the circuit. If circuit natively equips paulistrings, sample therefrom. +:param variables: the variables with which to sample the circuit. +:param samples: the number of samples to take. +:type samples: int: +:param read_out_qubits: target qubits to measure (default is all) +:type read_out_qubits: int: +:param args: +:param kwargs:

+
+
Returns:
+

The result of sampling, a recreated QubitWaveFunction in the sampled basis.

+
+
Return type:
+

QubitWaveFunction

+
+
+
+ +
+
+sample_all_z_hamiltonian(samples: int, hamiltonian, variables, *args, **kwargs)[source]
+

Sample from a Hamiltonian which only consists of Pauli-Z and unit operators +:param samples: number of samples to take +:param hamiltonian: the tequila hamiltonian +:param args: arguments for do_sample +:param kwargs: keyword arguments for do_sample

+
+
Return type:
+

samples, evaluated and summed Hamiltonian expectationvalue

+
+
+
+ +
+
+sample_paulistring(samples: int, paulistring, variables, *args, **kwargs) Real[source]
+

Sample an individual pauli word (pauli string) and return the average result thereof. +:param samples: how many samples to evaluate. +:type samples: int: +:param paulistring: the paulistring to be sampled. +:param args: +:param kwargs:

+
+
Returns:
+

the average result of sampling the chosen paulistring

+
+
Return type:
+

float

+
+
+
+ +
+
+simulate(variables, initial_state=0, *args, **kwargs) QubitWaveFunction[source]
+

simulate the circuit via the backend.

+
+
Parameters:
+
    +
  • variables – the parameters with which to simulate the circuit.

  • +
  • initial_state (Default = 0:) – one of several types; determines the base state onto which the circuit is applied. +Default: the circuit is applied to the all-zero state.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

the wavefunction of the system produced by the action of the circuit on the initial state.

+
+
Return type:
+

QubitWaveFunction

+
+
+
+ +
+
+update_variables(variables)[source]
+

This is the default, which just translates the circuit again. +Overwrite in inheritors if parametrized circuits are supported.

+
+ +
+ +
+
+class tequila_code.simulators.simulator_base.BackendExpectationValue(E, variables, noise, device, *args, **kwargs)[source]
+

Bases: object

+

Class representing an ExpectationValue for evaluation by some backend.

+
+
+H
+

the reduced tequila Hamiltonian(s) of the expectationvalue +reduction procedure is tracing out all qubits that are not part of the unitary U +stored as a tuple to evaluate multiple Hamiltonians over the same circuit faster in pure simulations

+
+ +
+
+abstract_H
+

the original (non-reduced) Hamiltonian(s)

+
+ +
+
+n_qubits
+

how many qubits appear in the expectationvalue.

+
+ +
+
+U
+

the underlying BackendCircuit of the expectationvalue.

+
+ +
+
+extract_variables:
+

return the underlying tequila variables of the circuit

+
+ +
+
+initialize_hamiltonian()[source]
+

prepare the hamiltonian for iteration over as a tuple

+
+ +
+
+initialize_unitary()[source]
+

compile the abstract circuit to a backend circuit.

+
+ +
+
+simulate:
+

simulate the unitary to measure H

+
+ +
+
+sample:
+

sample the unitary to measure H

+
+ +
+
+sample_paulistring()
+

sample a single term from H

+
+ +
+
+update_variables()[source]
+

wrapper over the update_variables of BackendCircuit.

+
+ +
+
+BackendCircuitType
+

alias of BackendCircuit

+
+ +
+
+property H
+
+ +
+
+property U
+
+ +
+
+count_measurements()[source]
+
+ +
+
+extract_variables() Dict[str, Real][source]
+

wrapper over circuit extract variables +:returns: Todo: is it really a dict? +:rtype: Dict

+
+ +
+
+initialize_hamiltonian(hamiltonians: tuple) tuple[source]
+
+ +
+
+initialize_unitary(U, variables, noise, device, *args, **kwargs)[source]
+

return a compiled unitary

+
+ +
+
+property n_qubits
+
+ +
+
+reduce_hamiltonians(abstract_hamiltonians: tuple) tuple[source]
+
+
Parameters:
+

abstract_hamiltonians – tuple of abstract tequila Hamiltonians

+
+
Return type:
+

reduces Hamiltonians where the qubits that are not defined in self.U are traced out

+
+
+
+ +
+
+sample(variables, samples, *args, **kwargs) array[source]
+

sample the expectationvalue.

+
+
Parameters:
+
    +
  • variables (dict:) – variables to supply to the unitary.

  • +
  • samples (int:) – number of samples to perform.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

a numpy array, the result of sampling.

+
+
Return type:
+

numpy.ndarray

+
+
+
+ +
+
+simulate(variables, *args, **kwargs)[source]
+

Simulate the expectationvalue.

+
+
Parameters:
+
    +
  • variables – variables to supply to the unitary.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

the result of simulation.

+
+
Return type:
+

numpy array

+
+
+
+ +
+
+update_variables(variables)[source]
+

wrapper over circuit update_variables

+
+ +
+
+use_mapping = True
+
+ +
+ +
+
+

simulator cirq module

+
+
+

simulator pyquil module

+
+
+

simulator qibo module

+
+
+

simulator qiskit module

+
+
+

simulator qlm module

+
+
+

simulator qulacs module

+
+
+class tequila_code.simulators.simulator_qulacs.BackendCircuitQulacs(abstract_circuit, noise=None, *args, **kwargs)[source]
+

Bases: BackendCircuit

+

Class representing circuits compiled to qulacs. +See BackendCircuit for documentation of features and methods inherited therefrom

+
+
+counter
+

counts how many distinct sympy.Symbol objects are employed in the circuit.

+
+ +
+
+has_noise
+

whether or not the circuit is noisy. needed by the expectationvalue to do sampling properly.

+
+ +
+
+noise_lookup
+

dict mapping strings to lists of constructors for cirq noise channel objects.

+
+
Type:
+

dict:

+
+
+
+ +
+
+op_lookup
+

dictionary mapping strings (tequila gate names) to cirq.ops objects.

+
+
Type:
+

dict:

+
+
+
+ +
+
+variables
+

a list of the qulacs variables of the circuit.

+
+
Type:
+

list:

+
+
+
+ +
+
+add_noise_to_circuit:
+

apply a tequila NoiseModel to a qulacs circuit, by translating the NoiseModel’s instructions into noise gates.

+
+ +
+
+add_basic_gate(gate, circuit, *args, **kwargs)[source]
+

add an unparametrized gate to the circuit. +:param gate: the gate to be added to the circuit. +:type gate: QGateImpl: +:param circuit: the circuit, to which a gate is to be added. +:param args: +:param kwargs:

+
+
Return type:
+

None

+
+
+
+ +
+
+add_exponential_pauli_gate(gate, circuit, variables, *args, **kwargs)[source]
+

Add a native qulacs Exponential Pauli gate to a circuit. +:param gate: the gate to add +:type gate: ExpPauliGateImpl: +:param circuit: the qulacs circuit, to which the gate is to be added. +:param variables: dict containing values of the parameters appearing in the pauli gate. +:param args: +:param kwargs:

+
+
Return type:
+

None

+
+
+
+ +
+
+add_measurement(circuit, target_qubits, *args, **kwargs)[source]
+

Add a measurement operation to a circuit. +:param circuit: a circuit, to which the measurement is to be added. +:param target_qubits: abstract target qubits +:type target_qubits: List[int] +:param args: +:param kwargs:

+
+
Return type:
+

None

+
+
+
+ +
+
+add_noise_to_circuit(noise_model)[source]
+

Apply noise from a NoiseModel to a circuit. +:param noise_model: the noisemodel to apply to the circuit. +:type noise_model: NoiseModel:

+
+
Returns:
+

self.circuit, with noise added on.

+
+
Return type:
+

qulacs.ParametrizedQuantumCircuit

+
+
+
+ +
+
+add_parametrized_gate(gate, circuit, variables, *args, **kwargs)[source]
+

add a parametrized gate. +:param gate: the gate to add to the circuit. +:type gate: QGateImpl: +:param circuit: the circuit to which the gate is to be added +:param variables: dict that tells values of variables; needed IFF the gate is an ExpPauli gate. +:param args: +:param kwargs:

+
+
Return type:
+

None

+
+
+
+ +
+
+compiler_arguments = {'cc_max': False, 'controlled_exponential_pauli': True, 'controlled_phase': True, 'controlled_power': True, 'controlled_rotation': True, 'exponential_pauli': False, 'generalized_rotation': True, 'hadamard_power': True, 'multitarget': True, 'phase': True, 'phase_to_z': True, 'power': True, 'swap': False, 'toffoli': False, 'trotterized': True}
+
+ +
+
+convert_measurements(backend_result, target_qubits=None) QubitWaveFunction[source]
+

Transform backend evaluation results into QubitWaveFunction +:param backend_result: the return value of backend simulation.

+
+
Returns:
+

results transformed to tequila native QubitWaveFunction

+
+
Return type:
+

QubitWaveFunction

+
+
+
+ +
+
+do_sample(samples, circuit, noise_model=None, initial_state=0, *args, **kwargs) QubitWaveFunction[source]
+

Helper function for performing sampling.

+
+
Parameters:
+
    +
  • samples (int:) – the number of samples to be taken.

  • +
  • circuit – the circuit to sample from.

  • +
  • noise_model (optional:) – noise model to be applied to the circuit.

  • +
  • initial_state – sampling supports initial states for qulacs. Indicates the initial state to which circuit is applied.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

the results of sampling, as a Qubit Wave Function.

+
+
Return type:
+

QubitWaveFunction

+
+
+
+ +
+
+do_simulate(variables, initial_state, *args, **kwargs)[source]
+

Helper function to perform simulation.

+
+
Parameters:
+
    +
  • variables (dict:) – variables to supply to the circuit.

  • +
  • initial_state – information indicating the initial state on which the circuit should act.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

QubitWaveFunction representing result of the simulation.

+
+
Return type:
+

QubitWaveFunction

+
+
+
+ +
+
+initialize_circuit(*args, **kwargs)[source]
+

return an empty circuit. +:param args: +:param kwargs:

+
+
Return type:
+

qulacs.ParametricQuantumCircuit

+
+
+
+ +
+
+initialize_state(n_qubits: int = None) QuantumState[source]
+
+ +
+
+no_translation(abstract_circuit)[source]
+

Todo: what is this for? +:param abstract_circuit:

+
+ +
+
+numbering = 0
+
+ +
+
+optimize_circuit(circuit, max_block_size: int = 4, silent: bool = True, *args, **kwargs)[source]
+

reduce circuit depth using the native qulacs optimizer. +:param circuit: +:param max_block_size: the maximum block size for use by the qulacs internal optimizer. +:type max_block_size: int: Default = 4: +:param silent: whether or not to print the resullt of having optimized. +:type silent: bool: +:param args: +:param kwargs:

+
+
Returns:
+

optimized qulacs circuit.

+
+
Return type:
+

qulacs.QuantumCircuit

+
+
+
+ +
+
+update_variables(variables)[source]
+

set new variable values for the circuit. +:param variables: the variables to supply to the circuit. +:type variables: dict:

+
+
Return type:
+

None

+
+
+
+ +
+ +
+
+class tequila_code.simulators.simulator_qulacs.BackendExpectationValueQulacs(E, variables, noise, device, *args, **kwargs)[source]
+

Bases: BackendExpectationValue

+

Class representing Expectation Values compiled for Qulacs.

+

Ovverrides some methods of BackendExpectationValue, which should be seen for details.

+
+
+BackendCircuitType
+

alias of BackendCircuitQulacs

+
+ +
+
+initialize_hamiltonian(hamiltonians)[source]
+

Convert reduced hamiltonians to native Qulacs types for efficient expectation value evaluation. +:param hamiltonians: an interable set of hamiltonian objects.

+
+
Returns:
+

initialized hamiltonian objects.

+
+
Return type:
+

list

+
+
+
+ +
+
+sample(variables, samples, *args, **kwargs) array[source]
+

Sample this Expectation Value. +:param variables: variables, to supply to the underlying circuit. +:param samples: the number of samples to take. +:type samples: int: +:param args: +:param kwargs:

+
+
Returns:
+

the result of sampling as a number.

+
+
Return type:
+

numpy.ndarray

+
+
+
+ +
+
+simulate(variables, *args, **kwargs) array[source]
+

Perform simulation of this expectationvalue. +:param variables: variables, to be supplied to the underlying circuit. +:param args: +:param kwargs:

+
+
Returns:
+

the result of simulation as an array.

+
+
Return type:
+

numpy.array

+
+
+
+ +
+
+use_mapping = True
+
+ +
+ +
+
+exception tequila_code.simulators.simulator_qulacs.TequilaQulacsException(msg)[source]
+

Bases: TequilaException

+
+ +
+
+

simulator qulacs gpu module

+
+
+class tequila_code.simulators.simulator_qulacs_gpu.BackendCircuitQulacsGpu(abstract_circuit, noise=None, *args, **kwargs)[source]
+

Bases: BackendCircuitQulacs

+
+
+initialize_state(n_qubits: int = None) QuantumState[source]
+
+ +
+ +
+
+class tequila_code.simulators.simulator_qulacs_gpu.BackendExpectationValueQulacsGpu(E, variables, noise, device, *args, **kwargs)[source]
+

Bases: BackendExpectationValueQulacs

+
+
+BackendCircuitType
+

alias of BackendCircuitQulacsGpu

+
+ +
+ +
+
+exception tequila_code.simulators.simulator_qulacs_gpu.TequilaQulacsGpuException(msg)[source]
+

Bases: TequilaException

+
+ +
+
+

simulator symbolic module

+
+
+class tequila_code.simulators.simulator_symbolic.BackendCircuitSymbolic(abstract_circuit: QCircuit, variables, noise=None, device=None, qubit_map=None, optimize_circuit=True, *args, **kwargs)[source]
+

Bases: BackendCircuit

+
+
+classmethod apply_gate(state: QubitWaveFunction, gate: QGate, qubits: dict, variables) QubitWaveFunction[source]
+
+ +
+
+classmethod apply_on_standard_basis(gate: QGate, basisfunction: BitString, qubits: dict, variables) QubitWaveFunction[source]
+
+ +
+
+compiler_arguments = {'cc_max': True, 'controlled_exponential_pauli': True, 'controlled_phase': True, 'controlled_power': True, 'controlled_rotation': False, 'exponential_pauli': True, 'generalized_rotation': True, 'hadamard_power': True, 'multitarget': True, 'phase': True, 'phase_to_z': True, 'power': True, 'swap': True, 'toffoli': True, 'trotterized': True}
+
+ +
+
+convert_to_numpy = True
+
+ +
+
+create_circuit(abstract_circuit: QCircuit, variables=None)[source]
+

build the backend specific circuit from the abstract tequila circuit.

+
+
Parameters:
+
    +
  • abstract_circuit (QCircuit:) – the circuit to build in the backend

  • +
  • circuit (BackendCircuitType (optional):) – Add to this already initialized circuit (not all backends support + operation)

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

The circuit, compiled to the backend.

+
+
Return type:
+

type varies

+
+
+
+ +
+
+do_simulate(variables, initial_state: int = None, *args, **kwargs) QubitWaveFunction[source]
+

helper for simulation. MUST be overwritten by inheritors.

+
+
Parameters:
+
    +
  • variables – the variables with which the circuit may be simulated.

  • +
  • initial_state – the initial state in which the system is in prior to the application of the circuit.

  • +
  • args

  • +
  • kwargs

  • +
+
+
Returns:
+

the result of simulating the circuit.

+
+
Return type:
+

QubitWaveFunction

+
+
+
+ +
+
+update_variables(variables)[source]
+

This is the default, which just translates the circuit again. +Overwrite in inheritors if parametrized circuits are supported.

+
+ +
+ +
+
+class tequila_code.simulators.simulator_symbolic.BackendExpectationValueSymbolic(E, variables, noise, device, *args, **kwargs)[source]
+

Bases: BackendExpectationValue

+
+
+BackendCircuitType
+

alias of BackendCircuitSymbolic

+
+ +
+ +
+
+

Module contents

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/research.html b/research.html index de8e8c0..8a302e9 100644 --- a/research.html +++ b/research.html @@ -211,7 +211,7 @@
Categories
-
+
@@ -249,7 +249,7 @@

-
+
@@ -290,7 +290,7 @@

-
+
@@ -325,7 +325,7 @@

-
+
diff --git a/sitemap.xml b/sitemap.xml index d3499b1..dbb5e54 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,78 +2,78 @@ https://github.com/tequilahub/tequila-tutorials/index.html - 2024-10-25T15:40:26.434Z + 2024-11-15T14:43:35.305Z https://github.com/tequilahub/tequila-tutorials/FAQ/FAQ.html - 2024-10-25T15:40:25.794Z + 2024-11-15T14:43:34.669Z https://github.com/tequilahub/tequila-tutorials/Tutorials/QTensor/QTensor.html - 2024-10-25T15:40:20.366Z + 2024-11-15T14:43:29.165Z https://github.com/tequilahub/tequila-tutorials/Tutorials/CircuitCompiler/CircuitCompiler.html - 2024-10-25T15:40:19.474Z + 2024-11-15T14:43:28.257Z https://github.com/tequilahub/tequila-tutorials/Tutorials/tq-get-started/index.html - 2024-10-25T15:40:18.178Z + 2024-11-15T14:43:26.929Z https://github.com/tequilahub/tequila-tutorials/Tutorials/AdaptiveMethods/jupyter_notebook.html - 2024-10-25T15:40:12.402Z + 2024-11-15T14:43:21.037Z https://github.com/tequilahub/tequila-tutorials/tutorials.html - 2024-10-25T15:40:08.850Z + 2024-11-15T14:43:16.797Z https://github.com/tequilahub/tequila-tutorials/research.html - 2024-10-25T15:40:07.342Z + 2024-11-15T14:43:15.253Z https://github.com/tequilahub/tequila-tutorials/Researches/electronic-hamiltonians/index.html - 2024-10-25T15:40:04.714Z + 2024-11-15T14:43:12.641Z https://github.com/tequilahub/tequila-tutorials/Researches/molcirc/index.html - 2024-10-25T15:39:03.125Z + 2024-11-15T14:42:03.373Z https://github.com/tequilahub/tequila-tutorials/Researches/Eigensolver/Eigensolver.html - 2024-10-25T15:39:59.102Z + 2024-11-15T14:43:07.069Z https://github.com/tequilahub/tequila-tutorials/Researches/quantum_classifier/quantum_classifier.html - 2024-10-25T15:40:06.286Z + 2024-11-15T14:43:14.189Z https://github.com/tequilahub/tequila-tutorials/Contribution/Contribution.html - 2024-10-25T15:40:07.714Z + 2024-11-15T14:43:15.621Z https://github.com/tequilahub/tequila-tutorials/Tutorials/optimizer/Optimizers.html - 2024-10-25T15:40:09.950Z + 2024-11-15T14:43:17.925Z https://github.com/tequilahub/tequila-tutorials/Tutorials/KrylovTutorial/KrylovTutorial.html - 2024-10-25T15:40:12.862Z + 2024-11-15T14:43:21.493Z https://github.com/tequilahub/tequila-tutorials/Tutorials/Braket/BraketTutorial.html - 2024-10-25T15:40:18.974Z + 2024-11-15T14:43:27.749Z https://github.com/tequilahub/tequila-tutorials/Tutorials/OpenQASMConversions/OpenQASMConversions.html - 2024-10-25T15:40:19.934Z + 2024-11-15T14:43:28.733Z https://github.com/tequilahub/tequila-tutorials/Tutorials/tq-circuits/index.html - 2024-10-25T15:40:25.250Z + 2024-11-15T14:43:34.117Z https://github.com/tequilahub/tequila-tutorials/FAQ.html - 2024-10-25T15:40:26.118Z + 2024-11-15T14:43:34.993Z diff --git a/tutorials.html b/tutorials.html index 9e8fc8b..6ff69eb 100644 --- a/tutorials.html +++ b/tutorials.html @@ -211,7 +211,7 @@
Categories
-
+
@@ -246,7 +246,7 @@

-
+
@@ -281,7 +281,7 @@

-
+
@@ -316,7 +316,7 @@

-
+
@@ -351,7 +351,7 @@

-
+
@@ -386,7 +386,7 @@

-
+
@@ -421,7 +421,7 @@

-
+
@@ -457,7 +457,7 @@

-
+
@@ -492,7 +492,7 @@

-
+