examples/Parametermap.ipynb
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Parameter handling\n",
"The tool within $C^3$ to manipulate the parameters of both the model and controls is the `ParameterMap`. It provides methods to present the same data for human interaction, i.e. structured information with physical units and for numerical optimization algorithms that prefer a linear vector of scale 1. Here, we'll show some example usage.\n",
"We'll use the `ParameterMap` of the model also used in the simulated calibration example."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from single_qubit_blackbox_exp import create_experiment\n",
"\n",
"exp = create_experiment()\n",
"pmap = exp.pmap"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The pmap contains a list of all parameters and their values:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'Q1-freq': 5.000 GHz 2pi,\n",
" 'Q1-anhar': -210.000 MHz 2pi,\n",
" 'Q1-temp': 0.000 K,\n",
" 'init_ground-init_temp': -3.469 aK,\n",
" 'resp-rise_time': 300.000 ps,\n",
" 'v_to_hz-V_to_Hz': 1.000 GHz/V,\n",
" 'id[0]-d1-no_drive-amp': 1.000 V,\n",
" 'id[0]-d1-no_drive-delta': 0.000 V,\n",
" 'id[0]-d1-no_drive-freq_offset': 0.000 Hz 2pi,\n",
" 'id[0]-d1-no_drive-xy_angle': 0.000 rad,\n",
" 'id[0]-d1-no_drive-sigma': 5.000 ns,\n",
" 'id[0]-d1-no_drive-t_final': 7.000 ns,\n",
" 'id[0]-d1-carrier-freq': 5.050 GHz 2pi,\n",
" 'id[0]-d1-carrier-framechange': 5.933 rad,\n",
" 'rx90p[0]-d1-gauss-amp': 450.000 mV,\n",
" 'rx90p[0]-d1-gauss-delta': -1.000 ,\n",
" 'rx90p[0]-d1-gauss-freq_offset': -50.500 MHz 2pi,\n",
" 'rx90p[0]-d1-gauss-xy_angle': -444.089 arad,\n",
" 'rx90p[0]-d1-gauss-sigma': 1.750 ns,\n",
" 'rx90p[0]-d1-gauss-t_final': 7.000 ns,\n",
" 'rx90p[0]-d1-carrier-freq': 5.050 GHz 2pi,\n",
" 'rx90p[0]-d1-carrier-framechange': 0.000 rad,\n",
" 'ry90p[0]-d1-gauss-amp': 450.000 mV,\n",
" 'ry90p[0]-d1-gauss-delta': -1.000 ,\n",
" 'ry90p[0]-d1-gauss-freq_offset': -50.500 MHz 2pi,\n",
" 'ry90p[0]-d1-gauss-xy_angle': 1.571 rad,\n",
" 'ry90p[0]-d1-gauss-sigma': 1.750 ns,\n",
" 'ry90p[0]-d1-gauss-t_final': 7.000 ns,\n",
" 'ry90p[0]-d1-carrier-freq': 5.050 GHz 2pi,\n",
" 'ry90p[0]-d1-carrier-framechange': 0.000 rad,\n",
" 'rx90m[0]-d1-gauss-amp': 450.000 mV,\n",
" 'rx90m[0]-d1-gauss-delta': -1.000 ,\n",
" 'rx90m[0]-d1-gauss-freq_offset': -50.500 MHz 2pi,\n",
" 'rx90m[0]-d1-gauss-xy_angle': 3.142 rad,\n",
" 'rx90m[0]-d1-gauss-sigma': 1.750 ns,\n",
" 'rx90m[0]-d1-gauss-t_final': 7.000 ns,\n",
" 'rx90m[0]-d1-carrier-freq': 5.050 GHz 2pi,\n",
" 'rx90m[0]-d1-carrier-framechange': 0.000 rad,\n",
" 'ry90m[0]-d1-gauss-amp': 450.000 mV,\n",
" 'ry90m[0]-d1-gauss-delta': -1.000 ,\n",
" 'ry90m[0]-d1-gauss-freq_offset': -50.500 MHz 2pi,\n",
" 'ry90m[0]-d1-gauss-xy_angle': 4.712 rad,\n",
" 'ry90m[0]-d1-gauss-sigma': 1.750 ns,\n",
" 'ry90m[0]-d1-gauss-t_final': 7.000 ns,\n",
" 'ry90m[0]-d1-carrier-freq': 5.050 GHz 2pi,\n",
" 'ry90m[0]-d1-carrier-framechange': 0.000 rad}"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_full_params()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To access a specific parameter, e.g. the frequency of qubit 1, we use the identifying tuple `('Q1','freq')`."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5.000 GHz 2pi"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameter(('Q1','freq'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The opt_map\n",
"To deal with multiple parameters we use the `opt_map`, a nested list of identifyers."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"opt_map = [\n",
" [\n",
" (\"Q1\", \"freq\")\n",
" ],\n",
" [\n",
" (\"Q1\", \"anhar\")\n",
" ], \n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, we get a list of the parameter values:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[5.000 GHz 2pi, -210.000 MHz 2pi]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameters(opt_map)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's look at the amplitude values of two gaussian control pulses, rotations about the $X$ and $Y$ axes repsectively."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"opt_map = [\n",
" [\n",
" ('rx90p[0]','d1','gauss','amp')\n",
" ],\n",
" [\n",
" ('ry90p[0]','d1','gauss','amp')\n",
" ], \n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[450.000 mV, 450.000 mV]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameters(opt_map)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can set the parameters to new values."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"pmap.set_parameters([0.5, 0.6], opt_map)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[500.000 mV, 600.000 mV]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameters(opt_map)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The opt_map also allows us to specify that two parameters should have identical values. Here, let's demand our $X$ and $Y$ rotations use the same amplitude."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"opt_map_ident = [\n",
" [\n",
" ('rx90p[0]','d1','gauss','amp'),\n",
" ('ry90p[0]','d1','gauss','amp')\n",
" ],\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The grouping here means that these parameters share their numerical value."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[432.000 mV]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.set_parameters([0.432], opt_map_ident)\n",
"pmap.get_parameters(opt_map_ident)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[432.000 mV, 432.000 mV]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameters(opt_map)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"During an optimization, the varied parameters do not change, so we fix the opt_map"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"pmap.set_opt_map(opt_map)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[432.000 mV, 432.000 mV]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameters()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Optimizer scaling\n",
"To be independent of the choice of numerical optimizer, they should use the methods"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([-0.68, -0.68])"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameters_scaled()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To provide values bound to $[-1, 1]$. Let's set the parameters to their allowed minimum an maximum value with"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"pmap.set_parameters_scaled([1.0,-1.0])"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[600.000 mV, 400.000 mV]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameters()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As a safeguard, when setting values outside of the unit range, their physical values get looped back in the specified limits."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"pmap.set_parameters_scaled([2.0, 3.0])"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[500.000 mV, 400.000 mV]"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pmap.get_parameters()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Storing and reading\n",
"For optimization purposes, we can store and load parameter values in [HJSON](https://hjson.github.io/) format."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"pmap.store_values(\"current_vals.c3log\")"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\r\n",
" opt_map:\r\n",
" [\r\n",
" [\r\n",
" rx90p[0]-d1-gauss-amp\r\n",
" ]\r\n",
" [\r\n",
" ry90p[0]-d1-gauss-amp\r\n",
" ]\r\n",
" ]\r\n",
" units:\r\n",
" [\r\n",
" V\r\n",
" V\r\n",
" ]\r\n",
" optim_status:\r\n",
" {\r\n",
" params:\r\n",
" [\r\n",
" 0.5\r\n",
" 0.4000000059604645\r\n",
" ]\r\n",
" }\r\n",
"}\r\n"
]
}
],
"source": [
"!cat current_vals.c3log"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"pmap.load_values(\"current_vals.c3log\")"
]
}
],
"metadata": {
"interpreter": {
"hash": "8fc56ae400e717d872a76f4d6b257151d16696a9d0a72e6998d355f9b43887c7"
},
"kernelspec": {
"display_name": "Python 3",
"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.8"
}
},
"nbformat": 4,
"nbformat_minor": 4
}