{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Parameter Labels\n",
    "This tutorials show how model parameters are labelled, and how this can be used to create more complex parameterizations for a model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pygsti\n",
    "import numpy as np\n",
    "from pygsti.modelpacks import smq1Q_XY as std\n",
    "from pygsti.baseobjs import Label\n",
    "\n",
    "mdl1 = std.target_model(\"H+s\")  # choose a H+s model because it has a simple parameterization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting parameter labels\n",
    "A `Model`'s parameters have corresponding labels, which can be accessed in a variety of ways.  Individual operators also have labeled parameters.  An `OpModel` (e.g. an `ExplicitModel` or `ImplicitModel`) sets default parameter labels based on the parameter labels of its contained operators, but the model's parameters can vary independently."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print the raw labels, straight up\n",
    "mdl1.parameter_labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# model parameters can be set to arbitrary user-defined values\n",
    "mdl1.set_parameter_label(index=0, label=\"My favorite parameter\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Model parameters in a nice format for printing\n",
    "mdl1.parameter_labels_pretty"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# For a single operator: you can get it's \"local\" parameter labels (in general different from the model's parameter labels)\n",
    "mdl1.operations[('Gxpi2',0)].parameter_labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# The parameters of all the operators, with mappings to non-default model parameters \n",
    "mdl1.print_parameters_by_op()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Collecting parameters\n",
    "You can combined multiple parameters into one using the `collect_parameters` method.  This effectively ties the values for all the original parameters together."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mdl1.collect_parameters([ (('Gxpi2',0), 'X Hamiltonian error coefficient'),\n",
    "                          (('Gypi2',0), 'Y Hamiltonian error coefficient')],\n",
    "                        new_param_label='Over-rotation')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Using \"pretty\" labels works too:\n",
    "mdl1.collect_parameters(['Gxpi2:0: Y stochastic coefficient',\n",
    "                         'Gxpi2:0: Z stochastic coefficient' ],\n",
    "                        new_param_label='Gxpi2 off-axis stochastic')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# You can also use integer indices, and parameter labels can be tuples too.\n",
    "mdl1.collect_parameters([3,4,5], new_param_label=(\"rho0\", \"common stochastic coefficient\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# There are now fewer parameters\n",
    "mdl1.parameter_labels_pretty"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# And you can see how they're wired up for each op:\n",
    "mdl1.print_parameters_by_op()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Un-collecting parameters\n",
    "You can also reverse the above process and \"un-collect\" a parameter so that one parameter gets replaced my multiple independent ones."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mdl1.uncollect_parameters('Gxpi2 off-axis stochastic')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mdl1.print_parameters_by_op()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
