├── Install.nb ├── LICENSE.txt ├── README.md ├── doc ├── api-doc │ ├── ControlTheory.nb │ ├── GRAPE.nb │ ├── LindbladSolver.nb │ ├── M2M.nb │ ├── Perturbation.nb │ ├── Predicates.nb │ ├── QSim.nb │ ├── QUTesting.nb │ ├── QuantumChannel.nb │ ├── QuantumSystems.nb │ ├── Tensor.nb │ └── Visualization.nb ├── dev-guide │ ├── QUDevTools.m │ └── package-template.nb └── index.nb ├── src ├── ControlTheory.m ├── GRAPE.m ├── LindbladSolver.m ├── M2M.m ├── Perturbation.m ├── Predicates.m ├── QSim.m ├── QUDevTools.m ├── QUDoc.m ├── QUTesting.m ├── QuantumChannel.m ├── QuantumSystems.m ├── QuantumUtils.m ├── Tensor.m ├── Visualization.m └── pylink │ ├── __init__.py │ └── grammar.py └── test ├── ControlTheoryTests.m ├── GRAPETests.m ├── LindbladSolverTests.m ├── M2MTests.m ├── PerturbationTests.m ├── PredicatesTests.m ├── QSimTests.m ├── QuantumChannelTests.m ├── QuantumSystemsTests.m ├── TensorTests.m ├── VisualizationTests.m └── test.m /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks 2 | 3 | Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met: 4 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 5 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 6 | 3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 7 | 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuantumUtils for Mathematica 2 | 3 | QuantumUtils for Mathematica is a software library for quantum information scientists. Features include: 4 | 5 | - Multi-partite tensor manipulations 6 | - Quantum system modelling including qudits, circuits, spins, and cavities 7 | - Symbolic Lie algebra simplification for spin and cavity systems 8 | - Quantum channels in multiple representations 9 | - Numerical and symbolic simulators for open and closed quantum system evolution 10 | - An implementation of GRadient Ascent Pulse Engineering including distortions 11 | - Perturbative expansion tools such as the Magnus series, the Zassenhaus formula, and matrix power series 12 | - Visualization functions for displaying matrices, quantum states, data etc. 13 | 14 | ## Requirements 15 | 16 | QuantumUtils officially requires Mathematica 10.0.0 or newer. Most features should work with Mathematica 9, and full compatibility with Mathematica 9 will be added in the future. Older versions of Mathematica are not supported. 17 | 18 | ## Installation 19 | 20 | Once this repository is cloned onto your computer, open the *Install.nb* notebook in Mathematica and follow instructions there (basically just *Evaluation -> Evaluate Notebook*). 21 | 22 | The installation places and/or symlinks files in your *`$UserBaseDirectory`/Applications* folder. 23 | 24 | QuantumUtils includes a suite of unit tests to check if the installed packages are running correctly. After installation these tests can be accesed from the package `QUTesting` by running the commands: 25 | 26 | Needs["QUTesting`"]; 27 | RunAllTests[] 28 | 29 | ## Using QuantumUtils for Mathematica 30 | 31 | Packages from the QuantumUtils for Mathematica library can be loaded by invoking the `Needs` function, for example: 32 | 33 | Needs["QuantumChannel`"]; 34 | 35 | All packages provided by QuantumUtils for Mathematica can be loaded simultaneously by needsing QuantumUtils`: 36 | 37 | Needs["QuantumUtils`"] 38 | 39 | ## Documentation 40 | 41 | **It is highly recommended that the icon for opening/closing cell groups be enabled. This makes it easy to expand and contract sections in the documentation notebooks. This option can be found in the Interface tab of the Preferences window (Edit>Preferences in Windows/Linux, Mathematica>Preferences in MacOS).** 42 | 43 | Documentation is stored as *.nb* notebooks in the *doc* folder. The documentation index can be opened from within Mathematica at any time by evaluating: 44 | 45 | <Normal*) 18 | 19 | (* Beginning of Notebook Content *) 20 | Notebook[{ 21 | 22 | Cell[CellGroupData[{ 23 | Cell["QUTesting` Documentation", "Chapter", 24 | CellChangeTimes->{{3.6333515346579514`*^9, 3.63335154627586*^9}, { 25 | 3.633364320690548*^9, 3.63336432261762*^9}, {3.633459692992848*^9, 26 | 3.633459695695156*^9}, {3.63352627649533*^9, 3.633526278958379*^9}, { 27 | 3.636901374637114*^9, 3.636901375728097*^9}}], 28 | 29 | Cell[CellGroupData[{ 30 | 31 | Cell["Preamble", "Section", 32 | CellChangeTimes->{{3.633351558518317*^9, 3.633351560041299*^9}, { 33 | 3.633781254199301*^9, 3.633781256261158*^9}}], 34 | 35 | Cell[BoxData[ 36 | RowBox[{"Needs", "[", "\"\\"", "]"}]], "Input", 37 | CellChangeTimes->{{3.633351696261045*^9, 3.633351701530016*^9}, { 38 | 3.633459703938384*^9, 3.633459707396385*^9}, {3.633526282103736*^9, 39 | 3.633526283991441*^9}, {3.636901378415098*^9, 3.636901380048747*^9}}] 40 | }, Open ]], 41 | 42 | Cell[CellGroupData[{ 43 | 44 | Cell["Introduction and Overview", "Section", 45 | CellChangeTimes->{{3.633351563673402*^9, 3.633351567143589*^9}, { 46 | 3.633878695511993*^9, 3.633878696655075*^9}}], 47 | 48 | Cell["\<\ 49 | This package contains functions to run the unit tests for the various \ 50 | packages in QuantumUtils. This can be used to check the installation, and to \ 51 | check if everything still works after making modifications to the code.\ 52 | \>", "Text", 53 | CellChangeTimes->{{3.6369013984973183`*^9, 3.636901432406*^9}}] 54 | }, Open ]], 55 | 56 | Cell[CellGroupData[{ 57 | 58 | Cell["Unit Tests", "Section", 59 | CellChangeTimes->{{3.63335202563237*^9, 3.6333520385490847`*^9}, { 60 | 3.633441643373975*^9, 3.633441643471745*^9}, {3.633459727021635*^9, 61 | 3.633459727820011*^9}, {3.633526289590464*^9, 3.6335262930624027`*^9}, { 62 | 3.63378126135916*^9, 3.633781261452849*^9}, {3.6369014438326187`*^9, 63 | 3.636901452273589*^9}}], 64 | 65 | Cell[CellGroupData[{ 66 | 67 | Cell["TestResults", "Subsection", 68 | CellChangeTimes->{{3.63690145452*^9, 3.6369014577181673`*^9}}], 69 | 70 | Cell[TextData[{ 71 | StyleBox["TestResults[\[OpenCurlyDoubleQuote]", "Input"], 72 | StyleBox["name\[CloseCurlyDoubleQuote]", "Input", 73 | FontWeight->"Plain", 74 | FontSlant->"Italic"], 75 | StyleBox["]", "Input"], 76 | " returns the results of the unit tests for ", 77 | StyleBox["QuantumUtils", 78 | FontSlant->"Italic"], 79 | " package ", 80 | StyleBox["name.m", "Input", 81 | FontWeight->"Plain", 82 | FontSlant->"Italic"], 83 | StyleBox[". These are returned as a list of rules ", 84 | FontWeight->"Plain"], 85 | StyleBox["\[OpenCurlyDoubleQuote]", "Input"], 86 | StyleBox["TestName", "Input", 87 | FontWeight->"Plain", 88 | FontSlant->"Italic"], 89 | StyleBox["\[CloseCurlyDoubleQuote]\[Rule]", "Input"], 90 | StyleBox["T/F/E", "Input", 91 | FontWeight->"Plain", 92 | FontSlant->"Italic"], 93 | StyleBox[",", 94 | FontWeight->"Plain"], 95 | " where result is \[OpenCurlyDoubleQuote]T\[CloseCurlyDoubleQuote] if the \ 96 | test succeeded, \[OpenCurlyDoubleQuote]F\[CloseCurlyDoubleQuote] if the test \ 97 | failed, or \[OpenCurlyDoubleQuote]E\[CloseCurlyDoubleQuote] if the test \ 98 | returned an error and failed to evaluate to True or False.\n\n", 99 | StyleBox["TestResults[]", "Input"], 100 | " returns the results of the unit tests for all ", 101 | StyleBox["QuantumUtils", 102 | FontSlant->"Italic"], 103 | " packages." 104 | }], "Text", 105 | CellDingbat->"\[FilledSquare]", 106 | CellChangeTimes->{ 107 | 3.634311328002417*^9, {3.634316418526174*^9, 3.634316521790423*^9}, { 108 | 3.634509526888596*^9, 3.634509548646995*^9}, {3.634924751102474*^9, 109 | 3.634924781111176*^9}, {3.6349258561999493`*^9, 3.6349259526860847`*^9}, { 110 | 3.634926269549931*^9, 3.6349262813179913`*^9}, {3.634989908112784*^9, 111 | 3.634989908825219*^9}, {3.636901524340518*^9, 3.636901768172884*^9}}, 112 | CellTags->"TestResults::usage"], 113 | 114 | Cell[CellGroupData[{ 115 | 116 | Cell["Example", "Subsubsection", 117 | CellChangeTimes->{{3.636901500668826*^9, 3.636901501457987*^9}}], 118 | 119 | Cell[CellGroupData[{ 120 | 121 | Cell[BoxData[ 122 | RowBox[{ 123 | RowBox[{"TestResults", "[", "\"\\"", "]"}], "//", 124 | "MatrixForm"}]], "Input", 125 | CellChangeTimes->{{3.636901505101733*^9, 3.636901514385421*^9}, { 126 | 3.6369023547295713`*^9, 3.6369023553894663`*^9}}], 127 | 128 | Cell[BoxData[ 129 | TagBox[ 130 | RowBox[{"(", "\[NoBreak]", 131 | TagBox[GridBox[{ 132 | { 133 | RowBox[{"\<\"Tensor:CircleTimes\"\>", "\[Rule]", "\<\"T\"\>"}]}, 134 | { 135 | RowBox[{"\<\"Tensor:\[DoubleStruckOne]\"\>", 136 | "\[Rule]", "\<\"T\"\>"}]}, 137 | { 138 | RowBox[{"\<\"Tensor:BlockMatrix\"\>", "\[Rule]", "\<\"T\"\>"}]}, 139 | { 140 | RowBox[{"\<\"Tensor:UnitArray\"\>", "\[Rule]", "\<\"T\"\>"}]}, 141 | { 142 | RowBox[{"\<\"Tensor:TensorFactorPermutations\"\>", 143 | "\[Rule]", "\<\"T\"\>"}]}, 144 | { 145 | RowBox[{"\<\"Tensor:SwapMatrix\"\>", "\[Rule]", "\<\"T\"\>"}]}, 146 | { 147 | RowBox[{"\<\"Tensor:Com\"\>", "\[Rule]", "\<\"T\"\>"}]}, 148 | { 149 | RowBox[{"\<\"Tensor:ACom\"\>", "\[Rule]", "\<\"T\"\>"}]}, 150 | { 151 | RowBox[{"\<\"Tensor:OuterProduct\"\>", "\[Rule]", "\<\"T\"\>"}]}, 152 | { 153 | RowBox[{"\<\"Tensor:Projector\"\>", "\[Rule]", "\<\"T\"\>"}]}, 154 | { 155 | RowBox[{"\<\"Tensor:MatrixToTensor\"\>", "\[Rule]", "\<\"T\"\>"}]}, 156 | { 157 | RowBox[{"\<\"Tensor:MatrixTranspose\"\>", "\[Rule]", "\<\"T\"\>"}]}, 158 | { 159 | RowBox[{"\<\"Tensor:Swap\"\>", "\[Rule]", "\<\"T\"\>"}]}, 160 | { 161 | RowBox[{"\<\"Tensor:Reshuffle\"\>", "\[Rule]", "\<\"T\"\>"}]}, 162 | { 163 | RowBox[{"\<\"Tensor:Unravel\"\>", "\[Rule]", "\<\"T\"\>"}]}, 164 | { 165 | RowBox[{"\<\"Tensor:Reravel\"\>", "\[Rule]", "\<\"T\"\>"}]}, 166 | { 167 | RowBox[{"\<\"Tensor:PartialTr\"\>", "\[Rule]", "\<\"T\"\>"}]}, 168 | { 169 | RowBox[{"\<\"Tensor:TensorPairContract\"\>", 170 | "\[Rule]", "\<\"T\"\>"}]}, 171 | { 172 | RowBox[{"\<\"Tensor:MatrixContract\"\>", "\[Rule]", "\<\"T\"\>"}]}, 173 | { 174 | RowBox[{"\<\"Tensor:MatrixPairContract\"\>", 175 | "\[Rule]", "\<\"T\"\>"}]}, 176 | { 177 | RowBox[{"\<\"Tensor:Basis\"\>", "\[Rule]", "\<\"T\"\>"}]}, 178 | { 179 | RowBox[{"\<\"Tensor:BasisLabels\"\>", "\[Rule]", "\<\"T\"\>"}]}, 180 | { 181 | RowBox[{"\<\"Tensor:ExpressInBasis\"\>", "\[Rule]", "\<\"T\"\>"}]}, 182 | { 183 | RowBox[{"\<\"Tensor:Vec\"\>", "\[Rule]", "\<\"T\"\>"}]}, 184 | { 185 | RowBox[{"\<\"Tensor:Devec\"\>", "\[Rule]", "\<\"T\"\>"}]}, 186 | { 187 | RowBox[{"\<\"Tensor:ProductIdentity\"\>", "\[Rule]", "\<\"T\"\>"}]}, 188 | { 189 | RowBox[{"\<\"Tensor:BasisMatrix\"\>", "\[Rule]", "\<\"T\"\>"}]}, 190 | { 191 | RowBox[{"\<\"Tensor:BasisTransformation\"\>", "\[Rule]", "\<\"T\"\>"}]}, 192 | { 193 | RowBox[{"\<\"Tensor:TP\"\>", "\[Rule]", "\<\"T\"\>"}]} 194 | }, 195 | GridBoxAlignment->{ 196 | "Columns" -> {{Center}}, "ColumnsIndexed" -> {}, "Rows" -> {{Baseline}}, 197 | "RowsIndexed" -> {}}, 198 | GridBoxSpacings->{"Columns" -> { 199 | Offset[0.27999999999999997`], { 200 | Offset[0.5599999999999999]}, 201 | Offset[0.27999999999999997`]}, "ColumnsIndexed" -> {}, "Rows" -> { 202 | Offset[0.2], { 203 | Offset[0.4]}, 204 | Offset[0.2]}, "RowsIndexed" -> {}}], 205 | Column], "\[NoBreak]", ")"}], 206 | Function[BoxForm`e$, 207 | MatrixForm[BoxForm`e$]]]], "Output", 208 | CellChangeTimes->{{3.6369015104258537`*^9, 3.636901514774818*^9}, 209 | 3.636902355805007*^9}] 210 | }, Open ]] 211 | }, Open ]] 212 | }, Open ]], 213 | 214 | Cell[CellGroupData[{ 215 | 216 | Cell["RunAllTests", "Subsection", 217 | CellChangeTimes->{{3.6335265055504847`*^9, 3.633526507574844*^9}}], 218 | 219 | Cell[TextData[{ 220 | StyleBox["RunAllTests[]", "Input"], 221 | " runs all ", 222 | StyleBox["QuantumUtils", 223 | FontSlant->"Italic"], 224 | " unit tests and reports on how many succeeded, failed, or returned errors." 225 | }], "Text", 226 | CellChangeTimes->{ 227 | 3.6338786671801777`*^9, {3.636901797949497*^9, 3.636901835178047*^9}}, 228 | CellTags->"RunAllTests::usage"], 229 | 230 | Cell[CellGroupData[{ 231 | 232 | Cell["Example", "Subsubsection", 233 | CellChangeTimes->{{3.633526541390602*^9, 3.633526545774642*^9}}], 234 | 235 | Cell[CellGroupData[{ 236 | 237 | Cell[BoxData[ 238 | RowBox[{"RunAllTests", "[", "]"}]], "Input", 239 | CellChangeTimes->{{3.633526546432682*^9, 3.633526549179888*^9}}], 240 | 241 | Cell[BoxData["\<\"209 of 209 unit tests passed.\"\>"], "Print", 242 | CellChangeTimes->{ 243 | 3.63352657177526*^9, 3.6335266248302917`*^9, 3.633526667800214*^9, { 244 | 3.633526701498966*^9, 3.6335267311422577`*^9}, 3.633526763039488*^9, 245 | 3.6335268894276114`*^9, 3.633527022952025*^9, 3.636901838762259*^9}] 246 | }, Open ]] 247 | }, Open ]] 248 | }, Open ]] 249 | }, Open ]] 250 | }, Open ]] 251 | }, 252 | WindowSize->{1280, 1000}, 253 | WindowMargins->{{317, Automatic}, {Automatic, 0}}, 254 | FrontEndVersion->"10.0 for Mac OS X x86 (32-bit, 64-bit Kernel) (December 4, \ 255 | 2014)", 256 | StyleDefinitions->"Default.nb" 257 | ] 258 | (* End of Notebook Content *) 259 | 260 | (* Internal cache information *) 261 | (*CellTagsOutline 262 | CellTagsIndex->{ 263 | "RunAllTests::usage"->{ 264 | Cell[7612, 218, 333, 9, 31, "Text", 265 | CellTags->"RunAllTests::usage"]}, 266 | "TestResults::usage"->{ 267 | Cell[2349, 69, 1672, 42, 89, "Text", 268 | CellTags->"TestResults::usage"]} 269 | } 270 | *) 271 | (*CellTagsIndex 272 | CellTagsIndex->{ 273 | {"RunAllTests::usage", 8903, 262}, 274 | {"TestResults::usage", 9003, 265} 275 | } 276 | *) 277 | (*NotebookFileOutline 278 | Notebook[{ 279 | Cell[CellGroupData[{ 280 | Cell[580, 22, 301, 4, 65, "Chapter"], 281 | Cell[CellGroupData[{ 282 | Cell[906, 30, 142, 2, 64, "Section"], 283 | Cell[1051, 34, 285, 4, 28, "Input"] 284 | }, Open ]], 285 | Cell[CellGroupData[{ 286 | Cell[1373, 43, 159, 2, 64, "Section"], 287 | Cell[1535, 47, 311, 5, 49, "Text"] 288 | }, Open ]], 289 | Cell[CellGroupData[{ 290 | Cell[1883, 57, 341, 5, 64, "Section"], 291 | Cell[CellGroupData[{ 292 | Cell[2249, 66, 97, 1, 44, "Subsection"], 293 | Cell[2349, 69, 1672, 42, 89, "Text", 294 | CellTags->"TestResults::usage"], 295 | Cell[CellGroupData[{ 296 | Cell[4046, 115, 98, 1, 35, "Subsubsection"], 297 | Cell[CellGroupData[{ 298 | Cell[4169, 120, 232, 5, 28, "Input"], 299 | Cell[4404, 127, 3043, 81, 510, "Output"] 300 | }, Open ]] 301 | }, Open ]] 302 | }, Open ]], 303 | Cell[CellGroupData[{ 304 | Cell[7508, 215, 101, 1, 44, "Subsection"], 305 | Cell[7612, 218, 333, 9, 31, "Text", 306 | CellTags->"RunAllTests::usage"], 307 | Cell[CellGroupData[{ 308 | Cell[7970, 231, 98, 1, 35, "Subsubsection"], 309 | Cell[CellGroupData[{ 310 | Cell[8093, 236, 125, 2, 28, "Input"], 311 | Cell[8221, 240, 299, 4, 22, "Print"] 312 | }, Open ]] 313 | }, Open ]] 314 | }, Open ]] 315 | }, Open ]] 316 | }, Open ]] 317 | } 318 | ] 319 | *) 320 | 321 | (* End of internal cache information *) 322 | -------------------------------------------------------------------------------- /doc/index.nb: -------------------------------------------------------------------------------- 1 | (* Content-type: application/vnd.wolfram.mathematica *) 2 | 3 | (*** Wolfram Notebook File ***) 4 | (* http://www.wolfram.com/nb *) 5 | 6 | (* CreatedBy='Mathematica 10.0' *) 7 | 8 | (*CacheID: 234*) 9 | (* Internal cache information: 10 | NotebookFileLineBreakTest 11 | NotebookFileLineBreakTest 12 | NotebookDataPosition[ 158, 7] 13 | NotebookDataLength[ 16451, 481] 14 | NotebookOptionsPosition[ 15560, 449] 15 | NotebookOutlinePosition[ 15903, 464] 16 | CellTagsIndexPosition[ 15860, 461] 17 | WindowFrame->Normal*) 18 | 19 | (* Beginning of Notebook Content *) 20 | Notebook[{ 21 | 22 | Cell[CellGroupData[{ 23 | Cell["Quantum Utils Documentation", "Chapter", 24 | CellChangeTimes->{{3.633439785011228*^9, 3.633439797185196*^9}}], 25 | 26 | Cell[TextData[{ 27 | "To more easily navigate this documentation, it is advised that you check \ 28 | the ", 29 | StyleBox["\[OpenCurlyDoubleQuote]Show open/close icon for cell groups\ 30 | \[CloseCurlyDoubleQuote]", 31 | FontSlant->"Italic"], 32 | " checkbox in the ", 33 | StyleBox["Edit > Preferences > Interface", 34 | FontSlant->"Italic"], 35 | " dialog." 36 | }], "Text", 37 | CellChangeTimes->{{3.63344027560156*^9, 3.633440378911942*^9}, { 38 | 3.633782637054619*^9, 3.633782637973031*^9}}], 39 | 40 | Cell[CellGroupData[{ 41 | 42 | Cell["Quantum Utils Packages", "Section", 43 | CellChangeTimes->{{3.633439803464673*^9, 3.633439816454121*^9}, { 44 | 3.633714165568389*^9, 3.6337141717213373`*^9}, {3.6337828870995502`*^9, 45 | 3.633782887211052*^9}, {3.635111763845348*^9, 3.635111763937435*^9}}], 46 | 47 | Cell[BoxData[GridBox[{ 48 | { 49 | StyleBox[ 50 | TagBox[ 51 | ButtonBox[ 52 | PaneSelectorBox[{False->"\<\"ControlTheory\"\>", True-> 53 | StyleBox["\<\"ControlTheory\"\>", "HyperlinkActive"]}, Dynamic[ 54 | CurrentValue["MouseOver"]], 55 | BaseStyle->{"Hyperlink"}, 56 | FrameMargins->0, 57 | ImageSize->Automatic], 58 | BaseStyle->"Hyperlink", 59 | ButtonData:>{"api-doc/ControlTheory.nb", None}, 60 | ButtonNote->"api-doc/ControlTheory.nb"], 61 | Annotation[#, "api-doc/ControlTheory.nb", "Hyperlink"]& ], "Text", 62 | FontWeight->Bold], 63 | StyleBox[ 64 | RowBox[{ 65 | "A", " ", "package", " ", "of", " ", "tools", " ", "commonly", " ", 66 | "used", " ", "in", " ", "quantum", " ", "control", " ", 67 | RowBox[{"theory", "."}]}], "Text"]} 68 | }, 69 | GridBoxAlignment->{"Columns" -> {{Left}}}, 70 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 71 | GridBoxItemSize->{"Columns" -> { 72 | Scaled[0.15], { 73 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 74 | "RowsIndexed" -> {}}]], "Text", 75 | GeneratedCell->True, 76 | CellAutoOverwrite->True, 77 | CellChangeTimes->{3.636901928644802*^9}], 78 | 79 | Cell[BoxData[GridBox[{ 80 | { 81 | StyleBox[ 82 | TagBox[ 83 | ButtonBox[ 84 | PaneSelectorBox[{False->"\<\"GRAPE\"\>", True-> 85 | StyleBox["\<\"GRAPE\"\>", "HyperlinkActive"]}, Dynamic[ 86 | CurrentValue["MouseOver"]], 87 | BaseStyle->{"Hyperlink"}, 88 | FrameMargins->0, 89 | ImageSize->Automatic], 90 | BaseStyle->"Hyperlink", 91 | ButtonData:>{"api-doc/GRAPE.nb", None}, 92 | ButtonNote->"api-doc/GRAPE.nb"], 93 | Annotation[#, "api-doc/GRAPE.nb", "Hyperlink"]& ], "Text", 94 | FontWeight->Bold], 95 | StyleBox[ 96 | RowBox[{ 97 | "An", " ", "implementation", " ", "of", " ", "GRadient", " ", "Ascent", 98 | " ", "Pulse", " ", 99 | RowBox[{"Engineering", "."}]}], "Text"]} 100 | }, 101 | GridBoxAlignment->{"Columns" -> {{Left}}}, 102 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 103 | GridBoxItemSize->{"Columns" -> { 104 | Scaled[0.15], { 105 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 106 | "RowsIndexed" -> {}}]], "Text", 107 | GeneratedCell->True, 108 | CellAutoOverwrite->True, 109 | CellChangeTimes->{3.636901928709544*^9}], 110 | 111 | Cell[BoxData[GridBox[{ 112 | { 113 | StyleBox[ 114 | TagBox[ 115 | ButtonBox[ 116 | PaneSelectorBox[{False->"\<\"LindbladSolver\"\>", True-> 117 | StyleBox["\<\"LindbladSolver\"\>", "HyperlinkActive"]}, Dynamic[ 118 | CurrentValue["MouseOver"]], 119 | BaseStyle->{"Hyperlink"}, 120 | FrameMargins->0, 121 | ImageSize->Automatic], 122 | BaseStyle->"Hyperlink", 123 | ButtonData:>{"api-doc/LindbladSolver.nb", None}, 124 | ButtonNote->"api-doc/LindbladSolver.nb"], 125 | Annotation[#, "api-doc/LindbladSolver.nb", "Hyperlink"]& ], "Text", 126 | FontWeight->Bold], 127 | StyleBox[ 128 | RowBox[{ 129 | "A", " ", "set", " ", "of", " ", "functions", " ", "for", " ", 130 | "numerically", " ", "or", " ", "symbolically", " ", "solving", " ", 131 | "Schrodinger", " ", "equations", " ", "and", " ", "Lindblad", " ", 132 | "master", " ", 133 | RowBox[{"equations", "."}]}], "Text"]} 134 | }, 135 | GridBoxAlignment->{"Columns" -> {{Left}}}, 136 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 137 | GridBoxItemSize->{"Columns" -> { 138 | Scaled[0.15], { 139 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 140 | "RowsIndexed" -> {}}]], "Text", 141 | GeneratedCell->True, 142 | CellAutoOverwrite->True, 143 | CellChangeTimes->{3.6369019287891293`*^9}], 144 | 145 | Cell[BoxData[GridBox[{ 146 | { 147 | StyleBox[ 148 | TagBox[ 149 | ButtonBox[ 150 | PaneSelectorBox[{False->"\<\"M2M\"\>", True-> 151 | StyleBox["\<\"M2M\"\>", "HyperlinkActive"]}, Dynamic[ 152 | CurrentValue["MouseOver"]], 153 | BaseStyle->{"Hyperlink"}, 154 | FrameMargins->0, 155 | ImageSize->Automatic], 156 | BaseStyle->"Hyperlink", 157 | ButtonData:>{"api-doc/M2M.nb", None}, 158 | ButtonNote->"api-doc/M2M.nb"], 159 | Annotation[#, "api-doc/M2M.nb", "Hyperlink"]& ], "Text", 160 | FontWeight->Bold], 161 | StyleBox[ 162 | RowBox[{ 163 | "Code", " ", "generation", " ", "functions", " ", "for", " ", 164 | "exporting", " ", "to", " ", 165 | RowBox[{"MATLAB", "."}]}], "Text"]} 166 | }, 167 | GridBoxAlignment->{"Columns" -> {{Left}}}, 168 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 169 | GridBoxItemSize->{"Columns" -> { 170 | Scaled[0.15], { 171 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 172 | "RowsIndexed" -> {}}]], "Text", 173 | CellChangeTimes->{ 174 | 3.6369019287891293`*^9, {3.6374656696800904`*^9, 3.6374656774095635`*^9}}], 175 | 176 | Cell[BoxData[GridBox[{ 177 | { 178 | StyleBox[ 179 | TagBox[ 180 | ButtonBox[ 181 | PaneSelectorBox[{False->"\<\"Perturbation\"\>", True-> 182 | StyleBox["\<\"Perturbation\"\>", "HyperlinkActive"]}, Dynamic[ 183 | CurrentValue["MouseOver"]], 184 | BaseStyle->{"Hyperlink"}, 185 | FrameMargins->0, 186 | ImageSize->Automatic], 187 | BaseStyle->"Hyperlink", 188 | ButtonData:>{"api-doc/Perturbation.nb", None}, 189 | ButtonNote->"api-doc/Perturbation.nb"], 190 | Annotation[#, "api-doc/Perturbation.nb", "Hyperlink"]& ], "Text", 191 | FontWeight->Bold], 192 | StyleBox[ 193 | RowBox[{ 194 | RowBox[{ 195 | "A", " ", "collection", " ", "of", " ", "perturbative", " ", 196 | "expansion", " ", "tools", " ", "such", " ", "as", " ", "the", " ", 197 | "Magnus", " ", "series"}], ",", " ", 198 | RowBox[{"the", " ", "Zassenhaus", " ", "formula"}], ",", " ", 199 | RowBox[{"and", " ", "matrix", " ", "perturbation", " ", "power", " ", 200 | RowBox[{"series", "."}]}]}], "Text"]} 201 | }, 202 | GridBoxAlignment->{"Columns" -> {{Left}}}, 203 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 204 | GridBoxItemSize->{"Columns" -> { 205 | Scaled[0.15], { 206 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 207 | "RowsIndexed" -> {}}]], "Text", 208 | GeneratedCell->True, 209 | CellAutoOverwrite->True, 210 | CellChangeTimes->{3.636901928861506*^9}], 211 | 212 | Cell[BoxData[GridBox[{ 213 | { 214 | StyleBox[ 215 | TagBox[ 216 | ButtonBox[ 217 | PaneSelectorBox[{False->"\<\"Predicates\"\>", True-> 218 | StyleBox["\<\"Predicates\"\>", "HyperlinkActive"]}, Dynamic[ 219 | CurrentValue["MouseOver"]], 220 | BaseStyle->{"Hyperlink"}, 221 | FrameMargins->0, 222 | ImageSize->Automatic], 223 | BaseStyle->"Hyperlink", 224 | ButtonData:>{"api-doc/Predicates.nb", None}, 225 | ButtonNote->"api-doc/Predicates.nb"], 226 | Annotation[#, "api-doc/Predicates.nb", "Hyperlink"]& ], "Text", 227 | FontWeight->Bold], 228 | StyleBox[ 229 | RowBox[{ 230 | "Provides", " ", "type", " ", "testing", " ", "functions", " ", "used", 231 | " ", "by", " ", "other", " ", 232 | RowBox[{"packages", "."}]}], "Text"]} 233 | }, 234 | GridBoxAlignment->{"Columns" -> {{Left}}}, 235 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 236 | GridBoxItemSize->{"Columns" -> { 237 | Scaled[0.15], { 238 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 239 | "RowsIndexed" -> {}}]], "Text", 240 | GeneratedCell->True, 241 | CellAutoOverwrite->True, 242 | CellChangeTimes->{3.636901928929929*^9}], 243 | 244 | Cell[BoxData[GridBox[{ 245 | { 246 | StyleBox[ 247 | TagBox[ 248 | ButtonBox[ 249 | PaneSelectorBox[{False->"\<\"QSim\"\>", True-> 250 | StyleBox["\<\"QSim\"\>", "HyperlinkActive"]}, Dynamic[ 251 | CurrentValue["MouseOver"]], 252 | BaseStyle->{"Hyperlink"}, 253 | FrameMargins->0, 254 | ImageSize->Automatic], 255 | BaseStyle->"Hyperlink", 256 | ButtonData:>{"api-doc/QSim.nb", None}, 257 | ButtonNote->"api-doc/QSim.nb"], 258 | Annotation[#, "api-doc/QSim.nb", "Hyperlink"]& ], "Text", 259 | FontWeight->Bold], 260 | StyleBox[ 261 | RowBox[{ 262 | RowBox[{ 263 | "A", " ", "general", " ", "purpose", " ", "quantum", " ", "system", " ", 264 | "time"}], "-", 265 | RowBox[{ 266 | "evolution", " ", "simulator", " ", "whose", " ", "primary", " ", 267 | "objective", " ", "is", " ", "ease", " ", "of", " ", 268 | RowBox[{"use", "."}]}]}], "Text"]} 269 | }, 270 | GridBoxAlignment->{"Columns" -> {{Left}}}, 271 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 272 | GridBoxItemSize->{"Columns" -> { 273 | Scaled[0.15], { 274 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 275 | "RowsIndexed" -> {}}]], "Text", 276 | GeneratedCell->True, 277 | CellAutoOverwrite->True, 278 | CellChangeTimes->{3.636901928990696*^9}], 279 | 280 | Cell[BoxData[GridBox[{ 281 | { 282 | StyleBox[ 283 | TagBox[ 284 | ButtonBox[ 285 | PaneSelectorBox[{False->"\<\"QuantumChannel\"\>", True-> 286 | StyleBox["\<\"QuantumChannel\"\>", "HyperlinkActive"]}, Dynamic[ 287 | CurrentValue["MouseOver"]], 288 | BaseStyle->{"Hyperlink"}, 289 | FrameMargins->0, 290 | ImageSize->Automatic], 291 | BaseStyle->"Hyperlink", 292 | ButtonData:>{"api-doc/QuantumChannel.nb", None}, 293 | ButtonNote->"api-doc/QuantumChannel.nb"], 294 | Annotation[#, "api-doc/QuantumChannel.nb", "Hyperlink"]& ], "Text", 295 | FontWeight->Bold], 296 | StyleBox[ 297 | RowBox[{ 298 | "Tools", " ", "for", " ", "constructing", " ", "and", " ", 299 | "manipulating", " ", "quantum", " ", "channels", " ", "in", " ", 300 | "various", " ", 301 | RowBox[{"representations", "."}]}], "Text"]} 302 | }, 303 | GridBoxAlignment->{"Columns" -> {{Left}}}, 304 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 305 | GridBoxItemSize->{"Columns" -> { 306 | Scaled[0.15], { 307 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 308 | "RowsIndexed" -> {}}]], "Text", 309 | GeneratedCell->True, 310 | CellAutoOverwrite->True, 311 | CellChangeTimes->{3.636901929057209*^9}], 312 | 313 | Cell[BoxData[GridBox[{ 314 | { 315 | StyleBox[ 316 | TagBox[ 317 | ButtonBox[ 318 | PaneSelectorBox[{False->"\<\"QuantumSystems\"\>", True-> 319 | StyleBox["\<\"QuantumSystems\"\>", "HyperlinkActive"]}, Dynamic[ 320 | CurrentValue["MouseOver"]], 321 | BaseStyle->{"Hyperlink"}, 322 | FrameMargins->0, 323 | ImageSize->Automatic], 324 | BaseStyle->"Hyperlink", 325 | ButtonData:>{"api-doc/QuantumSystems.nb", None}, 326 | ButtonNote->"api-doc/QuantumSystems.nb"], 327 | Annotation[#, "api-doc/QuantumSystems.nb", "Hyperlink"]& ], "Text", 328 | FontWeight->Bold], 329 | StyleBox[ 330 | RowBox[{ 331 | RowBox[{ 332 | "Tools", " ", "for", " ", "modelling", " ", "quantum", " ", "systems", 333 | " ", "of", " ", "qudits"}], ",", " ", "spins", ",", " ", 334 | RowBox[{"cavities", " ", "and", " ", 335 | RowBox[{"circuits", "."}]}]}], "Text"]} 336 | }, 337 | GridBoxAlignment->{"Columns" -> {{Left}}}, 338 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 339 | GridBoxItemSize->{"Columns" -> { 340 | Scaled[0.15], { 341 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 342 | "RowsIndexed" -> {}}]], "Text", 343 | GeneratedCell->True, 344 | CellAutoOverwrite->True, 345 | CellChangeTimes->{3.636901929127121*^9}], 346 | 347 | Cell[BoxData[GridBox[{ 348 | { 349 | StyleBox[ 350 | TagBox[ 351 | ButtonBox[ 352 | PaneSelectorBox[{False->"\<\"QUTesting\"\>", True-> 353 | StyleBox["\<\"QUTesting\"\>", "HyperlinkActive"]}, Dynamic[ 354 | CurrentValue["MouseOver"]], 355 | BaseStyle->{"Hyperlink"}, 356 | FrameMargins->0, 357 | ImageSize->Automatic], 358 | BaseStyle->"Hyperlink", 359 | ButtonData:>{"api-doc/QUTesting.nb", None}, 360 | ButtonNote->"api-doc/QUTesting.nb"], 361 | Annotation[#, "api-doc/QUTesting.nb", "Hyperlink"]& ], "Text", 362 | FontWeight->Bold], 363 | StyleBox[ 364 | RowBox[{ 365 | "Functions", " ", "for", " ", "running", " ", "unit", " ", "tests", " ", 366 | "for", " ", "QuantumUtils", " ", 367 | RowBox[{"packages", "."}]}], "Text"]} 368 | }, 369 | GridBoxAlignment->{"Columns" -> {{Left}}}, 370 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 371 | GridBoxItemSize->{"Columns" -> { 372 | Scaled[0.15], { 373 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 374 | "RowsIndexed" -> {}}]], "Text", 375 | GeneratedCell->True, 376 | CellAutoOverwrite->True, 377 | CellChangeTimes->{3.6369019291916847`*^9}], 378 | 379 | Cell[BoxData[GridBox[{ 380 | { 381 | StyleBox[ 382 | TagBox[ 383 | ButtonBox[ 384 | PaneSelectorBox[{False->"\<\"Tensor\"\>", True-> 385 | StyleBox["\<\"Tensor\"\>", "HyperlinkActive"]}, Dynamic[ 386 | CurrentValue["MouseOver"]], 387 | BaseStyle->{"Hyperlink"}, 388 | FrameMargins->0, 389 | ImageSize->Automatic], 390 | BaseStyle->"Hyperlink", 391 | ButtonData:>{"api-doc/Tensor.nb", None}, 392 | ButtonNote->"api-doc/Tensor.nb"], 393 | Annotation[#, "api-doc/Tensor.nb", "Hyperlink"]& ], "Text", 394 | FontWeight->Bold], 395 | StyleBox[ 396 | RowBox[{ 397 | "A", " ", "package", " ", "of", " ", "tensor", " ", "manipulations", " ", 398 | "for", " ", "multipartite", " ", "quantum", " ", 399 | RowBox[{"systems", "."}]}], "Text"]} 400 | }, 401 | GridBoxAlignment->{"Columns" -> {{Left}}}, 402 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 403 | GridBoxItemSize->{"Columns" -> { 404 | Scaled[0.15], { 405 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 406 | "RowsIndexed" -> {}}]], "Text", 407 | GeneratedCell->True, 408 | CellAutoOverwrite->True, 409 | CellChangeTimes->{3.6369019292600327`*^9}], 410 | 411 | Cell[BoxData[GridBox[{ 412 | { 413 | StyleBox[ 414 | TagBox[ 415 | ButtonBox[ 416 | PaneSelectorBox[{False->"\<\"Visualization\"\>", True-> 417 | StyleBox["\<\"Visualization\"\>", "HyperlinkActive"]}, Dynamic[ 418 | CurrentValue["MouseOver"]], 419 | BaseStyle->{"Hyperlink"}, 420 | FrameMargins->0, 421 | ImageSize->Automatic], 422 | BaseStyle->"Hyperlink", 423 | ButtonData:>{"api-doc/Visualization.nb", None}, 424 | ButtonNote->"api-doc/Visualization.nb"], 425 | Annotation[#, "api-doc/Visualization.nb", "Hyperlink"]& ], "Text", 426 | FontWeight->Bold], 427 | StyleBox[ 428 | RowBox[{ 429 | RowBox[{ 430 | "A", " ", "suite", " ", "of", " ", "tools", " ", "for", " ", 431 | "displaying", " ", "matrices"}], ",", " ", 432 | RowBox[{"quantum", " ", "states"}], ",", " ", "data", ",", " ", 433 | RowBox[{"etc", "."}]}], "Text"]} 434 | }, 435 | GridBoxAlignment->{"Columns" -> {{Left}}}, 436 | GridBoxDividers->{"Columns" -> {{False}}, "Rows" -> {{False}}}, 437 | GridBoxItemSize->{"Columns" -> { 438 | Scaled[0.15], { 439 | Scaled[0.7]}}, "ColumnsIndexed" -> {}, "Rows" -> {{1.}}, 440 | "RowsIndexed" -> {}}]], "Text", 441 | GeneratedCell->True, 442 | CellAutoOverwrite->True, 443 | CellChangeTimes->{3.636901929373824*^9}] 444 | }, Open ]], 445 | 446 | Cell["Tutorials", "Section", 447 | CellChangeTimes->{{3.633714486518713*^9, 3.6337144877822523`*^9}}] 448 | }, Open ]] 449 | }, 450 | WindowSize->{1631, 1026}, 451 | WindowMargins->{{0, Automatic}, {Automatic, 0}}, 452 | FrontEndVersion->"10.1 for Microsoft Windows (64-bit) (March 23, 2015)", 453 | StyleDefinitions->"Default.nb" 454 | ] 455 | (* End of Notebook Content *) 456 | 457 | (* Internal cache information *) 458 | (*CellTagsOutline 459 | CellTagsIndex->{} 460 | *) 461 | (*CellTagsIndex 462 | CellTagsIndex->{} 463 | *) 464 | (*NotebookFileOutline 465 | Notebook[{ 466 | Cell[CellGroupData[{ 467 | Cell[580, 22, 112, 1, 64, "Chapter"], 468 | Cell[695, 25, 450, 12, 30, "Text"], 469 | Cell[CellGroupData[{ 470 | Cell[1170, 41, 255, 3, 63, "Section"], 471 | Cell[1428, 46, 1136, 30, 33, "Text"], 472 | Cell[2567, 78, 1068, 30, 33, "Text"], 473 | Cell[3638, 110, 1249, 32, 33, "Text"], 474 | Cell[4890, 144, 1060, 29, 33, "Text"], 475 | Cell[5953, 175, 1347, 34, 33, "Text"], 476 | Cell[7303, 211, 1101, 30, 33, "Text"], 477 | Cell[8407, 243, 1221, 34, 33, "Text"], 478 | Cell[9631, 279, 1173, 31, 33, "Text"], 479 | Cell[10807, 312, 1211, 32, 33, "Text"], 480 | Cell[12021, 346, 1102, 30, 33, "Text"], 481 | Cell[13126, 378, 1103, 30, 33, "Text"], 482 | Cell[14232, 410, 1201, 32, 33, "Text"] 483 | }, Open ]], 484 | Cell[15448, 445, 96, 1, 63, "Section"] 485 | }, Open ]] 486 | } 487 | ] 488 | *) 489 | 490 | (* End of internal cache information *) 491 | -------------------------------------------------------------------------------- /src/ControlTheory.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*ControlTheory*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["ControlTheory`",{"QUDoc`","Tensor`"}]; 30 | 31 | 32 | Needs["QUDevTools`"]; 33 | 34 | 35 | $ControlTheoryUsages = LoadUsages[FileNameJoin[{$QUDocumentationPath, "api-doc", "ControlTheory.nb"}]]; 36 | 37 | 38 | (* ::Section:: *) 39 | (*Usage Declarations*) 40 | 41 | 42 | (* ::Subsection::Closed:: *) 43 | (*Lie Algebra Generation*) 44 | 45 | 46 | Unprotect[GenerateLieAlgebra,G,LieOperation,VSField,LinearIndependenceFun, 47 | StoppingDepth,StoppingDimension,AssumeHamiltonians,GeneratorSymbols, 48 | NumericalLieAlgebra]; 49 | 50 | 51 | AssignUsage[GenerateLieAlgebra,$ControlTheoryUsages]; 52 | 53 | 54 | AssignUsage[G,$ControlTheoryUsages]; 55 | 56 | 57 | AssignUsage[LieOperation,$ControlTheoryUsages]; 58 | AssignUsage[VSField,$ControlTheoryUsages]; 59 | AssignUsage[LinearIndependenceFun,$ControlTheoryUsages]; 60 | AssignUsage[StoppingDepth,$ControlTheoryUsages]; 61 | AssignUsage[StoppingDimension,$ControlTheoryUsages]; 62 | AssignUsage[AssumeHamiltonians,$ControlTheoryUsages]; 63 | AssignUsage[GeneratorSymbols,$ControlTheoryUsages]; 64 | AssignUsage[NumericalLieAlgebra,$ControlTheoryUsages]; 65 | 66 | 67 | (* ::Subsubsection:: *) 68 | (*Options*) 69 | 70 | 71 | Options[GenerateLieAlgebra]={ 72 | LieOperation->Com, 73 | Orthogonalize->True, 74 | NumericalLieAlgebra->False, 75 | VSField->Reals, 76 | LinearIndependenceFun->Automatic, 77 | StoppingDepth->\[Infinity], 78 | StoppingDimension->Automatic, 79 | AssumeHamiltonians->True, 80 | Threshold->10^-10, 81 | GeneratorSymbols->Automatic 82 | }; 83 | 84 | 85 | (* ::Subsubsection::Closed:: *) 86 | (*Errors*) 87 | 88 | 89 | GenerateLieAlgebra::moreargs = "At least two input generators required. Remember input should be a Sequence, and not a List."; 90 | 91 | 92 | (* ::Section:: *) 93 | (*Implementation*) 94 | 95 | 96 | Begin["`Private`"]; 97 | 98 | 99 | (* ::Subsection::Closed:: *) 100 | (*Lie Algebra Generation*) 101 | 102 | 103 | GenerateLieAlgebra[generators__,OptionsPattern[]]:=Module[ 104 | { 105 | gens,labs, 106 | com, 107 | num,dim, 108 | nextElement,nextPair,depth, 109 | \[Phi], 110 | parentSpot,expandOnce,expandAll, 111 | currentMax,currentDepth, 112 | meetsCriteria, 113 | freeBasis, 114 | i,j,x, 115 | stoppingDepth,stoppingDimension,stopSearching, 116 | field,orth,linIndep, 117 | vectorizor,devectorizor,ip,M,numGens, 118 | currentElement,noNewElems,noNewElemsAllDepth, 119 | symbols 120 | }, 121 | 122 | (* Various constants *) 123 | gens={generators}; 124 | If[Length@gens<2,Message[GenerateLieAlgebra::moreargs];Abort[]]; 125 | If[OptionValue@AssumeHamiltonians,gens=I*gens]; 126 | If[OptionValue@NumericalLieAlgebra,gens=N@gens]; 127 | com[args___]:=OptionValue[LieOperation][args]; 128 | dim=Length[First@gens]; 129 | num=Length[gens]; 130 | stoppingDimension=OptionValue@StoppingDimension; 131 | If[stoppingDimension===Automatic,stoppingDimension=dim^2-1]; 132 | stoppingDepth=OptionValue@StoppingDepth; 133 | field=OptionValue@VSField; 134 | orth=OptionValue@Orthogonalize; 135 | linIndep=OptionValue@LinearIndependenceFun; 136 | If[field==Reals, 137 | ip[v1_,v2_]:=v1.v2;, 138 | ip[v1_,v2_]:=Conjugate[v1].v2; 139 | ]; 140 | If[linIndep===Automatic, 141 | (* only works if orth=True*) 142 | linIndep=((Norm[#2]>OptionValue[Threshold]) && Not[Abs[Norm[ip[#1,#2]]-Norm[#2]]num&)]:>freeBasis[[n]]}; 168 | expandAll[expr_]:=expr//.{\[Phi][n_?(#>num&)]:>freeBasis[[n]]}; 169 | 170 | (* Functions to compute the depth of a given element, and the index of the left parent *) 171 | parentSpot[\[Phi][n_]]:=0; 172 | parentSpot[{\[Phi][n_],\[Phi][m_]}]:=n; 173 | Table[depth[\[Phi][n]]=1;,{n,num}]; 174 | depth[{\[Phi][n_],\[Phi][m_]}]:=(depth[{\[Phi][n],\[Phi][m]}]=depth@expandOnce[\[Phi][n]]+depth@expandOnce[\[Phi][m]]); 175 | 176 | (* The P Hall criteria, with an addition enforcing that the current Lie operation have the current depth. *) 177 | (* This condition is added for bookkeeping to make it easier to ensure we work through an entire depth before moving to the next one. *) 178 | meetsCriteria:=(depth[{\[Phi][i],\[Phi][j]}]==currentDepth)&&((j<=num)||(parentSpot[expandOnce[\[Phi][j]]]<=i)); 179 | 180 | (* Loop i and j between 1 and currentMax, enforcing icurrentMax, 185 | If[++i>=currentMax, 186 | currentMax=Length[freeBasis]; 187 | currentDepth++; 188 | (* Keep track of whether a new lin indep elem was added during a given depth for stopping criterion. *) 189 | If[noNewElems===True,noNewElemsAllDepth=True;]; 190 | noNewElems=True; 191 | i=1; 192 | ]; 193 | j=i+1; 194 | ]; 195 | ); 196 | 197 | (* Keep picking the nextPair until it meetsCriteria; append to the list *) 198 | nextElement:=( 199 | While[Not[meetsCriteria],nextPair;]; 200 | With[{next={\[Phi][i],\[Phi][j]}},AppendTo[freeBasis,next];nextPair;next] 201 | ); 202 | 203 | (* One can prove that separating into reals and imaginaries lets you compute R-linear-independance in C. *) 204 | If[field===Reals, 205 | vectorizor[A_]:=Flatten[{Re@A,Im@A}]; 206 | devectorizor[v_]:=Partition[v[[1;;dim^2]]+I*v[[dim^2+1;;-1]],dim];, 207 | vectorizor[A_]:=Flatten[A]; 208 | devectorizor[v_]:=Partition[v,dim]; 209 | ]; 210 | 211 | (* Make a matrix which spans the output Lie algebra. *) 212 | M=vectorizor/@gens; 213 | If[orth,M=Select[Orthogonalize[M],Norm[#]>$MachineEpsilon&]]; 214 | 215 | (* Condition to stop looking for more basis elements. *) 216 | stopSearching:= noNewElemsAllDepth || (currentDepth>stoppingDepth) || (Length[M]>=stoppingDimension); 217 | 218 | com[\[Phi][n_]]:=gens[[n]]; 219 | If[orth, 220 | com[{\[Phi][n_],\[Phi][m_]}]:=(com[{\[Phi][n],\[Phi][m]}]= 221 | With[{A=OptionValue[LieOperation][com@expandOnce@\[Phi][n],com@expandOnce@\[Phi][m]]}, 222 | With[{norm=Sqrt[Tr[A\[ConjugateTranspose].A]]},If[norm>OptionValue@Threshold,A/norm,0*A]] 223 | ] 224 | );, 225 | com[{\[Phi][n_],\[Phi][m_]}]:=(com[{\[Phi][n],\[Phi][m]}]=OptionValue[LieOperation][com@expandOnce@\[Phi][n],com@expandOnce@\[Phi][m]]); 226 | ]; 227 | 228 | (* Main loop. *) 229 | While[Not[stopSearching], 230 | currentElement=nextElement; 231 | 232 | (* Check for linear independence. *) 233 | If[linIndep[M,vectorizor[com[currentElement]]], 234 | noNewElems=False; 235 | If[orth, 236 | (* Append the normalized projection onto the space orthogonal to M. *) 237 | AppendTo[M,With[{v=vectorizor[com[currentElement]]},Normalize[v-Total[ip[M,v].M]]]], 238 | (* Append the whole thing. *) 239 | AppendTo[M,vectorizor[com[currentElement]]] 240 | ]; 241 | ]; 242 | ]; 243 | 244 | numGens=Length@M; 245 | If[OptionValue@AssumeHamiltonians,M=-I*M;]; 246 | com[{\[Phi][n_],\[Phi][m_]}]:=(com[{\[Phi][n],\[Phi][m]}]=OptionValue[LieOperation][com@expandOnce@\[Phi][n],com@expandOnce@\[Phi][m]]); 247 | 248 | (* Output. *) 249 | { 250 | numGens, 251 | With[{reps=Thread[freeBasis[[1;;num]]->symbols[[1;;num]]]},expandAll[freeBasis[[1;;numGens]]]/.reps], 252 | devectorizor/@M 253 | } 254 | ] 255 | 256 | 257 | (* ::Subsection::Closed:: *) 258 | (*End Private*) 259 | 260 | 261 | End[]; 262 | 263 | 264 | (* ::Section::Closed:: *) 265 | (*End Package*) 266 | 267 | 268 | Protect[GenerateLieAlgebra,G,LieOperation,VSField,LinearIndependenceFun, 269 | StoppingDepth,StoppingDimension,AssumeHamiltonians,GeneratorSymbols, 270 | NumericalLieAlgebra]; 271 | 272 | 273 | EndPackage[]; 274 | -------------------------------------------------------------------------------- /src/LindbladSolver.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Lindblad Solver Package*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["LindbladSolver`",{"QUDoc`"}]; 30 | 31 | 32 | Needs["QUDevTools`"]; 33 | Needs["Tensor`"] 34 | Needs["QuantumChannel`"] 35 | 36 | 37 | $LindbladSolverUsages = LoadUsages[FileNameJoin[{$QUDocumentationPath, "api-doc", "LindbladSolver.nb"}]]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Usage Declaration*) 42 | 43 | 44 | (* ::Subsection::Closed:: *) 45 | (*Main Functions*) 46 | 47 | 48 | Unprotect[ODESolver,SchrodingerSolver,LindbladSolver]; 49 | 50 | 51 | AssignUsage[{ODESolver,SchrodingerSolver,LindbladSolver},$LindbladSolverUsages]; 52 | 53 | 54 | (* ::Subsection::Closed:: *) 55 | (*Utility Functions*) 56 | 57 | 58 | Unprotect[ODECoefficients,ODEVariables,ODEInitialConditions,ODEFirstOrderSystem]; 59 | 60 | 61 | AssignUsage[{ODECoefficients,ODEVariables,ODEInitialConditions,ODEFirstOrderSystem},$LindbladSolverUsages]; 62 | 63 | 64 | (* ::Subsection::Closed:: *) 65 | (*Error Messages*) 66 | 67 | 68 | ODESolver::initcond = "Input state must be a square matrix or vector."; 69 | ODESolver::symsol = "ODESolver failed to find an symbolic solution."; 70 | 71 | 72 | (* ::Section:: *) 73 | (*Implementation*) 74 | 75 | 76 | Begin["`Private`"]; 77 | 78 | 79 | (* ::Subsection:: *) 80 | (*Preformating State and Lindblad*) 81 | 82 | 83 | (* ::Text:: *) 84 | (*These functions process the generator input for time-dependent or time-independent matrices and quantum channels.*) 85 | 86 | 87 | PreformatGenerator[generator_,t_]:= 88 | Which[ 89 | Head[generator]===Function, 90 | PreformatGenerator[generator[t],t], 91 | Head[generator]===QuantumChannel, 92 | PreformatGenerator[First@Super[generator],t], 93 | True,generator] 94 | 95 | 96 | PreformatLindblad[ham_,collapseOps_List]:= 97 | Function[t,Evaluate[ 98 | With[{ 99 | ham1=PreformatGenerator[ham,t], 100 | cOps1=Map[PreformatGenerator[#,t]&,PreformatGenerator[collapseOps,t]]}, 101 | First[If[ham1===0,0,-I*ComChannel[ham1]] 102 | +If[cOps1==={},0,LindbladDissipator[cOps1]] 103 | ]] 104 | ]] 105 | 106 | 107 | PreformatHamiltonian[ham_]:= 108 | Function[t, 109 | Evaluate[-I*PreformatGenerator[ham,t]] 110 | ] 111 | 112 | 113 | PreformatState[initState_]:= 114 | Which[ 115 | SquareMatrixQ[initState], Flatten@Vec[Normal[initState]], 116 | GeneralVectorQ[initState], Flatten[Normal[initState]], 117 | True, Message[ODESolver::initcond] 118 | ] 119 | 120 | 121 | (* ::Subsection::Closed:: *) 122 | (*Setting up the ODE*) 123 | 124 | 125 | (* ::Subsubsection::Closed:: *) 126 | (*First order system of equations*) 127 | 128 | 129 | (* ::Text:: *) 130 | (*Variables for a matrix ODE*) 131 | 132 | 133 | ODECoefficients[{d_,sym_}]:=Array[sym,d] 134 | 135 | 136 | (* ::Text:: *) 137 | (*Time dependent variables for a matrix ODE*) 138 | 139 | 140 | ODEVariables[{d_,t_,sym_}]:=Through[ODECoefficients[{d,sym}][t]] 141 | 142 | 143 | (* ::Text:: *) 144 | (*Setting up conditions for a first order matrix ODE*) 145 | 146 | 147 | ODEInitialConditions[initState_,{t0_,sym_}]:= 148 | With[{state=PreformatState[initState]}, 149 | LogicalExpand[ODEVariables[{Length[state],t0,sym}]==state]] 150 | 151 | 152 | Options[ODEFirstOrderSystem]:={Compile->False}; 153 | ODEFirstOrderSystem[generator_,{t_,sym_},opts:OptionsPattern[ODEFirstOrderSystem]]:= 154 | With[{ 155 | op=PreformatGenerator[generator,t]}, 156 | If[OptionValue[Compile], 157 | CompileFirstOrderODE[op,{t,sym}], 158 | LogicalExpand[ 159 | D[ODEVariables[{Length[op],t,sym}],t] 160 | ==op.ODEVariables[{Length[op],t,sym}]] 161 | ]] 162 | 163 | 164 | (* ::Subsubsection::Closed:: *) 165 | (*Compiling part of ODE*) 166 | 167 | 168 | (* ::Text:: *) 169 | (*Compiling RHS of ODE (seems to be slower for most things)*) 170 | 171 | 172 | CompileODETerm[genTerm_,{t_,sym_}]:= 173 | Block[{inside,$t,$x}, 174 | ReleaseHold[ 175 | Hold[ 176 | Compile[{{$t,_Real},{$x,_Complex,1}}, 177 | inside, 178 | Parallelization->True, 179 | CompilationTarget->"C"] 180 | ]//.{inside->genTerm,t->$t, sym[m_Integer]:>$x[[m]]} 181 | ] 182 | ] 183 | 184 | 185 | ClearAll[CompileFirstOrderODE]; 186 | CompileFirstOrderODE[generator_,{t_,sym_}]:= 187 | CompileFirstOrderODE[generator,{t,sym}]= 188 | Block[{inside,genTerms, 189 | d=Length[generator], 190 | rhsfun=Unique["rhs"], 191 | cfun=Unique["cfun"]}, 192 | genTerms=generator.ODECoefficients[{d,sym}]; 193 | MapThread[ 194 | (Evaluate[cfun[#1]]=CompileODETerm[#2,{t,sym}])&, 195 | {Range[d],genTerms}]; 196 | rhsfun[j_,$t_?NumericQ,$x_]:=Evaluate[cfun[j][$t,$x]]; 197 | Inner[Equal, 198 | D[ODEVariables[{d,t,sym}],t], 199 | Map[rhsfun[#,t,ODEVariables[{d,t,sym}]]&,Range[d]], 200 | And] 201 | ] 202 | 203 | 204 | (* ::Subsection::Closed:: *) 205 | (*Numerically Solving ODE*) 206 | 207 | 208 | (* ::Subsubsection:: *) 209 | (*General ODE Solver*) 210 | 211 | 212 | (* ::Text:: *) 213 | (*Filter option function for passing options to NDSolveValue and DSolveValue*) 214 | 215 | 216 | FilterOptions[targetFun_,opts___]:=Sequence@@FilterRules[{opts},Options[targetFun]]; 217 | 218 | 219 | Options[ODESolver]=Join[{Symbol->"x"},Options[ODEFirstOrderSystem],Options[NDSolve]]; 220 | 221 | 222 | ODESolver[generator_,{initState_,t0_?NumericQ,tf_?NumericQ},opts:OptionsPattern[ODESolver]]:= 223 | With[{sym=OptionValue[Symbol]}, 224 | With[{init=ODEInitialConditions[initState,{t0,sym}]}, 225 | NDSolveValue[ 226 | And[ 227 | ODEFirstOrderSystem[generator,{t,sym} 228 | ,FilterOptions[ODEFirstOrderSystem,opts]], 229 | init], 230 | ODECoefficients[{Length[init],sym}], 231 | {t,0,tf}, 232 | FilterOptions[NDSolve,opts]] 233 | ]] 234 | 235 | 236 | (* ::Subsubsection:: *) 237 | (*Schrodinger Equation Solver*) 238 | 239 | 240 | (* ::Text:: *) 241 | (*Returns the result for ODESolver but with -I coefficient added to the hamiltonian operator as per Schrodingers equation. It also returns the result as a function of time rather than the raw interpolation functions.*) 242 | 243 | 244 | SchrodingerSolver[ham_,{initState_,t0_?NumericQ,tf_?NumericQ},opts:OptionsPattern[ODESolver]]:= 245 | Function[t,Evaluate[ 246 | Through[ 247 | ODESolver[PreformatHamiltonian[ham],{initState,t0,tf},opts][t] 248 | ]]] 249 | 250 | 251 | (* ::Subsubsection:: *) 252 | (*Lindblad Equation Solver*) 253 | 254 | 255 | (* ::Text:: *) 256 | (*If only one argument is input it behaves the same as ODESolver, but with the addition of devectorizing the output to return a density matrix, it also returns the resulting state as a function of time rather than the raw interpolation functions.*) 257 | 258 | 259 | LindbladSolver[generator_,{initState_,t0_?NumericQ,tf_?NumericQ},opts:OptionsPattern[ODESolver]]:= 260 | Function[t,Evaluate[ 261 | Devec[Through[ 262 | ODESolver[generator,{initState,t0,tf},opts][t]] 263 | ]]] 264 | 265 | 266 | LindbladSolver[ 267 | {ham_,collapseOps_List}, 268 | {initState_,t0_?NumericQ,tf_?NumericQ}, 269 | opts:OptionsPattern[ODESolver]]:= 270 | LindbladSolver[PreformatLindblad[ham,collapseOps],{initState,t0,tf},opts] 271 | 272 | 273 | (* ::Subsection:: *) 274 | (*Symbolically Solver ODE*) 275 | 276 | 277 | (* ::Subsubsection:: *) 278 | (*General Solver*) 279 | 280 | 281 | ODESolver[generator_,{initState_,t0_},opts:OptionsPattern[ODESolver]]:= 282 | With[{sym=OptionValue[Symbol]}, 283 | Function[t, 284 | Evaluate[ 285 | Block[{vars,sys,sol, 286 | init=ODEInitialConditions[initState,{t0,sym}]}, 287 | vars=ODEVariables[{Length[init],t,sym}]; 288 | sys=And[ODEFirstOrderSystem[generator,{t,sym}],init]; 289 | sol=DSolve[sys,vars,t,FilterOptions[DSolve,opts]]; 290 | If[Head[sol]===DSolve, 291 | Message[ODESolver::symsol], 292 | vars/.Flatten[sol] 293 | ] 294 | ] 295 | ] 296 | ]] 297 | 298 | 299 | ODESolver[generator_,opts:OptionsPattern[ODESolver]]:= 300 | With[{sym=OptionValue[Symbol]}, 301 | Function[t, 302 | Evaluate[ 303 | Block[{vars,sol, 304 | sys=ODEFirstOrderSystem[generator,{t,sym}],vars}, 305 | vars=ODEVariables[{Length[sys],t,sym}]; 306 | sol=DSolve[sys,vars,t,FilterOptions[DSolve,opts]]; 307 | If[Head[sol]===DSolve, 308 | Message[ODESolver::symsol], 309 | vars/.Flatten[sol] 310 | ] 311 | ] 312 | ] 313 | ]] 314 | 315 | 316 | (* ::Subsubsection::Closed:: *) 317 | (*Schrodinger Equation Solver*) 318 | 319 | 320 | SchrodingerSolver[ham_,{initState_,t0_},opts:OptionsPattern[ODESolver]]:= 321 | ODESolver[PreformatHamiltonian[ham],{initState,t0},opts] 322 | 323 | SchrodingerSolver[ham_,opts:OptionsPattern[ODESolver]]:=ODESolver[PreformatHamiltonian[ham],opts] 324 | 325 | 326 | (* ::Subsubsection::Closed:: *) 327 | (*Lindblad Equation Solver*) 328 | 329 | 330 | LindbladSolver[generator_,opts:OptionsPattern[ODESolver]]:= 331 | With[{sol=ODESolver[generator,opts]}, 332 | ReplacePart[sol,2->Evaluate[Devec[Part[sol,2]]]]] 333 | 334 | 335 | LindbladSolver[generator_,{initState_,t0_},opts:OptionsPattern[ODESolver]]:= 336 | With[{sol=ODESolver[generator,{initState,t0},opts]}, 337 | ReplacePart[sol,2->Evaluate[Devec[Part[sol,2]]]]] 338 | 339 | 340 | LindbladSolver[{ham_,collapseOps_List},opts:OptionsPattern[ODESolver]]:= 341 | LindbladSolver[PreformatLindblad[ham,collapseOps],opts] 342 | 343 | 344 | LindbladSolver[{ham_,collapseOps_List},{initState_,t0_},opts:OptionsPattern[ODESolver]]:= 345 | LindbladSolver[PreformatLindblad[ham,collapseOps],{initState,t0},opts] 346 | 347 | 348 | (* ::Subsection::Closed:: *) 349 | (*End Private*) 350 | 351 | 352 | End[]; 353 | 354 | 355 | (* ::Section::Closed:: *) 356 | (*End Package*) 357 | 358 | 359 | Protect[ODESolver,SchrodingerSolver,LindbladSolver]; 360 | Protect[ODECoefficients,ODEVariables,ODEInitialConditions,ODEFirstOrderSystem]; 361 | 362 | 363 | EndPackage[]; 364 | -------------------------------------------------------------------------------- /src/M2M.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*M2M Package*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["M2M`",{"QUDoc`"}]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | 38 | 39 | $M2MUsages = LoadUsages[FileNameJoin[{$QUDocumentationPath, "api-doc", "M2M.nb"}]]; 40 | 41 | 42 | (* ::Section:: *) 43 | (*Known Limitations*) 44 | 45 | 46 | (* ::Text:: *) 47 | (*Adds lots of extraneous parens, since the different structure of Mathematica and MATLAB syntax trees makes the order of operations ambiguous without. A smarter transformation would deal with this problem.*) 48 | 49 | 50 | (* ::Text:: *) 51 | (*Assumes that QuantumUtils for MATLAB is on the path.*) 52 | 53 | 54 | (* ::Section:: *) 55 | (*Usage Declaration*) 56 | 57 | 58 | (* ::Subsection:: *) 59 | (*Utility Functions*) 60 | 61 | 62 | Unprotect[ 63 | LatinLowerCaseQ, LatinUpperCaseQ, LatinLetterQ, 64 | UnderscoreQ, ValidMATLABIdentifierCharacterQ, 65 | ValidMATLABIdentifierQ 66 | ]; 67 | 68 | 69 | AssignUsage[{ 70 | LatinLowerCaseQ, LatinUpperCaseQ, LatinLetterQ, 71 | UnderscoreQ, ValidMATLABIdentifierQ, 72 | ValidMATLABIdentifierQ 73 | }, $M2MUsages]; 74 | 75 | 76 | (* ::Subsection:: *) 77 | (*Expression Converters*) 78 | 79 | 80 | Unprotect[ 81 | ExpressionToMATLAB 82 | ]; 83 | 84 | 85 | AssignUsage[ 86 | ExpressionToMATLAB 87 | , $M2MUsages]; 88 | 89 | 90 | (* ::Subsection:: *) 91 | (*Function Converters*) 92 | 93 | 94 | Unprotect[ 95 | SimpleFunctionToMATLAB, StatementToMATLAB, FunctionToMATLAB, ExportFunctionToMATLAB 96 | ]; 97 | 98 | 99 | AssignUsage[{ 100 | SimpleFunctionToMATLAB, StatementToMATLAB, FunctionToMATLAB, ExportFunctionToMATLAB 101 | }, $M2MUsages]; 102 | 103 | 104 | (* ::Section:: *) 105 | (*Utility Functions*) 106 | 107 | 108 | (* ::Subsection:: *) 109 | (*Predicates*) 110 | 111 | 112 | (* ::Subsubsection:: *) 113 | (*Implementations*) 114 | 115 | 116 | Begin["`Private`"]; 117 | 118 | 119 | LatinLowerCaseQ[x_]:=MemberQ[CharacterRange["a","z"],x]; 120 | LatinUpperCaseQ[x_]:=MemberQ[CharacterRange["A","Z"],x]; 121 | 122 | 123 | LatinLetterQ[x_]:=LatinLowerCaseQ[x]\[Or]LatinUpperCaseQ[x]; 124 | 125 | 126 | UnderscoreQ[x_]:=x=="_"; 127 | 128 | 129 | ValidMATLABIdentiferCharacterQ[ch_]:=Or@@Map[#[ch]&,{LatinLetterQ,UnderscoreQ,DigitQ}] 130 | 131 | 132 | ValidMATLABIdentifierQ[str_]:=(And@@Map[ValidMATLABIdentiferCharacterQ,Characters@str])&&LatinLetterQ[(Characters@str)[[1]]]&&(Length[Characters@str]<=63); 133 | 134 | 135 | End[]; 136 | 137 | 138 | (* ::Subsection:: *) 139 | (*String Handling*) 140 | 141 | 142 | (* ::Subsubsection:: *) 143 | (*Implementations*) 144 | 145 | 146 | Begin["`Private`"]; 147 | 148 | 149 | JoinStrings[{strs__},sep_]:=StringJoin@@Flatten[Map[{#,sep}&, {strs}]][[;;-2]] 150 | 151 | 152 | End[]; 153 | 154 | 155 | (* ::Subsection:: *) 156 | (*Internal Use Utility Functions*) 157 | 158 | 159 | Begin["`Private`"]; 160 | 161 | 162 | CheckSymbol[sym_] := If[\[Not]ValidMATLABIdentifierQ[SymbolName[sym]], Message[ExpressionToMATLAB::invsym, SymbolName[sym]]]; 163 | 164 | 165 | End[]; 166 | 167 | 168 | (* ::Section:: *) 169 | (*Expression Conversions*) 170 | 171 | 172 | (* ::Text:: *) 173 | (*The core of the M2M package is the function ExpressionToMATLAB, which we progressively extend with new functionality. Here, we define the usage statement and error messages for that function.*) 174 | 175 | 176 | (* ::Subsection:: *) 177 | (*Numeric Literals*) 178 | 179 | 180 | Begin["`Private`"]; 181 | 182 | 183 | (* ::Text:: *) 184 | (*We now define how to convert numeric literals of Real and Integer heads to MATLAB expressions: by directly converting them to strings.*) 185 | 186 | 187 | ExpressionToMATLAB[x_Real] := ToString[CForm[x]] 188 | ExpressionToMATLAB[x_Integer] := ToString[x] 189 | 190 | 191 | (* ::Text:: *) 192 | (*Next, we extend this definition to Complex and Rational heads by recursion.*) 193 | 194 | 195 | ExpressionToMATLAB[Complex[re_,im_]]:="("<>ExpressionToMATLAB[re] <> " + " <>ExpressionToMATLAB[im]<>"*i)"; 196 | ExpressionToMATLAB[Rational[nu_,de_]]:="("<>ExpressionToMATLAB[nu] <> "/" <> ExpressionToMATLAB[de]<>")"; 197 | 198 | 199 | End[]; 200 | 201 | 202 | (* ::Subsection:: *) 203 | (*Symbols*) 204 | 205 | 206 | Begin["`Private`"]; 207 | 208 | 209 | (* ::Text:: *) 210 | (*We assume that free symbols in Mathematica expressions are intended to be represented by variables in corresponding MATLAB code. Hence, we restrict conversions of symbols to those symbols that could concievably be used as MATLAB identifiers.*) 211 | 212 | 213 | ExpressionToMATLAB[x_Symbol] := ( 214 | If[\[Not]ValidMATLABIdentifierQ[SymbolName[x]], Message[ExpressionToMATLAB::invsym, SymbolName[x]]]; 215 | SymbolName[x] 216 | ); 217 | 218 | 219 | (* ::Text:: *) 220 | (*Some Mathematica symbols require special treatment, however, and so we override the generic definition for Symbol heads in these particular cases.*) 221 | 222 | 223 | ExpressionToMATLAB[E]="exp(1)"; 224 | ExpressionToMATLAB[\[Pi]]="pi"; 225 | 226 | 227 | End[]; 228 | 229 | 230 | (* ::Subsection:: *) 231 | (*Argument Lists*) 232 | 233 | 234 | (* ::Subsubsection:: *) 235 | (*Usage Statements and Error Messages*) 236 | 237 | 238 | MATLABArgsList::usage = "Converts a list of Mathematica expressions into a string representing list of MATLAB arguments."; 239 | 240 | 241 | (* ::Subsubsection:: *) 242 | (*Implementations*) 243 | 244 | 245 | Begin["`Private`"]; 246 | 247 | 248 | (* ::Text:: *) 249 | (*In converting to MATLAB code, we shall commonly need to form lists of arguments, and so we define a function that calls JoinStrings appropriately.*) 250 | 251 | 252 | MATLABArgsList[{args__},sep_,suppressParens_:False] := 253 | Module[{inner}, 254 | inner = JoinStrings[ExpressionToMATLAB/@{args}, sep]; 255 | If[suppressParens, inner, 256 | "(" <> inner <> ")" 257 | ] 258 | ]; 259 | 260 | 261 | End[]; 262 | 263 | 264 | (* ::Subsection:: *) 265 | (*Infix Operators*) 266 | 267 | 268 | (* ::Subsubsection:: *) 269 | (*Usage Statements and Error Messages*) 270 | 271 | 272 | DefineMATLABInfixOperator::usage = "Extends ExpressionToMATLAB so as to recognize a given Mathematica head as corresponding to a string represention of a MATLAB operator."; 273 | 274 | 275 | (* ::Subsubsection:: *) 276 | (*Implementations*) 277 | 278 | 279 | Begin["`Private`"]; 280 | 281 | 282 | (* ::Text:: *) 283 | (*We are now prepared to define infix operators between two or more expressions.*) 284 | 285 | 286 | DefineMATLABInfixOperator[head_,str_]:=( 287 | ExpressionToMATLAB[HoldPattern[head[xs__]]]:=MATLABArgsList[{xs},str]; 288 | ); 289 | 290 | 291 | (* ::Text:: *) 292 | (*Using this new function, we can quickly define a few useful infix operators:*) 293 | 294 | 295 | DefineMATLABInfixOperator[Plus, "+"]; 296 | DefineMATLABInfixOperator[Times, ".*"]; 297 | DefineMATLABInfixOperator[Dot, "*"]; 298 | DefineMATLABInfixOperator[Power, ".^"]; 299 | DefineMATLABInfixOperator[MatrixPower, "^"]; 300 | 301 | DefineMATLABInfixOperator[Equal, "=="]; 302 | DefineMATLABInfixOperator[Unequal, "~="]; 303 | DefineMATLABInfixOperator[Less, "<"]; 304 | DefineMATLABInfixOperator[Greater, ">"]; 305 | DefineMATLABInfixOperator[LessEqual, "<="]; 306 | DefineMATLABInfixOperator[GreaterEqual, ">="]; 307 | 308 | DefineMATLABInfixOperator[And, "&&"]; 309 | DefineMATLABInfixOperator[Or, "||"]; 310 | 311 | 312 | (* ::Text:: *) 313 | (*Note that we have exercised caution about the discinction between MATLAB's dotted infix operators and their undotted forms.*) 314 | 315 | 316 | (* ::Text:: *) 317 | (*As a special case of the Power function, we wish to map natural exponentials onto MATLAB's exp function.*) 318 | 319 | 320 | ExpressionToMATLAB[Power[E,expr_]] := "exp(" <> ExpressionToMATLAB[expr] <> ")"; 321 | 322 | 323 | (* ::Text:: *) 324 | (*Also note that division must be handled as a special case of the Times head, since Mathematica does not separate divison from multiplying by the reciprocal. This is not ideal for MATLAB code, however, as we must worry about efficiency and numerical stability. An added difficulty is that the pattern for division is fragile and must be protected by the HoldPattern head.*) 325 | 326 | 327 | ExpressionToMATLAB[HoldPattern[x_ / y_]]:= "(" <> ExpressionToMATLAB[x] <> "./" <>ExpressionToMATLAB[y] <> ")" 328 | 329 | 330 | End[]; 331 | 332 | 333 | (* ::Subsection:: *) 334 | (*Functions*) 335 | 336 | 337 | (* ::Subsubsection:: *) 338 | (*Usage Statements and Error Messages*) 339 | 340 | 341 | DefineMATLABFunction::usage = "Extends ExpressionToMATLAB to recognize a Mathematica function as having an equivalent MATLAB function."; 342 | 343 | 344 | (* ::Subsubsection:: *) 345 | (*Implementations*) 346 | 347 | 348 | Begin["`Private`"]; 349 | 350 | 351 | (* ::Text:: *) 352 | (*Using the same trick as for infix operators, we now define a function that extends ExpressionToMATLAB to recognize a Mathematica head as corresponding exactly to a MATLAB function call. This is only appropriate if the argument lists are expected to be identical.*) 353 | 354 | 355 | DefineMATLABFunction[head_,str_]:=( 356 | ExpressionToMATLAB[HoldPattern[head[args__]]]:=str<>MATLABArgsList[{args}, ","] 357 | ); 358 | 359 | 360 | (* ::Text:: *) 361 | (*We can now define a few functions as having equivalents in the MATLAB world.*) 362 | 363 | 364 | DefineMATLABFunction[Sin,"sin"]; 365 | DefineMATLABFunction[Cos,"cos"]; 366 | DefineMATLABFunction[Tan,"tan"]; 367 | DefineMATLABFunction[Csc,"csc"]; 368 | DefineMATLABFunction[Sec,"sec"]; 369 | DefineMATLABFunction[Cot,"cot"]; 370 | DefineMATLABFunction[Sqrt,"sqrt"]; 371 | DefineMATLABFunction[MatrixExp,"expm"]; 372 | DefineMATLABFunction[Abs,"abs"]; 373 | DefineMATLABFunction[Tr,"trace"]; 374 | 375 | 376 | (* ::Text:: *) 377 | (*Some of the functions we wish to convert only have equivalents that we provide with QuantumUtils for MATLAB.*) 378 | 379 | 380 | DefineMATLABFunction[If, "iif"]; 381 | 382 | 383 | ExpressionToMATLAB[HoldPattern[QuantumUtils`Private`VecImpl[ColStackingVectorizationConvention,\[Rho]_Symbol]]] := ExpressionToMATLAB[\[Rho]]<>"(:)"; 384 | 385 | 386 | End[]; 387 | 388 | 389 | (* ::Subsection:: *) 390 | (*Vectors and Matrices*) 391 | 392 | 393 | Begin["`Private`"]; 394 | 395 | 396 | (* ::Text:: *) 397 | (*Defining a transformation for vectors is relatively straightforward.*) 398 | 399 | 400 | ExpressionToMATLAB[vec_?VectorQ] := "[" <> MATLABArgsList[vec, " ", True] <> "]"; 401 | 402 | 403 | (* ::Text:: *) 404 | (*More complicated is the transformation for matrices, where we must worry about treating columns and rows differently.*) 405 | 406 | 407 | ExpressionToMATLAB[array_?MatrixQ] := Module[{marr, rowfn, colfn}, 408 | marr=Map[ExpressionToMATLAB,array,{2}]; 409 | rowfn[{row__}]:=JoinStrings[{row}, " "]; 410 | colfn[{col__}]:=JoinStrings[{col}, "; "]; 411 | 412 | "[" <> colfn[Map[rowfn, marr]] <> "]" 413 | ]; 414 | 415 | 416 | (* ::Text:: *) 417 | (*We also define a mapping for the ConjugateTranspose operation:*) 418 | 419 | 420 | ExpressionToMATLAB[HoldPattern[ConjugateTranspose[M_]]] := "(" <> ExpressionToMATLAB[M] <> ")'"; 421 | 422 | 423 | End[]; 424 | 425 | 426 | (* ::Subsection:: *) 427 | (*Held Expressions*) 428 | 429 | 430 | Begin["`Private`"]; 431 | 432 | 433 | ExpressionToMATLAB::holdunfinished = "Using ExpressionToMATLAB with Hold is currently buggy! Please check the output carefully."; 434 | ExpressionToMATLAB[Hold[head_[args__]]] := ( 435 | Message[ExpressionToMATLAB::holdunfinished]; 436 | StringReplace[ 437 | Quiet[ExpressionToMATLAB[head[$x]], ExpressionToMATLAB::invsym], 438 | "$x" -> MATLABArgsList[{args}, ", ", False] 439 | ] 440 | ); 441 | 442 | 443 | End[]; 444 | 445 | 446 | (* ::Section:: *) 447 | (*Statement and Function Conversions*) 448 | 449 | 450 | (* ::Subsection:: *) 451 | (*Simple Functions*) 452 | 453 | 454 | (* ::Text:: *) 455 | (*At times, we will want to convert entire Mathematica functions into MATLAB functions. We start by defining how to convert functions that consist of single expressions.*) 456 | 457 | 458 | (* ::Subsubsection:: *) 459 | (*Implementations*) 460 | 461 | 462 | Begin["`Private`"]; 463 | 464 | 465 | SimpleFunctionToMATLAB[funcname_, {args__}, func_]:= 466 | Module[{header,argsList,footer,exprStr}, 467 | CheckSymbol/@{args}; 468 | (* TODO: Check that funcname is a valid identifier. *) 469 | 470 | exprStr="Y = "<>ExpressionToMATLAB[func[args]] <> ";"; 471 | argsList = MATLABArgsList[{args}, ", "]; 472 | header= 473 | "% " <> funcname <> " TODO: add documentation here.\n" <> 474 | "function Y = " <> funcname <> argsList <>"\n"<> 475 | "% WARNING: This file was automatically generated by the M2M package for Mathematica.\n" <> 476 | "% Do not edit the following lines directly." ; 477 | (* TODO: Add metadata from the current notebook. *) 478 | footer = "end"; 479 | header <> "\n" <> exprStr <> "\n"<>footer 480 | ]; 481 | 482 | 483 | End[]; 484 | 485 | 486 | (* ::Subsection:: *) 487 | (*Statement Conversions*) 488 | 489 | 490 | (* ::Text:: *) 491 | (*In order to convert more complicated functions, we must operate statement-by-statement. This requires being more careful with what is and is not evaluated. As before, we shall work by repeatedly extending a single function, in this case StatementToMATLAB, in order to recognize more features of the MATLAB language.*) 492 | 493 | 494 | (* ::Subsubsection:: *) 495 | (*Attributes*) 496 | 497 | 498 | SetAttributes[StatementToMATLAB, HoldAll]; 499 | 500 | 501 | (* ::Subsubsection:: *) 502 | (*Implementations*) 503 | 504 | 505 | Begin["`Private`"]; 506 | 507 | 508 | (* ::Text:: *) 509 | (*We strip off calls to Module, as they are unnecessary in MATLAB.*) 510 | 511 | 512 | StatementToMATLAB[HoldPattern[Module[{vars__},body_]]]:=( 513 | (* We can ignore the list of vars, owing to MATLAB dynamically allocating variables. *) 514 | StatementToMATLAB[body] 515 | ); 516 | 517 | 518 | (* ::Text:: *) 519 | (*Next, we reduce the problem of converting compound expressions (those involving a semicolon) to converting each statement at a time.*) 520 | 521 | 522 | StatementToMATLAB[HoldPattern[CompoundExpression[firstStatement_, rest__]]] := ( 523 | StatementToMATLAB[firstStatement] <> "\n" <> StatementToMATLAB[CompoundExpression[rest]] 524 | ); 525 | 526 | 527 | StatementToMATLAB[HoldPattern[CompoundExpression[singleStatement_]]] := ( 528 | StatementToMATLAB[singleStatement] 529 | ); 530 | 531 | 532 | (* ::Text:: *) 533 | (*When we get down to a single statement, we will sometimes want to interpret this as returning a value, and so we turn lone statements that do not match any other pattern into assignments, using the variable $M2MReturnSymbol to track what we are naming the return value.*) 534 | 535 | 536 | $M2MReturnSymbol = retval; 537 | 538 | 539 | StatementToMATLAB[else_] := ( 540 | StatementToMATLAB[Set[Evaluate[$M2MReturnSymbol], else]] 541 | ); 542 | 543 | 544 | (* ::Text:: *) 545 | (*We now can define what it means to set a variable in MATLAB. Note that we do not convert DelayedSet, as there is no equivalent in MATLAB.*) 546 | 547 | 548 | StatementToMATLAB[HoldPattern[Set[var_, expr_]]] := SymbolName[var] <> " = " <> ExpressionToMATLAB[expr] <> ";"; 549 | 550 | 551 | (* ::Text:: *) 552 | (*Though we can represent conditional expressions using the "iif" MATLAB function, as we did above, it is useful to treat statements differently by converting calls to If into "if-else" blocks in MATLAB.*) 553 | 554 | 555 | StatementToMATLAB[HoldPattern[If[cond_,ift_]]]:=( 556 | "if " <> ExpressionToMATLAB[cond] <> "\n" <> 557 | "\t" <> StatementToMATLAB[ift] <> "\n" <> 558 | "end" 559 | ); 560 | 561 | 562 | StatementToMATLAB[HoldPattern[If[cond_,ift_,iff_]]]:=( 563 | "if " <> ExpressionToMATLAB[cond] <> "\n" <> 564 | "\t" <> StatementToMATLAB[ift] <> "\n" <> 565 | "else" <> "\n" <> 566 | "\t"<>StatementToMATLAB[iff] <>"\n"<> 567 | "end" 568 | ); 569 | 570 | 571 | (* ::Text:: *) 572 | (*TODO: fix indenting in the statements above.*) 573 | 574 | 575 | End[]; 576 | 577 | 578 | (* ::Subsection:: *) 579 | (*Compound Functions*) 580 | 581 | 582 | (* ::Text:: *) 583 | (*TODO: change signature to match FunctionToMATLAB.*) 584 | 585 | 586 | (* ::Subsubsection:: *) 587 | (*Usage Strings and Attributes*) 588 | 589 | 590 | SetAttributes[ExportFunctionToMATLAB, HoldAll]; 591 | SetAttributes[FunctionToMATLAB, HoldAll]; 592 | 593 | 594 | (* ::Subsubsection:: *) 595 | (*Implementations*) 596 | 597 | 598 | Begin["`Private`"]; 599 | 600 | 601 | ExportFunctionToMATLAB[directory_, fname_, {args__}, body_] := 602 | Export[dir <> fn <> ".m", FunctionToMATLAB[fname, {args}, body], "Text"]; 603 | 604 | 605 | FunctionToMATLAB[fname_, {args__}, body_] := Module[{ 606 | dir = ReleaseHold[directory], 607 | fn = ReleaseHold[fname], 608 | as = ReleaseHold[{args}], 609 | argsList, header, footer, 610 | contents 611 | }, 612 | CheckSymbol/@{args}; 613 | 614 | argsList = MATLABArgsList[{args}, ", "]; 615 | header = ( 616 | "% " <> fn <> " TODO: add documentation here.\n" <> 617 | "function " <> SymbolName[$M2MReturnSymbol] <> " = " <> fn <> argsList <> "\n" <> 618 | "% WARNING: This file was automatically generated by the M2M package for Mathematica.\n" <> 619 | "% Do not edit the following lines directly." 620 | ); 621 | footer = "end"; 622 | 623 | contents = header <> "\n" <> StatementToMATLAB[body] <> "\n" <> footer; 624 | contents 625 | 626 | (* TODO: Add metadata from the current notebook. *) 627 | ]; 628 | 629 | 630 | End[]; 631 | 632 | 633 | (* ::Section:: *) 634 | (*Epilouge*) 635 | 636 | 637 | EndPackage[]; 638 | -------------------------------------------------------------------------------- /src/Perturbation.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Perturbation*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["Perturbation`",{"QUDoc`"}]; 30 | 31 | 32 | Needs["QUDevTools`"]; 33 | Needs["Tensor`"]; 34 | 35 | 36 | $PerturbationsUsages = LoadUsages[FileNameJoin[{$QUDocumentationPath, "api-doc", "Perturbation.nb"}]]; 37 | 38 | 39 | (* ::Section:: *) 40 | (*Usage Declarations*) 41 | 42 | 43 | (* ::Subsection:: *) 44 | (*Magnus Expansion*) 45 | 46 | 47 | Unprotect[MagnusExpansionTerm,MagnusExpansion,MagnusConvergenceTest,ClearMagnusCache]; 48 | 49 | 50 | AssignUsage[MagnusExpansionTerm,$PerturbationsUsages]; 51 | AssignUsage[MagnusExpansion,$PerturbationsUsages]; 52 | AssignUsage[MagnusConvergenceTest,$PerturbationsUsages]; 53 | AssignUsage[ClearMagnusCache,$PerturbationsUsages]; 54 | 55 | 56 | (* ::Subsection::Closed:: *) 57 | (*Average Hamiltonian*) 58 | 59 | 60 | Unprotect[AverageHamiltonianTerm,AverageHamiltonian]; 61 | 62 | 63 | AssignUsage[AverageHamiltonianTerm,$PerturbationsUsages]; 64 | AssignUsage[AverageHamiltonian,$PerturbationsUsages]; 65 | 66 | 67 | (* ::Subsection::Closed:: *) 68 | (*Matrix Perturbations*) 69 | 70 | 71 | Unprotect[FirstOrderEigenvector,SecondOrderEigenvalue]; 72 | 73 | 74 | AssignUsage[FirstOrderEigenvector,$PerturbationsUsages]; 75 | AssignUsage[SecondOrderEigenvalue,$PerturbationsUsages]; 76 | 77 | 78 | (* ::Subsection:: *) 79 | (*Zassenhaus Expansion*) 80 | 81 | 82 | Unprotect[ZassenhausTerm,ZassenhausSeries,ZassenhausExpansion,ClearZassenhausCache]; 83 | 84 | 85 | AssignUsage[ZassenhausTerm,$PerturbationsUsages]; 86 | AssignUsage[ZassenhausSeries,$PerturbationsUsages]; 87 | AssignUsage[ZassenhausExpansion,$PerturbationsUsages]; 88 | AssignUsage[ClearZassenhausCache,$PerturbationsUsages]; 89 | 90 | 91 | (* ::Section:: *) 92 | (*Implementation*) 93 | 94 | 95 | Begin["`Private`"]; 96 | 97 | 98 | (* ::Subsection:: *) 99 | (*Magnus Expansion*) 100 | 101 | 102 | (* ::Text:: *) 103 | (*Clear memoized values*) 104 | 105 | 106 | Clear[MagnusGenerator,MagnusExpansionTermCached] 107 | 108 | 109 | ClearMagnusCache[]:=( 110 | DownValues[MagnusGenerator]=Part[DownValues[MagnusGenerator],{-1}]; 111 | DownValues[MagnusExpansionTermCached]=Part[DownValues[MagnusExpansionTermCached],{-1}];) 112 | 113 | 114 | (* ::Text:: *) 115 | (*Set Options*) 116 | 117 | 118 | Options[MagnusExpansionTerm]={Simplify->Identity,Chop->False,NIntegrate->False}; 119 | Options[MagnusGenerator]=Options[MagnusExpansionTerm]; 120 | Options[MagnusExpansionTermCached]=Options[MagnusExpansionTerm]; 121 | Options[MagnusExpansion]=Options[MagnusExpansionTerm]; 122 | Options[MagnusConvergenceTest]={NIntegrate->False}; 123 | 124 | 125 | (* ::Text:: *) 126 | (*Generator term for magnus expansion*) 127 | 128 | 129 | MagnusGenerator[{A_,t0_,tf_},{n_,j_},opt:OptionsPattern[]]:= 130 | MagnusGenerator[{A,t0,tf},{n,j},opt]= 131 | Block[{fn=OptionValue[Simplify]}, 132 | If[fn===True,fn=Simplify]; 133 | If[OptionValue[Chop],fn=Composition[fn,Chop]]; 134 | fn@Which[ 135 | j===1, 136 | Com[MagnusExpansionTerm[{A,t0,tf},n-1,opt],A[tf]], 137 | j===n-1, 138 | Com[MagnusExpansionTerm[{A,t0,tf},1,opt],A[tf],n-1], 139 | True, 140 | Total@Map[ 141 | Com[ 142 | MagnusExpansionTerm[{A,t0,tf},#,opt], 143 | MagnusGenerator[{A,t0,tf},{n-#,j-1},opt] 144 | ]&,Range[n-j] 145 | ] 146 | ] 147 | ]; 148 | 149 | 150 | (* ::Text:: *) 151 | (*Memoized Magnus expansion term*) 152 | 153 | 154 | MagnusExpansionTermCached[{A_,t0_,tf_},k_,opt:OptionsPattern[]]:= 155 | MagnusExpansionTermCached[{A,t0,tf},k,opt]= 156 | Block[{fn=OptionValue[Simplify]}, 157 | If[fn===True,fn=Simplify]; 158 | If[OptionValue[Chop],fn=Composition[fn,Chop]]; 159 | fn@If[k===1, 160 | If[OptionValue[NIntegrate], 161 | NIntegrate[A[t],{t,t0,tf}], 162 | Integrate[A[t],{t,t0,tf}] 163 | ], 164 | Total@Map[(BernoulliB[#]/#!)* 165 | If[OptionValue[NIntegrate], 166 | NIntegrate[MagnusGenerator[{A,t0,t1},{k,#},opt],{t1,t0,tf}], 167 | Integrate[MagnusGenerator[{A,t0,t1},{k,#},opt],{t1,t0,tf}] 168 | ]&, 169 | Range[k-1]] 170 | ] 171 | ]; 172 | 173 | 174 | 175 | 176 | (* ::Text:: *) 177 | (*Calling Magnus Expansion Term and sum of terms*) 178 | 179 | 180 | MagnusExpansionTerm[{A_,t0_,tf_},k_,opt:OptionsPattern[]]:= 181 | MagnusExpansionTermCached[{A,t0,tf},k,opt] 182 | 183 | MagnusExpansionTerm[{A_,tf_},k_,opt:OptionsPattern[]]:=MagnusExpansionTerm[{A,0,tf},k,opt] 184 | 185 | 186 | MagnusExpansion[{A_,t0_,tf_},order_,opt:OptionsPattern[]]:=Map[MagnusExpansionTerm[{A,t0,tf},#,opt]&,Range[order]]; 187 | MagnusExpansion[{A_,tf_},order_,opt:OptionsPattern[]]:=MagnusExpansion[{A,0,tf},order,opt] 188 | 189 | 190 | MagnusConvergenceTest[{A_,t0_,tf_},opts:OptionsPattern[]]:= 191 | If[OptionValue[NIntegrate], 192 | NIntegrate[Norm[A[t],"Frobenius"],{t,t0,tf}], 193 | Integrate[Norm[A[t],"Frobenius"],{t,t0,tf}] 194 | ] 195 | 196 | MagnusConvergenceTest[{A_,tf_},opts:OptionsPattern[]]:=MagnusConvergenceTest[{A,0,tf},opts] 197 | 198 | 199 | (* ::Subsection:: *) 200 | (*Average Hamiltonian*) 201 | 202 | 203 | Options[AverageHamiltonianTerm]=Options[MagnusGenerator]; 204 | Options[AverageHamiltonian]=Options[MagnusGenerator]; 205 | 206 | 207 | AverageHamiltonianTerm[{H_,t0_,tf_},k_,opt:OptionsPattern[]]:= 208 | (-I)^k*MagnusExpansionTerm[{H,t0,tf},k+1,opt]/(tf-t0) 209 | 210 | AverageHamiltonianTerm[{H_,tf_},k_,opt:OptionsPattern[]]:=AverageHamiltonianTerm[{H,0,tf},k,opt] 211 | 212 | 213 | AverageHamiltonian[{H_,t0_,tf_},order_,opt:OptionsPattern[]]:= 214 | Total[ 215 | Array[(-I)^(#-1)/(tf-t0)&,order+1]*MagnusExpansion[{H,t0,tf},order+1,opt] 216 | ] 217 | AverageHamiltonian[{H_,tf_},order_,opt:OptionsPattern[]]:=AverageHamiltonian[{H,0,tf},order,opt] 218 | 219 | 220 | (* ::Subsection::Closed:: *) 221 | (*Matrix Perturbations*) 222 | 223 | 224 | FirstOrderEigenvector[A_,B_,\[Lambda]_:All,output_:"sum"]:= 225 | Block[ 226 | { 227 | IP, 228 | dim,inds,deg,M,k, 229 | eigs,cureig, 230 | v,eigspacedirections, 231 | vals,vecs,valshc,vecshc,valOrder, 232 | pertvecs1,pertvals1 233 | }, 234 | IP[v1_,v2_]:=Simplify[Conjugate[v1].v2]; 235 | dim=Length[A]; 236 | 237 | (* First we get the unperturbed eigensystem of both A and A\[HermitianConjugate]*) 238 | {vals,vecs}=Eigensystem[A]//Simplify; 239 | If[A===Simplify[A\[HermitianConjugate]], 240 | {valshc,vecshc}={vals,vecs}, 241 | {valshc,vecshc}=Eigensystem[FullSimplify[A\[HermitianConjugate]]]//Simplify; 242 | valOrder=Flatten@DeleteDuplicates@Table[Select[Table[m,{m,dim}],FullSimplify[Conjugate[valshc[[n]]]-vals[[#]]]==0&],{n,dim}]; 243 | valshc=Permute[valshc,valOrder]; 244 | vecshc=Permute[vecshc,valOrder]; 245 | ]; 246 | 247 | (* Next we determine exactly which eigenvalues we're supposed to perturb *) 248 | eigs= 249 | Which[ 250 | \[Lambda]===All,DeleteDuplicates[vals], 251 | ListQ[\[Lambda]],\[Lambda], 252 | True,{\[Lambda]} 253 | ]; 254 | 255 | (* Initialize the output *) 256 | pertvecs1={}; 257 | 258 | (* Finally we loop thrugh eigs and calculate the perturbation on each one *) 259 | (* This algorithm can be found, eg, on pg 15 of Perturbation Methods by Hinch*) 260 | For[k=1,k<=Length[eigs],k++, 261 | cureig=eigs[[k]]; 262 | 263 | (* Get the indeces of the eigenvalues *) 264 | inds=Select[Table[m,{m,dim}],(vals[[#]]==cureig)&]; 265 | 266 | (* deg is the ammount of degeneracy*) 267 | deg=Length[inds]; 268 | If[deg==0,Print["Eigenvalue "<>ToString[cureig]<>" not found"];Abort[];]; 269 | 270 | (* M is the degeneracy matrix; it's eigenvalues are the first order perturbations. If deg=1, M is 1x1*) 271 | M=Table[IP[vecshc[[i]],B.vecs[[j]]]/IP[vecshc[[i]],vecs[[i]]],{i,deg},{j,deg}]; 272 | {pertvals1,v}=Eigensystem[M]; 273 | eigspacedirections=Table[Plus@@(DiagonalMatrix[v[[m]]].vecs[[inds]]),{m,deg}]; 274 | 275 | (* We need the first order perturbed vectors in order to get the 2nd order value*) 276 | pertvecs1=Append[pertvecs1, 277 | Sum[ 278 | If[MemberQ[inds,i],0, 279 | (IP[vecshc[[i]],B.#]vecs[[i]])/((cureig-vals[[i]])IP[vecshc[[i]],vecs[[i]]]) 280 | ], 281 | {i,dim} 282 | ]&/@eigspacedirections 283 | ]; 284 | ]; 285 | 286 | (* Return all perturbations *) 287 | pertvecs1 288 | 289 | ] 290 | 291 | 292 | SecondOrderEigenvalue[A_,B_,\[Lambda]_:All,output_:"sum"]:= 293 | Block[ 294 | { 295 | IP, 296 | dim,inds,deg,M,k, 297 | eigs,cureig, 298 | v,eigspacedirections, 299 | vals,vecs,valshc,vecshc,valOrder, 300 | pertvecs1,pertvals1,pertvals2 301 | }, 302 | IP[v1_,v2_]:=Simplify[Conjugate[v1].v2]; 303 | dim=Length[A]; 304 | 305 | (* First we get the unperturbed eigensystem of both A and A\[HermitianConjugate]*) 306 | {vals,vecs}=Eigensystem[A]//Simplify; 307 | If[A===Simplify[A\[HermitianConjugate]], 308 | {valshc,vecshc}={vals,vecs}, 309 | {valshc,vecshc}=Eigensystem[A\[HermitianConjugate]]//Simplify; 310 | (*valOrder=Flatten@DeleteDuplicates@Table[Select[Table[m,{m,dim}],Simplify[Conjugate[valshc[[n]]]-vals[[#]]]==0&],{n,dim}];*) 311 | (*valOrder=FindPermutation[FullSimplify[Conjugate[valshc]],vals];*) 312 | valOrder=InversePermutation[Total/@Transpose[Map[(#==0)/.{True->0,False->1}&,Outer[Conjugate[#1].#2&,vecs,vecshc,1]//Simplify,{2}]*Table[n,{n,dim}]]]; 313 | valshc=Permute[valshc,valOrder]; 314 | vecshc=Permute[vecshc,valOrder]; 315 | ]; 316 | 317 | (* Next we determine exactly which eigenvalues we're supposed to perturb *) 318 | eigs= 319 | Which[ 320 | \[Lambda]===All,DeleteDuplicates[vals], 321 | ListQ[\[Lambda]],\[Lambda], 322 | True,{\[Lambda]} 323 | ]; 324 | 325 | (* Finally we loop thrugh eigs and calculate the perturbation on each one *) 326 | (* This algorithm can be found, eg, on pg 15 of Perturbation Methods by Hinch*) 327 | For[k=1,k<=Length[eigs],k++, 328 | cureig=eigs[[k]]; 329 | 330 | (* Get the indeces of the eigenvalues *) 331 | inds=Select[Table[m,{m,dim}],(vals[[#]]==cureig)&]; 332 | 333 | (* deg is the ammount of degeneracy*) 334 | deg=Length[inds]; 335 | If[deg==0,Print["Eigenvalue "<>ToString[cureig]<>" not found"];Abort[];]; 336 | 337 | (* M is the degeneracy matrix; it's eigenvalues are the first order perturbations. If deg=1, M is 1x1*) 338 | M=Table[IP[vecshc[[i]],B.vecs[[j]]]/IP[vecshc[[i]],vecs[[i]]],{i,deg},{j,deg}]; 339 | {pertvals1,v}=Eigensystem[M]; 340 | eigspacedirections=Table[Plus@@(DiagonalMatrix[v[[m]]].vecs[[inds]]),{m,deg}]; 341 | 342 | (* We need the first order perturbed vectors in order to get the 2nd order value*) 343 | pertvecs1=Sum[ 344 | If[MemberQ[inds,i],0, 345 | (IP[vecshc[[i]],B.#]vecs[[i]])/((cureig-vals[[i]])IP[vecshc[[i]],vecs[[i]]]) 346 | ], 347 | {i,dim} 348 | ]&/@eigspacedirections; 349 | 350 | (* Finally what we're after*) 351 | pertvals2=Table[ 352 | With[ 353 | {e=Plus@@(DiagonalMatrix[Conjugate[v[[i]]]].vecshc[[inds]])}, 354 | (IP[e,B.pertvecs1[[i]]]-pertvals1[[i]]IP[e,pertvecs1[[i]]])/IP[e,eigspacedirections[[i]]] 355 | ], 356 | {i,deg} 357 | ]//Simplify; 358 | eigs[[k]]=cureig+pertvals1+pertvals2; 359 | ]; 360 | 361 | (* Return all perturbations *) 362 | Flatten@eigs 363 | ] 364 | 365 | 366 | (* ::Subsection:: *) 367 | (*Zassenhaus Expansion*) 368 | 369 | 370 | (* ::Text:: *) 371 | (*The generator form is taken from "Efficient Computation of the Zassenhaus formula" F. Casas, A. Murua, M. Nadinic, Computer Physics Communications 183 (2012) 2386-2391.*) 372 | 373 | 374 | (* ::Subsubsection:: *) 375 | (*Generator Function*) 376 | 377 | 378 | (* ::Text:: *) 379 | (*Clear memoized values*) 380 | 381 | 382 | Clear[ZassenhausGenerator,ZassenhausTermCached]; 383 | 384 | 385 | ClearZassenhausCache[]:=( 386 | DownValues[ZassenhausGenerator]=Part[DownValues[ZassenhausGenerator],{-1}]; 387 | DownValues[ZassenhausTermCached]=Part[DownValues[ZassenhausTermCached],{-1}];) 388 | 389 | 390 | ZassenhausGenerator[X_,Y_,n_,k_]:= 391 | ZassenhausGenerator[X,Y,n,k]= 392 | If[n===1, 393 | Total@Map[ 394 | (-1)^k/(#!(k-#)!) Com[Y,Com[X,Y,#],k-#]&, 395 | Range[k] 396 | ], 397 | Total@Map[(-1)^#/(#!) 398 | Com[ 399 | ZassenhausTermCached[X,Y,n], 400 | ZassenhausGenerator[X,Y,n-1,k-n*#],# 401 | ]&, 402 | Range[0,Floor[k/n]-1] 403 | ] 404 | ]; 405 | 406 | 407 | ZassenhausTermCached[X_,Y_,n_]:= 408 | ZassenhausTermCached[X,Y,n]= 409 | Which[ 410 | n===0, X, 411 | n===1, Y, 412 | IntegerQ[n], (1/n)*ZassenhausGenerator[X,Y,If[n>=5,Floor[(n-1)/2],1],n-1] 413 | ] 414 | 415 | 416 | (* ::Subsubsection:: *) 417 | (*Expansion Terms*) 418 | 419 | 420 | ZassenhausTerm[X_,Y_,n_]:=ZassenhausTermCached[X,Y,n] 421 | 422 | 423 | ZassenhausSeries[X_,Y_,n_]:=ZassenhausTerm[X,Y,#]&/@Range[0,n] 424 | 425 | 426 | (* ::Subsubsection:: *) 427 | (*MatrixExp Expansion*) 428 | 429 | 430 | (* ::Text:: *) 431 | (*Cached function*) 432 | 433 | 434 | Clear[ZassenhausExpansionCached]; 435 | 436 | 437 | ZassenhausExpansionCached[\[Lambda]_,X_,Y_,n_]:= 438 | ZassenhausExpansionCached[\[Lambda],X,Y,n]= 439 | Which[ 440 | n===0, 441 | MatrixExp[\[Lambda] X], 442 | n===1, 443 | ZassenhausExpansionCached[\[Lambda],X,Y,0].MatrixExp[\[Lambda] Y], 444 | IntegerQ[n], 445 | ZassenhausExpansionCached[\[Lambda],X,Y,n-1].MatrixExp[(\[Lambda]^n)*ZassenhausTerm[X,Y,n]] 446 | ] 447 | 448 | 449 | ZassenhausExpansion[\[Lambda]_:1,X_,Y_,n_]:=ZassenhausExpansionCached[\[Lambda],X,Y,n] 450 | 451 | 452 | (* ::Subsection::Closed:: *) 453 | (*End Private*) 454 | 455 | 456 | End[]; 457 | 458 | 459 | (* ::Section:: *) 460 | (*End Package*) 461 | 462 | 463 | (* ::Text:: *) 464 | (*The commented sections represent functions which need unprotection for memoization to work.*) 465 | 466 | 467 | Protect[MagnusExpansionTerm,MagnusExpansion,MagnusConvergenceTest,ClearMagnusCache]; 468 | Protect[AverageHamiltonianTerm,AverageHamiltonian]; 469 | Protect[FirstOrderEigenvector,SecondOrderEigenvalue]; 470 | Protect[ZassenhausSeries,ZassenhausTerm,ZassenhausExpansion,ClearZassenhausCache]; 471 | 472 | 473 | EndPackage[]; 474 | -------------------------------------------------------------------------------- /src/Predicates.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Predicates Package*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["Predicates`",{"QUDoc`"}]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | 38 | 39 | $PredicatesUsages = LoadUsages[FileNameJoin[{$QUDocumentationPath, "api-doc", "Predicates.nb"}]]; 40 | 41 | 42 | (* ::Section:: *) 43 | (*Usage Declarations*) 44 | 45 | 46 | (* ::Subsection::Closed:: *) 47 | (*Fuzzy Logic*) 48 | 49 | 50 | Unprotect[PossiblyTrueQ,PossiblyFalseQ,PossiblyNonzeroQ]; 51 | 52 | 53 | AssignUsage[PossiblyTrueQ,$PredicatesUsages]; 54 | AssignUsage[PossiblyFalseQ,$PredicatesUsages]; 55 | AssignUsage[PossiblyNonzeroQ,$PredicatesUsages]; 56 | 57 | 58 | (* ::Subsection::Closed:: *) 59 | (*Numbers and Lists*) 60 | 61 | 62 | Unprotect[AnyQ,AnyMatchQ,AnyElementQ,AllQ,AllMatchQ,AllElementQ,AnyNonzeroQ,AnyPossiblyNonzeroQ]; 63 | 64 | 65 | AssignUsage[AnyQ,$PredicatesUsages]; 66 | AssignUsage[AnyMatchQ,$PredicatesUsages]; 67 | AssignUsage[AnyElementQ,$PredicatesUsages]; 68 | 69 | 70 | AssignUsage[AllQ,$PredicatesUsages]; 71 | AssignUsage[AllMatchQ,$PredicatesUsages]; 72 | AssignUsage[AllElementQ,$PredicatesUsages]; 73 | 74 | 75 | AssignUsage[AnyNonzeroQ,$PredicatesUsages]; 76 | AssignUsage[AnyPossiblyNonzeroQ,$PredicatesUsages]; 77 | 78 | 79 | (* ::Subsection::Closed:: *) 80 | (*Symbolic Expressions*) 81 | 82 | 83 | Unprotect[SymbolQ,ScalarQ,CoefficientSymbolQ,CoefficientQ]; 84 | 85 | 86 | AssignUsage[SymbolQ,$PredicatesUsages]; 87 | AssignUsage[ScalarQ,$PredicatesUsages]; 88 | AssignUsage[CoefficientSymbolQ,$PredicatesUsages]; 89 | AssignUsage[CoefficientQ,$PredicatesUsages]; 90 | 91 | 92 | (* ::Subsection::Closed:: *) 93 | (*Matrices and Vectors*) 94 | 95 | 96 | Unprotect[NonzeroDimQ,DiagonalMatrixQ,PureStateQ,ColumnVectorQ,RowVectorQ,GeneralVectorQ]; 97 | 98 | 99 | AssignUsage[NonzeroDimQ,$PredicatesUsages]; 100 | AssignUsage[DiagonalMatrixQ,$PredicatesUsages]; 101 | AssignUsage[PureStateQ,$PredicatesUsages]; 102 | AssignUsage[ColumnVectorQ,$PredicatesUsages]; 103 | AssignUsage[RowVectorQ,$PredicatesUsages]; 104 | AssignUsage[GeneralVectorQ,$PredicatesUsages]; 105 | 106 | 107 | (* ::Section:: *) 108 | (*Implementation*) 109 | 110 | 111 | Begin["`Private`"]; 112 | 113 | 114 | (* ::Subsection::Closed:: *) 115 | (*Fuzzy Logic*) 116 | 117 | 118 | PossiblyTrueQ[expr_]:=\[Not]TrueQ[\[Not]expr] 119 | 120 | 121 | PossiblyFalseQ[expr_]:=\[Not]TrueQ[expr] 122 | 123 | 124 | PossiblyNonzeroQ[expr_]:=PossiblyTrueQ[expr!=0] 125 | 126 | 127 | (* ::Subsection::Closed:: *) 128 | (*Numbers and Lists*) 129 | 130 | 131 | AnyQ[cond_, L_] := Fold[Or, False, cond /@ L] 132 | AllQ[cond_, L_] := Fold[And, True, cond /@ L] 133 | 134 | 135 | AnyMatchQ[cond_, L_] := AnyQ[MatchQ[#,cond]&,L] 136 | AllMatchQ[cond_, L_] := AllQ[MatchQ[#,cond]&,L] 137 | 138 | 139 | AnyElementQ[cond_,L_]:=AnyQ[cond,Flatten[L]] 140 | AllElementQ[cond_, L_] := AllQ[cond,Flatten[L]] 141 | 142 | 143 | AnyNonzeroQ[L_]:=AnyElementQ[#!=0&,L] 144 | 145 | 146 | AnyPossiblyNonzeroQ[expr_]:=AnyElementQ[PossiblyNonzeroQ,expr] 147 | 148 | 149 | (* ::Subsection::Closed:: *) 150 | (*Symbolic Expressions*) 151 | 152 | 153 | SymbolQ[a_]:= 154 | And[ 155 | SameQ[Head[a],Symbol], 156 | SameQ[DownValues[a],{}] 157 | ]; 158 | 159 | 160 | ScalarQ[a_]:=Or[NumericQ[a],SymbolQ[a],StringQ[a]] 161 | 162 | 163 | CoefficientSymbolQ[a_]:= 164 | And[SymbolQ[a], 165 | SameQ[DownValues[a],{}], 166 | SameQ[#,{}]||SameQ[#,{Temporary}]||MemberQ[#,NumericFunction]&[Attributes@a] 167 | ] 168 | 169 | 170 | CoefficientQ[expr_]:= 171 | Or[ScalarQ[expr], 172 | With[{head=Head[expr]}, 173 | And[ 174 | MatchQ[expr,_[__]], 175 | Or[StringQ[head],CoefficientSymbolQ[head]], 176 | AllQ[ScalarQ[#]||CoefficientQ[#]&, List@@expr] 177 | ] 178 | ]] 179 | 180 | 181 | (* ::Subsection::Closed:: *) 182 | (*Matrices and Vectors*) 183 | 184 | 185 | NonzeroDimQ:=\[Not]MemberQ[Dimensions[#],0]& 186 | 187 | 188 | DiagonalMatrixQ[A_?MatrixQ]:= 189 | If[SquareMatrixQ[A], 190 | Module[{n=Length[A],dlist}, 191 | dlist=List/@Plus[Range[0,n-1]*(n+1),1]; 192 | Total[Abs[Delete[Flatten[A],dlist]]]===0], 193 | False 194 | ]; 195 | 196 | 197 | PureStateQ[A_]:=TrueQ[Tr[ConjugateTranspose[A].A]==1]; 198 | 199 | 200 | ColumnVectorQ[v_]:=MatchQ[Dimensions[v],{_,1}]; 201 | 202 | 203 | RowVectorQ[v_]:=MatchQ[Dimensions[v],{1,_}]; 204 | 205 | 206 | GeneralVectorQ[v_]:=Or[VectorQ[v],ColumnVectorQ[v]]; 207 | 208 | 209 | (* ::Subsection::Closed:: *) 210 | (*End Private*) 211 | 212 | 213 | End[]; 214 | 215 | 216 | (* ::Section::Closed:: *) 217 | (*End Package*) 218 | 219 | 220 | Protect[PossiblyTrueQ,PossiblyFalseQ,PossiblyNonzeroQ]; 221 | Protect[AnyQ,AnyMatchQ,AnyElementQ,AllQ,AllMatchQ,AllElementQ,AnyNonzeroQ,AnyPossiblyNonzeroQ]; 222 | Protect[SymbolQ,CoefficientQ]; 223 | Protect[NonzeroDimQ,DiagonalMatrixQ,PureStateQ,ColumnVectorQ,RowVectorQ,GeneralVectorQ]; 224 | 225 | 226 | EndPackage[]; 227 | -------------------------------------------------------------------------------- /src/QUDevTools.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*QUDevTools*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["QUDevTools`",{"QUDoc`"}]; 30 | 31 | 32 | (* ::Subsection::Closed:: *) 33 | (*Note*) 34 | 35 | 36 | (* ::Text:: *) 37 | (*Because this package defines LoadUsages and AssignUsage, functions from this package cannot (easily) be documented in the way that other packages are with auxilliary notebooks.*) 38 | 39 | 40 | (* ::Section:: *) 41 | (*Usage Declaration*) 42 | 43 | 44 | (* ::Subsection::Closed:: *) 45 | (*Backwards Compatibility*) 46 | 47 | 48 | Polyfill::usage= "Polyfill[ver, expr] checks if the current version of mathematica is less than 'ver', and if so evaluates expr."; 49 | 50 | 51 | (* ::Subsubsection:: *) 52 | (*Pre Version 10*) 53 | 54 | 55 | Polyfill[10, 56 | NormalMatrixQ::usage = "Returns True if the object is a normal matrix"; 57 | SquareMatrixQ::usage = "Returns True if and only if the argument is a square matrix"; 58 | PositiveSemidefiniteMatrixQ::usage = "Returns True if and only if the chopped eigenvalues of the argument are non-negative."; 59 | Keys::usage = "Keys[{key1->val1,key2->val2,...}] gives a list of the keyj in a list of rules."; 60 | ]; 61 | 62 | 63 | (* ::Subsection::Closed:: *) 64 | (*QuantumUtils Options*) 65 | 66 | 67 | QuantumUtilsOptions::usage = "QuantumUtilsOptions[] returns a list of options, formatted as Rules, that configure the QuantumUtils` package."; 68 | $QUDocumentationPath::usage = "$QUDocumentationPath returns the path to documentation for QuantumUtils`."; 69 | $QUSourcePath::usage = "$QUSourcePath returns the path to the source folder for QuantumUtils`."; 70 | $QUTestingPath::usage = "$QUTesting returns the path to the test folder for QuantumUtils`."; 71 | 72 | 73 | (* ::Subsection::Closed:: *) 74 | (*Function Options*) 75 | 76 | 77 | InheritOptions::usage = "InheritOptions[fn_, {baseFns__}, newOptions_] defines options for fn by adding the options for each of the symbols listed in baseFns, along with new and possibly overriden options defined in newOptions."; 78 | 79 | 80 | FilterOptions::usage = "FilterOptions[function, opt1, opt2, opt3,...] returns a Sequence of those options in opt1,opt2,... which are Options of the given function. 81 | FilterOptions[{function1,function2,...}, opt1, opt2, opt3,...] returns a Sequence of those options in opt1,opt2,... which are Options of any of the given functions. 82 | FilterOptions[{distributor,n}, function, opt1, opt2, opt3,...] for those selected options with value Head distributor, sets the returned option value to the n'th argument of distributor. 83 | FilterOptions[{distributor,n}, {function1,function2,...}, opt1, opt2, opt3,...] for those selected options with value Head distributor, sets the returned option value to the n'th argument of distributor."; 84 | 85 | 86 | FilterOptions::toomany = "Expecting at least `1` option values for `2`; `3` received."; 87 | 88 | 89 | (* ::Subsection::Closed:: *) 90 | (*Creating Tables*) 91 | 92 | 93 | DescriptiveTable::usage = "DescriptiveTable[headers,content,OptionsPattern[GridBox]] generates a new cell containing a table. The first row of the table contains the header strings provided in headers in bold font. The rest of the table is filled in with content."; 94 | DescriptiveFillInTable::usage = "DescriptiveFillInTable[headers,rows,OptionsPattern[GridBox]] invokes DescriptiveTable to generate a new cell containing a table. The first row of the table contains the header strings provided in headers in bold font. The rest of the table has the given number of rows, with each table element a placeholder."; 95 | 96 | 97 | DisplayOptions::usage = "DisplayOptions[TargetFunction] prints a human readable cell describing the options of a given function. Assumes all options have usage text."; 98 | 99 | 100 | (* ::Subsection::Closed:: *) 101 | (*Usage Strings*) 102 | 103 | 104 | (* 105 | The AssignUsage function is heavily based on StackExchange: 106 | http://mathematica.stackexchange.com/questions/3941/managing-formatted-usage-messages-in-wolfram-workbench 107 | *) 108 | 109 | 110 | Attributes[AssignUsage] = {HoldFirst}; 111 | 112 | 113 | LoadUsages::usage = "LoadUsages[nbName] loads usage strings from a tagged cells in notebook, such that the strings can later be applied using AssignUsage[]. For more details, see the examples in doc/."; 114 | UsageData::usage = "UsageData[] represents usage strings loaded using LoadUsages[]."; 115 | AssignUsage::usage = "AssignUsage[symbol, usageData] sets symbol::usage to be drawn from the usage data usageData made by running LoadUsages[] with a name corresponding to symbol. 116 | AssignUsage[codeSymbol->docSymbol, usageData] sets codeSymbol::usage to be drawn from the usage data usageData made by running LoadUsages[] with a name corresponding to docSymbol. 117 | AssignUsage[{a1,a2,a3,...}, usageData] calls AssignUsage[a, usageData] on each of the a's."; 118 | 119 | 120 | (* ::Subsection::Closed:: *) 121 | (*Links and Buttons*) 122 | 123 | 124 | NotebookLink::usage = "NotebookLink[notebookFile_,name_,description_] generates a cell containing a link to another notebook, with a description."; 125 | 126 | 127 | SourceCodeButton::usage = "SourceCodeButton[] creates a button to the source code of the .m file with the same name as the current document." 128 | 129 | 130 | QUPackages::usage = "Creates links to documentation notebooks for index.nb." 131 | 132 | 133 | Tutorials::usage = "Creates links to tutorial notebooks for index.nb." 134 | 135 | 136 | (* ::Subsection::Closed:: *) 137 | (*Unit Testing Framework*) 138 | 139 | 140 | TestCase::usage = "TestCase[name,expr] generates a new tests case named 'name' that asserts that 'expr' evaluates to True."; 141 | RunTest::usage = "RunTest[name->expr] runs an instance of TestCase and returns if the result was True, False or returned an Error. RunTest is Listable for lists of tests."; 142 | 143 | 144 | (* ::Subsection::Closed:: *) 145 | (*Messages*) 146 | 147 | 148 | AssignUsage::nousg = "No usage message in `1` for symbol `2` found; using a blank message instead."; 149 | 150 | 151 | (* ::Section:: *) 152 | (*Implementation*) 153 | 154 | 155 | Begin["`Private`"]; 156 | 157 | 158 | (* ::Subsection::Closed:: *) 159 | (*Backwards Compatibility*) 160 | 161 | 162 | (* ::Subsubsection:: *) 163 | (*Polyfill Function*) 164 | 165 | 166 | SetAttributes[Polyfill, HoldAllComplete]; 167 | 168 | Polyfill[goodVersion_, expr_] := 169 | If[$VersionNumber < goodVersion, 170 | ReleaseHold[HoldComplete[expr]] 171 | ]; 172 | 173 | 174 | (* ::Subsubsection:: *) 175 | (*Pre Version 10*) 176 | 177 | 178 | Polyfill[10, 179 | NormalMatrixQ[M_]:=M.ConjugateTranspose[M]===ConjugateTranspose[M].M; 180 | SquareMatrixQ[M_]:=TrueQ[MatrixQ[M]&&Dimensions[M][[1]]==Dimensions[M][[2]]]; 181 | PositiveSemidefiniteMatrixQ[M_?SquareMatrixQ]:=With[{evals=Eigenvalues[M]},Not[MemberQ[NonNegative[evals],False]]&&Not[Norm[evals]==0]]; 182 | SetAttributes[Keys,Listable];Keys[Rule[expr_,_]]:=expr; 183 | ]; 184 | 185 | 186 | (* ::Subsection::Closed:: *) 187 | (*QuantumUtils Options*) 188 | 189 | 190 | QuantumUtilsOptions[] := QuantumUtilsOptions[] = Module[{opts}, 191 | opts = QuantumUtilsOptions /. Options[$FrontEnd]; 192 | If[ 193 | opts === QuantumUtilsOptions, 194 | {}, 195 | opts 196 | ] 197 | ] 198 | 199 | 200 | $QUDocumentationPath = DocumentationPath /. QuantumUtilsOptions[]; 201 | $QUSourcePath = SourcePath /. QuantumUtilsOptions[]; 202 | $QUTestingPath = TestingPath /. QuantumUtilsOptions[]; 203 | 204 | 205 | (* ::Subsection::Closed:: *) 206 | (*Function Options*) 207 | 208 | 209 | InheritOptions[fn_,{baseFns__},newOptions_]:=( 210 | Options[fn]=DeleteDuplicates[Join[ 211 | newOptions, 212 | Sequence@@Map[Options,{baseFns}] 213 | ],First@#1==First@#2&]; 214 | ) 215 | 216 | 217 | FilterOptions[function_,options___Rule]:=Apply[Sequence, FilterRules[{options},Options[function]]] 218 | FilterOptions[{function__},options___Rule]:=Apply[Sequence, FilterRules[{options},Options/@{function}]] 219 | FilterOptions[{distributor_,n_Integer},args___]:=Apply[ 220 | Sequence, 221 | {FilterOptions[args]} /. 222 | Rule[option_,distributor[values__]]:>If[Length[{values}]>=n, 223 | option->{values}[[n]], 224 | Message[FilterOptions::toomany,n,option,Length[{values}]]; 225 | ] 226 | ] 227 | 228 | 229 | (* ::Subsection::Closed:: *) 230 | (*Tables*) 231 | 232 | 233 | (* ::Subsubsection:: *) 234 | (*Descriptive Tables*) 235 | 236 | 237 | DescriptiveTable[headers_,content_,opt:OptionsPattern[GridBox]]:=Module[{headStyle}, 238 | headStyle[str_]:=StyleBox[str,Bold,"Text"]; 239 | CellPrint@Cell[ 240 | BoxData[ 241 | GridBox[ 242 | Prepend[ 243 | content, 244 | headStyle/@headers 245 | ], 246 | opt, 247 | GridBoxAlignment -> {"Columns" -> {{Left}}}, 248 | GridBoxDividers->{"Rows"->{{True}},"Columns"->{{False}}} 249 | ] 250 | ], 251 | "Text" 252 | ] 253 | ] 254 | 255 | 256 | DescriptiveFillInTable[headers_,rows_,opt:OptionsPattern[GridBox]]:=DescriptiveTable[headers,ConstantArray["\[Placeholder]",{rows,Length@headers}],opt] 257 | 258 | 259 | (* ::Subsubsection:: *) 260 | (*Displaying Options*) 261 | 262 | 263 | DisplayOptions[TargetFunction_]:=Module[{options,headers,content,textFormat,opt}, 264 | options=Options@TargetFunction; 265 | headers={"Option","Default Value","Description"}; 266 | textFormat[option_]:=Module[{box}, 267 | Which[ 268 | Head[option]===String, 269 | StyleBox["No description available.","Text"], 270 | Head[option::usage]===MessageName, 271 | StyleBox["No description available.","Text"], 272 | Head[option::usage]===String, 273 | StyleBox[option::usage,"Text"], 274 | True, 275 | ToBoxes[option::usage] 276 | ] 277 | ]; 278 | content={MakeBoxes[#1],MakeBoxes[#2],textFormat[#1]}&@@@options; 279 | opt=ColumnWidths->{Automatic,Automatic,Scaled[.5]}; 280 | DescriptiveTable[headers,content,opt] 281 | ] 282 | 283 | 284 | (* ::Subsection::Closed:: *) 285 | (*Usage Strings*) 286 | 287 | 288 | LoadUsages[nbName_] := Module[{notebook, usageData, processCell, possibleBoxToString}, 289 | notebook = Quiet[Get[nbName]]; 290 | 291 | possibleBoxToString[elem_]:=If[StringQ[elem], 292 | elem, 293 | ToString[ 294 | DisplayForm[elem]/.StyleBox[boxes_,"Input",args___]:>StyleBox[boxes,"Input",FontFamily->"Courier",args], 295 | StandardForm] 296 | ]; 297 | 298 | processCell[contents_]:=If[ 299 | StringQ[contents], 300 | contents, 301 | StringJoin@Map[possibleBoxToString,First@contents,1] 302 | ]; 303 | 304 | (*It is a waste of time for parallel kernels to load documentation*) 305 | If[Not[notebook === $Failed] && $KernelID==0, 306 | usageData = Cases[notebook, 307 | Cell[contents_, ___, CellTags -> tag_, ___] /; 308 | StringMatchQ[tag, __ ~~ "::usage"] :> 309 | ( 310 | StringReplace[tag, "::usage" -> ""] -> 311 | processCell[contents] 312 | ), 313 | Infinity]; 314 | 315 | UsageData @@ usageData, 316 | 317 | UsageData[] 318 | ] 319 | ] 320 | 321 | 322 | Format[usageData_UsageData] := Interpretation[UsageData, "UsageData"][Interpretation[ 323 | Grid[List@@List@@@usageData, Alignment -> Left], 324 | Null] 325 | ] 326 | 327 | 328 | AssignUsage[codeSymb_Symbol->docSymb_Symbol, usageData_UsageData] := Module[{docName}, 329 | If[$KernelID == 0, 330 | docName = SymbolName @ Unevaluated[docSymb]; 331 | If[FreeQ[usageData, (docName -> _)], 332 | Message[AssignUsage::nousg, usageData, HoldForm[docSymb]]; 333 | MessageName[docSymb, "usage"] = ""; 334 | $Failed, 335 | MessageName[codeSymb, "usage"] = docName /. List @@ usageData 336 | ], 337 | (*It is a waste of time for parallel kernels to load documentation*) 338 | MessageName[codeSymb, "usage"] = "QU function on parallel kernel."; 339 | ] 340 | ] 341 | 342 | AssignUsage[symb_Symbol, usageData_UsageData] := AssignUsage[symb->symb,usageData]; 343 | 344 | AssignUsage[{s:(__Rule|__Symbol)}, usageData_UsageData] := Map[AssignUsage[#, usageData]&, {s}]; 345 | 346 | 347 | (* ::Subsection::Closed:: *) 348 | (*Links and Buttons*) 349 | 350 | 351 | NotebookLink[notebookFile_,name_,description_]:=Module[{headStyle}, 352 | headStyle[str_]:=StyleBox[str,Bold,"Text"]; 353 | CellPrint@Cell[ 354 | BoxData[ 355 | GridBox[ 356 | {{ 357 | StyleBox[ToBoxes@Hyperlink[name,notebookFile],Bold,"Text"], 358 | StyleBox[description,"Text"] 359 | }}, 360 | GridBoxAlignment -> {"Columns" -> {{Left}}}, 361 | GridBoxDividers->{"Rows"->{{False}},"Columns"->{{False}}}, 362 | ColumnWidths->{Scaled[0.15],Scaled[.7]} 363 | ] 364 | ], 365 | "Text" 366 | ] 367 | ] 368 | 369 | 370 | SourceCodeButton[]:=Button["Open Source Code",Needs["QUDevTools`"];NotebookOpen[ 371 | FileNameJoin[{$QUSourcePath,FileBaseName[NotebookFileName[]]<>".m"}] 372 | ]] 373 | 374 | 375 | QUPackages:=( 376 | (NotebookLink["api-doc/"<>#1<>".nb",#1,#2];)&@@@Sort[{ 377 | {"ControlTheory","A package of tools commonly used in quantum control theory."}, 378 | {"GRAPE","An implementation of GRadient Ascent Pulse Engineering."}, 379 | {"Predicates","Provides type testing functions used by other packages."}, 380 | {"Perturbation","A collection of perturbative expansion tools such as the Magnus series, the Zassenhaus formula, and matrix perturbation power series."}, 381 | {"LindbladSolver","A set of functions for numerically or symbolically solving Schrodinger equations and Lindblad master equations."}, 382 | {"QSim","A general purpose quantum system time-evolution simulator whose primary objective is ease of use."}, 383 | {"QuantumChannel","Tools for constructing and manipulating quantum channels in various representations."}, 384 | {"QuantumSystems","Tools for modelling quantum systems of qudits, spins, cavities and circuits."}, 385 | {"Tensor","A package of tensor manipulations for multipartite quantum systems."}, 386 | {"Visualization","A suite of tools for displaying matrices, quantum states, data, etc."}, 387 | {"QUTesting","Functions for running unit tests for QuantumUtils packages."} 388 | }];) 389 | 390 | 391 | Tutorials:=( 392 | (NotebookLink["tutorials/"<>#1<>".nb",#2,#3];)&@@@Sort[{ 393 | {"notebook-name","Display Name","Description."} 394 | }];) 395 | 396 | 397 | (* ::Subsection::Closed:: *) 398 | (*Unit Testing Framework*) 399 | 400 | 401 | SetAttributes[TestCase, HoldAll]; 402 | 403 | TestCase[testVar_,name_, expr_] := ( 404 | AppendTo[Unevaluated[testVar], name -> Hold[expr]]; 405 | Null 406 | ); 407 | 408 | 409 | SetAttributes[RunTest,Listable]; 410 | 411 | 412 | RunTest[name_ -> expr_] := Module[{result}, 413 | result = Quiet[ 414 | Check[ReleaseHold[expr], $Failed] 415 | ]; 416 | 417 | If[Not[TrueQ @ result], 418 | Print[name <> ":\t" <> (result /. {False -> "Failed", $Failed -> "Error", _ -> "Did something very weird indeed."})] 419 | ]; 420 | 421 | name -> (result /. { 422 | True -> "T", 423 | False -> "F", 424 | $Failed -> "E", 425 | _ -> "?" 426 | }) 427 | ]; 428 | 429 | 430 | (* ::Subsection::Closed:: *) 431 | (*End Private*) 432 | 433 | 434 | End[]; 435 | 436 | 437 | (* ::Section::Closed:: *) 438 | (*End Package*) 439 | 440 | 441 | EndPackage[]; 442 | -------------------------------------------------------------------------------- /src/QUDoc.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Documentation*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["QUDoc`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | 38 | 39 | (* ::Text:: *) 40 | (*The following command makes running Get["QUDoc`"] or <".nb"}]; 87 | 88 | 89 | SetAttributes[QUDoc,HoldAll]; 90 | 91 | QUDoc[]:=(NotebookOpen[FileNameJoin[{$QUDocumentationPath, "index.nb"}]];) 92 | 93 | QUDoc[name_String]:=With[{ 94 | str=StringReplace[name,"`"->""]}, 95 | If[MemberQ[$DocumentNotebooks,str], 96 | NotebookOpen@QUDocPath[str];, 97 | Message[QUDoc::file,str<>".nb"] 98 | ]] 99 | 100 | QUDoc[sym_Symbol]:= 101 | With[{str=ToString[sym]}, 102 | If[MemberQ[$FunctionManifest,str], 103 | NotebookLocate[{QUDocPath[str/.$FunctionNotebooks],str<>"::usage"}];, 104 | Message[QUDoc::fn,str] 105 | ] 106 | ] 107 | 108 | 109 | (* ::Subsection::Closed:: *) 110 | (*Manifests*) 111 | 112 | 113 | (* ::Text:: *) 114 | (*These manifest variables are memoized so that they only load notebooks once (as this is a slow operation).*) 115 | 116 | 117 | (* ::Text:: *) 118 | (*Get a list of document notebooks stored in /docs/api-docs/*) 119 | 120 | 121 | $DocumentNotebooks:= 122 | $DocumentNotebooks= 123 | Block[{dir=Directory[],files}, 124 | SetDirectory[FileNameJoin[{$QUDocumentationPath, "api-doc"}]]; 125 | files=FileNames["*.nb"]; 126 | SetDirectory[dir]; 127 | StringReplace[files,".nb"->""] 128 | ]; 129 | 130 | 131 | (* ::Text:: *) 132 | (*Load a list of all functions in the documentation notebooks*) 133 | 134 | 135 | $FunctionNotebooks:= 136 | $FunctionNotebooks= 137 | Join@@( 138 | ReplaceAll[ 139 | List@@LoadUsages[QUDocPath[#]], 140 | {Rule[a_,_]:>Rule[a,#]} 141 | ]&/@$DocumentNotebooks); 142 | 143 | 144 | (* ::Text:: *) 145 | (*List of all Quantum Utils functions*) 146 | 147 | 148 | $FunctionManifest:=$FunctionManifest=First/@$FunctionNotebooks 149 | 150 | 151 | (* ::Subsection::Closed:: *) 152 | (*End Private*) 153 | 154 | 155 | End[]; 156 | 157 | 158 | (* ::Section::Closed:: *) 159 | (*End Package*) 160 | 161 | 162 | Protect[QUDoc]; 163 | 164 | 165 | EndPackage[]; 166 | -------------------------------------------------------------------------------- /src/QUTesting.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Unit Testing*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["QUTesting`",{"QUDoc`"}]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | 38 | 39 | $QUTestingUsages = LoadUsages[FileNameJoin[{$QUDocumentationPath, "api-doc", "QUTesting.nb"}]]; 40 | 41 | 42 | (* ::Section::Closed:: *) 43 | (*Usage Declarations*) 44 | 45 | 46 | AssignUsage[{TestResults,RunAllTests},$QUTestingUsages]; 47 | 48 | 49 | (* ::Section:: *) 50 | (*Implementation*) 51 | 52 | 53 | Begin["`Private`"]; 54 | 55 | 56 | (* ::Subsection:: *) 57 | (*Test Results*) 58 | 59 | 60 | (* ::Text:: *) 61 | (*Unit tests for a package "name.m" are stored in the /tests/ folder under under the name "nameTests.m"*) 62 | 63 | 64 | (* ::Text:: *) 65 | (*The results of the unit tests are stored in the variable nameTests`UnitTests`$TestResults, which is set to delayed evaluation so that the tests will not be run until the variable is called.*) 66 | 67 | 68 | (* ::Text:: *) 69 | (*To call the test results of an individual package use TestResults["name"]. For example: TestResults["Tensor"]*) 70 | 71 | 72 | SetAttributes[TestResults,HoldAll]; 73 | 74 | 75 | TestResults[package_]:= 76 | With[{name=ToString[package]}, 77 | Needs[name<>"Tests`",FileNameJoin[{$QUTestingPath,name<>"Tests.m"}]]; 78 | ToExpression[name<>"Tests`UnitTests`$TestResults"] 79 | ] 80 | 81 | 82 | TestResults[]:=Join@@Map[TestResults,$UnitTestManifest] 83 | 84 | 85 | (* ::Text:: *) 86 | (*Registered unit test packages*) 87 | 88 | 89 | $UnitTestManifest={ 90 | "Predicates", 91 | "Tensor", 92 | "QuantumSystems", 93 | "QuantumChannel", 94 | "LindbladSolver", 95 | "M2M", 96 | "QSim" 97 | }; 98 | 99 | 100 | (* ::Subsection:: *) 101 | (*Run All Tests*) 102 | 103 | 104 | (* ::Text:: *) 105 | (*This function checks how many unit tests passed, failed, or returned errors.*) 106 | 107 | 108 | RunAllTests[] := ( 109 | PrintTemporary["Running unit tests..."]; 110 | Block[{results,n,pass,fail,error}, 111 | results = TestResults[]; 112 | n = Length[results]; 113 | pass=Length@Select[results,MatchQ[#,_->"T"]&]; 114 | fail=Length@Select[results,MatchQ[#,_->"F"]&]; 115 | error=Length@Select[results,MatchQ[#,_->"E"]&]; 116 | Print[ToString[pass]<>" of "<>ToString[n]<> " unit tests passed."]; 117 | If[fail>0,Print[ToString[fail]<>" of "<>ToString[n]<> " unit tests failed."]; 118 | If[error>0,Print[ToString[error]<>" of "<>ToString[n]<> " unit tests returned errors."]]; 119 | ] 120 | ]) 121 | 122 | 123 | (* ::Subsection::Closed:: *) 124 | (*End Private*) 125 | 126 | 127 | End[]; 128 | 129 | 130 | (* ::Section:: *) 131 | (*End Package*) 132 | 133 | 134 | EndPackage[]; 135 | -------------------------------------------------------------------------------- /src/QuantumUtils.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | 6 | 7 | (* ::Subsection:: *) 8 | (*Copyright and License Information*) 9 | 10 | 11 | (* ::Text:: *) 12 | (*This package is part of QuantumUtils for Mathematica.*) 13 | (**) 14 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 15 | (**) 16 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 17 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 18 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 19 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 20 | (**) 21 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 22 | 23 | 24 | (* ::Subsection::Closed:: *) 25 | (*Preamble*) 26 | 27 | 28 | (* ::Text:: *) 29 | (*This package just exposes all user-end packages in Quantum Utils.*) 30 | 31 | 32 | BeginPackage["QuantumUtils`",{ 33 | "ControlTheory`", 34 | "GRAPE`", 35 | "LindbladSolver`", 36 | "Predicates`", 37 | "Perturbation`", 38 | "QSim`", 39 | "QuantumSystems`", 40 | "QuantumChannel`", 41 | "Tensor`", 42 | "Visualization`", 43 | "QUTesting`", 44 | "QUDoc`" 45 | }]; 46 | 47 | 48 | (* ::Section::Closed:: *) 49 | (*End Package*) 50 | 51 | 52 | EndPackage[]; 53 | -------------------------------------------------------------------------------- /src/Visualization.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Visualization Package*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preample*) 27 | 28 | 29 | BeginPackage["Visualization`",{"QUDoc`"}]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["Predicates`"]; 38 | Needs["Tensor`"]; 39 | 40 | 41 | $VisualizationUsages = LoadUsages[FileNameJoin[{$QUDocumentationPath, "api-doc", "Visualization.nb"}]]; 42 | 43 | 44 | (* ::Section:: *) 45 | (*Usage Declaration*) 46 | 47 | 48 | (* ::Subsection::Closed:: *) 49 | (*Matrices*) 50 | 51 | 52 | Unprotect[ComplexMatrixPlot,BlockForm,MatrixListForm]; 53 | 54 | 55 | AssignUsage[ComplexMatrixPlot,$VisualizationUsages]; 56 | AssignUsage[BlockForm,$VisualizationUsages]; 57 | AssignUsage[MatrixListForm,$VisualizationUsages]; 58 | 59 | 60 | (* ::Subsection::Closed:: *) 61 | (*Bloch Plots*) 62 | 63 | 64 | Unprotect[BlochPlot,BlochPlot2D,ListBlochPlot2D,BlochPlotColors,BlochPlotEndPoints,BlochPlotJoined,BlochPlotLabels]; 65 | 66 | 67 | AssignUsage[BlochPlot,$VisualizationUsages]; 68 | AssignUsage[BlochPlot2D,$VisualizationUsages]; 69 | AssignUsage[ListBlochPlot2D,$VisualizationUsages]; 70 | AssignUsage[BlochPlotColors,$VisualizationUsages]; 71 | AssignUsage[BlochPlotJoined,$VisualizationUsages]; 72 | AssignUsage[BlochPlotEndPoints,$VisualizationUsages]; 73 | AssignUsage[BlochPlotLabels,$VisualizationUsages]; 74 | 75 | 76 | (* ::Subsection::Closed:: *) 77 | (*Eigensystems*) 78 | 79 | 80 | Unprotect[EigensystemForm]; 81 | 82 | 83 | AssignUsage[EigensystemForm,$VisualizationUsages]; 84 | 85 | 86 | (* ::Subsection::Closed:: *) 87 | (*Special Plotting Functions*) 88 | 89 | 90 | Unprotect[FourierListPlot]; 91 | 92 | 93 | AssignUsage[FourierListPlot,$VisualizationUsages]; 94 | 95 | 96 | (* ::Subsection::Closed:: *) 97 | (*Error Messages*) 98 | 99 | 100 | BlochPlot::input = "Unable to parse input state(s); see Documentation. Constructed density lists have dimensions `1`."; 101 | BlochPlot::color = "BlochPlotColor option value not understood."; 102 | 103 | 104 | (* ::Section:: *) 105 | (*Implementation*) 106 | 107 | 108 | Begin["`Private`"]; 109 | 110 | 111 | (* ::Subsection::Closed:: *) 112 | (*Matrices*) 113 | 114 | 115 | ComplexMatrixPlot[A_,opts:OptionsPattern[DiscretePlot3D]]:=Module[{fun,color}, 116 | fun[x_,y_]:=(2UnitStep[Im[A[[x,y]]]]-1)Abs[A[[x,y]]]; 117 | (* We only use half of the Hue range otherwise 0 and \[Pi] would both be red *) 118 | color[x_,y_,z_]:=Hue[Abs[Arg[A[[x,y]]]]/\[Pi]/2]; 119 | DiscretePlot3D[ 120 | fun[x,y], 121 | {x,First@Dimensions@A}, 122 | {y,Last@Dimensions@A}, 123 | (* Allow user options to override anything *) 124 | opts, 125 | PlotTheme->"Detailed", 126 | PlotStyle->Opacity[0.7], 127 | (* ExtentSize gives it the bar graph look *) 128 | ExtentSize->Full, 129 | ColorFunctionScaling->False, 130 | ColorFunction->color, 131 | (* Note that the use of Ticks in BarLegend seems to work, although isn't documented*) 132 | PlotLegends->BarLegend[{Hue[# /\[Pi]/2]&,{0,\[Pi]}},Ticks->Range[0,\[Pi],\[Pi]/4]], 133 | AxesLabel->{"Row","Column"}, 134 | Ticks->{Range[First@Dimensions@A],Range[Last@Dimensions@A],Automatic}, 135 | Boxed->False 136 | ] 137 | ] 138 | 139 | 140 | BlockForm[mat_,n_]:= 141 | With[{div={False, Append[Table[False,{n - 1}], Dashed], False}}, 142 | {{Grid[mat, Dividers -> {div, div}, ItemSize -> Full]}} // MatrixForm 143 | ] 144 | BlockForm[mat_]:=BlockForm[mat,First@Last@FactorInteger[Length[mat],2]] 145 | 146 | 147 | MatrixListForm[mats_]:=Row[Riffle[MatrixForm/@mats,","]] 148 | 149 | 150 | (* ::Subsection::Closed:: *) 151 | (*Bloch Plots*) 152 | 153 | 154 | (* ::Subsubsection::Closed:: *) 155 | (*Bloch Sphere Display Components*) 156 | 157 | 158 | With[{r=1}, 159 | $BlochSphereXY=ParametricPlot3D[0.99*{r Cos[\[Theta]],r Sin[\[Theta]],0},{\[Theta],0,2 \[Pi]},PlotStyle->Dashed,Boxed->False,Axes->False]; 160 | $BlochSphereYZ=ParametricPlot3D[0.99*{0,r Cos[\[Theta]],r Sin[\[Theta]]},{\[Theta],0,2 \[Pi]},PlotStyle->Dashed,Boxed->False,Axes->False]; 161 | $BlochSphereXZ=ParametricPlot3D[0.99*{r Cos[\[Theta]],0,r Sin[\[Theta]]},{\[Theta],0,2 \[Pi]},PlotStyle->Dashed,Boxed->False,Axes->False]; 162 | 163 | $BlochSphere=Show[ 164 | Graphics3D[{ 165 | Opacity[.2], 166 | Sphere[{0,0,0},r], 167 | Opacity[.5],Black,Thick, 168 | Line[{{0,r,0},{0,-r,0}}],Line[{{0,0,r},{0,0,-r}}],Line[{{r,0,0},{-r,0,0}}], 169 | Opacity[1],Black,Thick, 170 | Text[Style["|+Z\[RightAngleBracket]",FontSize->14,FontWeight->Bold,FontColor->GrayLevel[.3]],{0,0,1.15 r}], 171 | Text[Style["|-Z\[RightAngleBracket]",FontSize->14,FontWeight->Bold,FontColor->GrayLevel[.3]],{0,0,-1.15 r}], 172 | Text[Style["|+X\[RightAngleBracket]",FontSize->14,FontWeight->Bold,FontColor->GrayLevel[.3]],{1.15 r,0,0}], 173 | Text[Style["|-X\[RightAngleBracket]",FontSize->14,FontWeight->Bold,FontColor->GrayLevel[.3]],{-1.15 r,0,0}], 174 | Text[Style["|+Y\[RightAngleBracket]",FontSize->14,FontWeight->Bold,FontColor->GrayLevel[.3]],{0,1.15 r,0}], 175 | Text[Style["|-Y\[RightAngleBracket]",FontSize->14,FontWeight->Bold,FontColor->GrayLevel[.3]],{0,-1.15 r,0}]}], 176 | $BlochSphereXY,$BlochSphereXZ,$BlochSphereYZ,Boxed->False]; 177 | 178 | $BlochCircleXZ=Graphics[{ 179 | Circle[{0,0},1], 180 | Line[{{1,0},{-1,0}}], 181 | Line[{{0,1},{0,-1}}], 182 | Text[Style["|+X\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{1.15,0}], 183 | Text[Style["|-X\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{-1.15,0}],Text[Style["|+Z\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{0,1.15}], 184 | Text[Style["|-Z\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{0,-1.15 }]}]; 185 | 186 | $BlochCircleXY=Graphics[{ 187 | Circle[{0,0},1], 188 | Line[{{1,0},{-1,0}}], 189 | Line[{{0,1},{0,-1}}], 190 | Text[Style["|+X\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{1.15,0}], 191 | Text[Style["|-X\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{-1.15,0}],Text[Style["|+Y\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{0,1.15}], 192 | Text[Style["|-Y\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{0,-1.15 }]}]; 193 | 194 | $BlochCircleYZ=Graphics[{ 195 | Circle[{0,0},1], 196 | Line[{{1,0},{-1,0}}], 197 | Line[{{0,1},{0,-1}}], 198 | Text[Style["|+Y\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{1.15,0}], 199 | Text[Style["|-Y\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{-1.15,0}], 200 | Text[Style["|+Z\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{0,1.15}], 201 | Text[Style["|-Z\[RightAngleBracket]",FontSize->12,FontWeight->Bold],{0,-1.15 }]}]; 202 | 203 | ]; 204 | 205 | 206 | (* ::Subsubsection::Closed:: *) 207 | (*Private Helper Functions*) 208 | 209 | 210 | (*BlochCoordinates[state_]:=Table[Re@Tr[PauliMatrix[n].state],{n,3}] 211 | BlochCoordinates = Compile[{{state,_Complex,2}},{ 212 | Re[state[[1,2]]+state[[2,1]]], 213 | -Im[state[[1,2]]]+Im[state[[2,1]]], 214 | Re[state[[1,1]]-state[[2,2]]] 215 | }];*) 216 | BlochCoordinates = Function[{state},{ 217 | Re[state[[1,2]]+state[[2,1]]], 218 | -Im[state[[1,2]]]+Im[state[[2,1]]], 219 | Re[state[[1,1]]-state[[2,2]]] 220 | }]; 221 | SetAttributes[BlochCoordinates,Listable]; 222 | 223 | 224 | BlochLegend[labels_,joined_,colorPairs_]:=LineLegend[ 225 | Directive[Thickness[0.01],Sequence@@If[joined,{},{Dotted}],#]&/@colorPairs[[All,1]], 226 | labels 227 | ] 228 | 229 | 230 | ChooseBlochColorPairs[colorOption_]:= 231 | Which[ 232 | colorOption===Automatic, 233 | ChooseBlochColorPairs[{RGBColor[0.742077, 0.0624857, 0.00605783],RGBColor[0, 0.501961, 0],RGBColor[1, 0.0175937, 0.505959],RGBColor[1, 0.904479, 0.279423],RGBColor[0.915, 0.3325, 0.2125],RGBColor[0.28026441037696703`, 0.715, 0.4292089322474965],RGBColor[0.6705882352941176, 0.8784313725490196, 0.9372549019607843],RGBColor[0.09019607843137255, 0.33725490196078434`, 0.49411764705882355`],RGBColor[0.975067, 1, 0.906294],RGBColor[0.5333333333333333, 0.23529411764705882`, 0.3058823529411765],RGBColor[0.823529, 0.663981, 0.00828565]}], 234 | ListQ[colorOption]&&MatchQ[colorOption,{__?ColorQ}], 235 | Map[{#,Lighter[#]}&,colorOption], 236 | ListQ[colorOption]&&ArrayDepth[colorOption]===2&&MatchQ[Flatten[colorOption],{__?ColorQ}], 237 | colorOption, 238 | True, 239 | Message[BlochPlot::color]; 240 | ChooseBlochColorPairs[Automatic] 241 | ] 242 | 243 | 244 | (* ::Subsubsection::Closed:: *) 245 | (*Bloch Sphere Plotting*) 246 | 247 | 248 | InheritOptions[BlochPlot, {Graphics3D, ParametricPlot3D, Interpolation}, { 249 | ViewAngle->0.34, 250 | BlochPlotLabels->Off, 251 | BlochPlotJoined->False, 252 | BlochPlotColors->Automatic, 253 | BlochPlotEndPoints->True 254 | }]; 255 | 256 | 257 | Unprotect@BlochPlot; 258 | BlochPlot[state_,opts:OptionsPattern[]]:= 259 | Module[{statesList,listOfDensity}, 260 | 261 | statesList=state; 262 | listOfDensity[array_]:=And[ArrayDepth[array]===3,Dimensions[array][[-2;;]]==={2,2}]; 263 | 264 | (*Turn single pure state or density matrix into list of one density matrix*) 265 | If[VectorQ[statesList],statesList=Projector[statesList]]; 266 | If[SquareMatrixQ[statesList],statesList={statesList}]; 267 | (*If the depth is still 2 it must be a list of pure states *) 268 | If[ArrayDepth[statesList]===2,statesList=Map[Projector,statesList]]; 269 | (*Turn a list of density matrices into a list thereof*) 270 | If[listOfDensity[statesList],statesList={statesList}]; 271 | (*If the depth is still 3 it must be a list of lists of pure states; make into densities*) 272 | If[Apply[And,Map[MatrixQ,statesList]],statesList=Map[Projector,statesList,{2}]]; 273 | 274 | (*If all went right we should have a list of lists of 2x2 density matrices.*) 275 | If[Not[And@@(Map[listOfDensity,statesList])],Message[BlochPlot::input,Dimensions/@statesList]]; 276 | If[OptionValue[BlochPlotJoined], 277 | ParametricBlochPlot[statesList,opts], 278 | ListBlochPlot[statesList,opts] 279 | ] 280 | ] 281 | 282 | 283 | ListBlochPlot[statesList_,opt:OptionsPattern[BlochPlot]]:= 284 | Module[{plotdat,d,numlists,colorPairs,ep,fig}, 285 | colorPairs=ChooseBlochColorPairs[OptionValue[BlochPlotColors]]; 286 | numlists=Length@statesList; 287 | ep=OptionValue@BlochPlotEndPoints; 288 | plotdat=Table[Map[BlochCoordinates,statesList[[n]]],{n,numlists}]; 289 | 290 | d=Table[Length[statesList[[n]]],{n,numlists}]; 291 | colorPairs=colorPairs[[Mod[Range[numlists]-1,Length@colorPairs]+1]]; 292 | 293 | fig=Show[ 294 | $BlochSphere, 295 | Table[ 296 | Graphics3D[{ 297 | Table[ 298 | { 299 | Blend[colorPairs[[n]],1-j/d[[n]]], 300 | PointSize@If[Or[1False], 307 | {n,numlists} 308 | ], 309 | ViewAngle->OptionValue[ViewAngle], 310 | FilterOptions[Graphics3D,opt] 311 | ]; 312 | If[OptionValue[BlochPlotLabels]===Off, 313 | fig, 314 | Legended[fig,BlochLegend[OptionValue[BlochPlotLabels],False,colorPairs]] 315 | ] 316 | ] 317 | 318 | 319 | 320 | ParametricBlochPlot[statesList_,opt:OptionsPattern[BlochPlot]]:= 321 | Module[{fig,plotdat,fx,fy,fz,d,numlists,colorPairs,range}, 322 | colorPairs=ChooseBlochColorPairs[OptionValue[BlochPlotColors]]; 323 | numlists=Length@statesList; 324 | d=Table[Length[statesList[[n]]],{n,numlists}]; 325 | colorPairs=colorPairs[[Mod[Range[numlists]-1,Length@colorPairs]+1]]; 326 | 327 | plotdat=Table[Map[BlochCoordinates,statesList[[n]]],{n,numlists}]; 328 | Table[ 329 | If[d[[n]]>1, 330 | range=Range[0,1,1/(d[[n]]-1)]; 331 | fx[n]=Interpolation[{range,plotdat[[n,All,1]]}\[Transpose],FilterOptions[Interpolation,opt]]; 332 | fy[n]=Interpolation[{range,plotdat[[n,All,2]]}\[Transpose],FilterOptions[Interpolation,opt]]; 333 | fz[n]=Interpolation[{range,plotdat[[n,All,3]]}\[Transpose],FilterOptions[Interpolation,opt]];, 334 | fx[n]=Null &; 335 | fy[n]=Null &; 336 | fz[n]=Null &; 337 | ], 338 | {n,numlists} 339 | ]; 340 | fig=Show[ 341 | $BlochSphere, 342 | Table[Sequence@@{ 343 | ParametricPlot3D[ 344 | {fx[n][u],fy[n][u],fz[n][u]}, {u,0,1}, 345 | Boxed->False, 346 | Evaluate@FilterOptions[ParametricPlot3D,opt], 347 | PlotStyle->Thickness[0.01], 348 | ColorFunction->(Blend[colorPairs[[n]],#4]&) 349 | ], 350 | Graphics3D[{PointSize[0.035], 351 | If[OptionValue[BlochPlotEndPoints],Sequence@@{ 352 | colorPairs[[n,1]],Point[plotdat[[n,1]]], 353 | colorPairs[[n,2]],Point[plotdat[[n,-1]]] 354 | }], 355 | Sequence@@If[d[[n]]===1,{colorPairs[[n,1]],Thickness[0.005],Line[{{0,0,0},plotdat[[n,1]]}]},{}] 356 | }]}, 357 | {n,numlists} 358 | ], 359 | ViewAngle->OptionValue[ViewAngle], 360 | FilterOptions[Graphics3D,opt] 361 | ]; 362 | If[OptionValue[BlochPlotLabels]===Off, 363 | fig, 364 | Legended[fig,BlochLegend[OptionValue[BlochPlotLabels],True,colorPairs]] 365 | ] 366 | ] 367 | 368 | 369 | (* ::Subsubsection::Closed:: *) 370 | (*Bloch Sphere 2D Projection*) 371 | 372 | 373 | BlochPlot2D[state_]:= 374 | With[{p=BlochCoordinates[state]}, 375 | GraphicsRow[{ 376 | Show[$BlochCircleXZ,Graphics[ 377 | {Red,Thickness[0.01],Line[{{0,0},Part[p,{1,3}]}]}, 378 | {Red,PointSize[0.03],Point[Part[p,{1,3}]]}]], 379 | Show[$BlochCircleYZ,Graphics[ 380 | {Red,Thickness[0.01],Line[{{0,0},Part[p,{2,3}]}]}, 381 | {Red,PointSize[0.03],Point[Part[p,{2,3}]]}]], 382 | Show[$BlochCircleXY,Graphics[ 383 | {Red,Thickness[0.01],Line[{{0,0},Part[p,{1,2}]}]}, 384 | {Red,PointSize[0.03],Point[Part[p,{1,2}]]}]] 385 | },ImageSize->Large]] 386 | 387 | 388 | ListBlochPlot2D[\[Rho]list_]:= 389 | With[{ 390 | ps=Map[BlochCoordinates,\[Rho]list], 391 | d=Length[\[Rho]list]}, 392 | GraphicsRow[{ 393 | Show[$BlochCircleXZ, 394 | Graphics[{ 395 | Map[{Blend[{Red,Blue},1-#/d],PointSize[0.02],Point[Part[ps,#,{1,3}]]}&, 396 | Range[d]] 397 | }]], 398 | Show[$BlochCircleYZ, 399 | Graphics[{ 400 | Map[{Blend[{Red,Blue},1-#/d],PointSize[0.02],Point[Part[ps,#,{2,3}]]}&, 401 | Range[d]] 402 | }]], 403 | Show[$BlochCircleXY, 404 | Graphics[{ 405 | Map[{Blend[{Red,Blue},1-#/d],PointSize[0.02],Point[Part[ps,#,{1,2}]]}&, 406 | Range[d]] 407 | }]] 408 | },ImageSize->Large] 409 | ]; 410 | 411 | 412 | (* ::Subsection::Closed:: *) 413 | (*Eigensystems*) 414 | 415 | 416 | EigensystemForm[sys_]:=Grid[ 417 | ({#[[1]],"\[DownArrow]",MatrixForm[#[[2]]]}&/@(sys\[Transpose]))\[Transpose], 418 | ItemSize->Full 419 | ]; 420 | 421 | 422 | (* ::Subsection::Closed:: *) 423 | (*Special Plotting Functions*) 424 | 425 | 426 | FourierListPlot[data_,{mint_,maxt_},function_,opt:OptionsPattern[ListPlot]]:= 427 | Module[{n,n2,dt,fdata,minf,maxf}, 428 | (*Take the discrete FT of each input list*) 429 | fdata=(Fourier/@If[VectorQ[data],{data},data]); 430 | (* Now that we've sorted out whether data is a list or list of lists... *) 431 | n=Length[fdata[[1]]]; 432 | n2=Floor[n/2]; 433 | dt=(maxt-mint)/(n-1); 434 | (* Apply each input function to each fourier domain list *) 435 | fdata=Flatten[Outer[#2[#1]&,fdata,If[ListQ[function],function,{function}],1],1]; 436 | (* Add x cooordinates to the lists *) 437 | fdata=Map[({Range[0,1/dt,1/((n-1)dt)],#}\[Transpose])&,fdata,1]; 438 | (* determine the plot bounds *) 439 | If[OptionValue[DataRange]===Automatic, 440 | minf=0;maxf=1/(2dt);, 441 | minf=OptionValue[DataRange][[1]];maxf=OptionValue[DataRange][[2]]; 442 | ]; 443 | (* select only those data lying in the frequency bounds*) 444 | fdata=Function[{list},Select[list,minf<=#[[1]]<=maxf&]]/@fdata; 445 | (* usual list plot *) 446 | ListPlot[fdata,DataRange->Automatic,opt] 447 | ] 448 | 449 | 450 | (* ::Subsection::Closed:: *) 451 | (*End Private*) 452 | 453 | 454 | End[]; 455 | 456 | 457 | (* ::Section:: *) 458 | (*End Package*) 459 | 460 | 461 | Protect[ComplexMatrixPlot,BlockForm,MatrixListForm]; 462 | Protect[BlochPlot,BlochPlot2D,ListBlochPlot2D,BlochPlotColors,BlochPlotEndPoints,BlochPlotJoined,BlochPlotLabels]; 463 | Protect[EigensystemForm]; 464 | Protect[FourierListPlot]; 465 | 466 | 467 | EndPackage[]; 468 | -------------------------------------------------------------------------------- /src/pylink/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantumUtils/quantum-utils-mathematica/4026f922031da7045ea8e5cf4a26c1ab893dd3e0/src/pylink/__init__.py -------------------------------------------------------------------------------- /src/pylink/grammar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | ## 4 | # This package is part of QuantumUtils for Mathematica. 5 | ## 6 | # Copyright (c) 2015 and later, 7 | # Christopher J. Wood, Christopher E. Granade, Ian N. Hincks. 8 | # 9 | # Redistribution and use in source and binary forms, with or without 10 | # modification, are permitted provided that the following conditions are met: 11 | # 12 | # 1. Redistributions of source code must retain the above copyright notice, 13 | # this list of conditions and the following disclaimer. 14 | # 2. Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 3. Neither the name of quantum-utils-mathematica nor the names of its 18 | # contributors may be used to endorse or promote products derived from this 19 | # software without specific prior written permission. 20 | ## 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22 | # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 | # THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 | # PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 25 | # CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | # EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | # PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; 28 | # OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, 29 | # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 | # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | ## 33 | 34 | ## DOCSTRING ######################################################### 35 | 36 | """ 37 | This module defines a grammar for a restricted subset of the Mathematica 38 | language, suitable for interprocess communication (IPC) between Python and 39 | Mathematica. 40 | 41 | Known Issues: 42 | - Due to a bug in the most recent versions of PyPEG2, this module 43 | only works with the HEAD of the repo (as of 7 April 2015). 44 | - Functions with no arguments get truncated to just the lone symbol, 45 | e. g.: List[] parses as List. 46 | - Atomic data types such as floating point numbers are 47 | not yet supported. 48 | - The String grammar element is buried one level too deep; e. g.: 49 | parse('"a"', MExpression) is embedded in an MExpression with 50 | head and body both None, as opposed to the behavior of Integer. 51 | - Forms such as f[a][b] are not yet supported. 52 | - Shorthand forms such as ; are not yet supported. 53 | - PyPEG2's compose() function doesn't yet play well with this 54 | grammar. 55 | """ 56 | 57 | ## FEATURES ########################################################## 58 | 59 | from __future__ import division 60 | 61 | ## IMPORTS ########################################################### 62 | 63 | from pypeg2 import Symbol, Literal, parse, optional, csl, attr 64 | import re 65 | 66 | ## CLASSES ########################################################### 67 | 68 | class MathematicaObject(object): 69 | head = "" 70 | body = [] 71 | 72 | def __repr__(self): 73 | if self.body is not None: 74 | return "{}[{}]".format(self.head, ", ".join(map(repr, self.body))) 75 | else: 76 | return "{}".format(self.head) 77 | def __str__(self): 78 | return repr(self) 79 | 80 | ## GRAMMAR ELEMENTS ################################################## 81 | 82 | class MSymbol(MathematicaObject, Symbol): 83 | Symbol.regex = re.compile(r'[\w\`]+') 84 | 85 | head = "Symbol" 86 | 87 | @property 88 | def body(self): 89 | return ['"{}"'.format(self)] 90 | 91 | class Integer(MathematicaObject, int): 92 | grammar = re.compile(r'[+-]?[0-9]+') 93 | head = "Integer" 94 | 95 | @property 96 | def body(self): 97 | return [int(self)] 98 | 99 | class String(MathematicaObject, str): 100 | grammar = Literal('"'), re.compile(r'([^\"]*)'), Literal('"') 101 | head = "String" 102 | 103 | @property 104 | def body(self): 105 | return [str(self[:])] 106 | 107 | def __repr__(self): 108 | return '"{}"'.format(str(self[:])) 109 | 110 | 111 | atom = [Integer, String] 112 | 113 | class MExpression(MathematicaObject, list): 114 | head = None 115 | body = None 116 | 117 | class List(MExpression): 118 | head = MSymbol("List") 119 | 120 | grammar = ( 121 | Literal("{"), optional(attr("body", csl(MExpression))), Literal("}") 122 | ) 123 | 124 | 125 | # Since MExpression is recursive, we need to define the class, 126 | # then the grammar. Moreover, since it depends on List and other 127 | # such things, we need to put it last. 128 | MExpression.grammar = [ 129 | ( 130 | attr("head", MSymbol), Literal("["), optional(attr("body", csl(MExpression))), Literal("]") 131 | ), 132 | attr("head", MSymbol), 133 | List, 134 | atom 135 | ] 136 | 137 | 138 | ## TESTING ########################################################### 139 | 140 | if __name__ == "__main__": 141 | print parse("ab`c", MExpression) 142 | print parse('12', MExpression) 143 | print parse('"a"', MExpression) 144 | print parse("List", MExpression) 145 | print parse("List[]", MExpression) 146 | print parse("List[foo]", MExpression) 147 | print parse("List[foo[bar, a]]", MExpression) 148 | print parse('{a, 12, "foo"}', MExpression) 149 | print parse('{a, 12, 12}', MExpression) 150 | 151 | -------------------------------------------------------------------------------- /test/ControlTheoryTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Control Theory Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["ControlTheoryTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["ControlTheory`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section::Closed:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsection::Closed:: *) 62 | (*End*) 63 | 64 | 65 | End[]; 66 | 67 | 68 | (* ::Section:: *) 69 | (*End Package*) 70 | 71 | 72 | EndPackage[]; 73 | -------------------------------------------------------------------------------- /test/GRAPETests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*GRAPE Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["GRAPETests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["GRAPE`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section::Closed:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsection::Closed:: *) 62 | (*End*) 63 | 64 | 65 | End[]; 66 | 67 | 68 | (* ::Section:: *) 69 | (*End Package*) 70 | 71 | 72 | EndPackage[]; 73 | -------------------------------------------------------------------------------- /test/LindbladSolverTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Lindblad Solver Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["LindbladSolverTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["LindbladSolver`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section::Closed:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsubsection::Closed:: *) 62 | (*Preformating State and Lindblad*) 63 | 64 | 65 | TestCase[$RegisteredTests,"LindbladSolver:PreformatGenerator", 66 | Block[{t,a}, 67 | And[ 68 | Norm@Simplify[ 69 | LindbladSolver`Private`PreformatGenerator[Sin[#]*Array[a,{2,2}]&,t]-Sin[t]*Array[a,{2,2}] 70 | ]===0, 71 | Norm@Simplify[ 72 | LindbladSolver`Private`PreformatGenerator[Array[a,{2,2}],t]-Array[a,{2,2}] 73 | ]===0] 74 | ] 75 | ]; 76 | 77 | 78 | TestCase[$RegisteredTests,"LindbladSolver:PreformatLindblad", 79 | Block[{t, 80 | ham=PauliMatrix[3], 81 | cOp={{{0,1},{0,0}}}, 82 | L=DiagonalMatrix[{0,2*I,-2*I,0}], 83 | D={{0,0,0,1},{0,-1/2,0,0},{0,0,-1/2,0},{0,0,0,-1}}}, 84 | And[ 85 | Norm@Simplify[LindbladSolver`Private`PreformatLindblad[ham,cOp][t]-L-D]===0, 86 | Norm@Simplify[LindbladSolver`Private`PreformatLindblad[0,cOp][t]-D]===0, 87 | Norm@Simplify[LindbladSolver`Private`PreformatLindblad[ham,{}][t]-L]===0] 88 | ]] 89 | 90 | 91 | TestCase[$RegisteredTests,"LindbladSolver:PreformatHamiltonian", 92 | Block[{ham=PauliMatrix[1],t}, 93 | And[ 94 | Norm@Simplify[LindbladSolver`Private`PreformatHamiltonian[ham][t]+I*ham]===0, 95 | Norm@Simplify[LindbladSolver`Private`PreformatHamiltonian[Cos[#]*ham&][t]+I*Cos[t]*ham]===0 96 | ] 97 | ]] 98 | 99 | 100 | TestCase[$RegisteredTests,"LindbladSolver:PreformatState", 101 | And[ 102 | LindbladSolver`Private`PreformatState[{{"a",0},{0,"b"}}]==={"a",0,0,"b"}, 103 | LindbladSolver`Private`PreformatState[{{"a"},{"b"}}]==={"a","b"}, 104 | LindbladSolver`Private`PreformatState[{"a","b"}]==={"a","b"}] 105 | ] 106 | 107 | 108 | (* ::Subsubsection::Closed:: *) 109 | (*Setting Up ODE*) 110 | 111 | 112 | TestCase[$RegisteredTests,"LindbladSolver:ODEInitialConditions", 113 | ODEInitialConditions[{0,1},{0,"x"}]===And["x"[1][0]==0,"x"[2][0]==1] 114 | ] 115 | 116 | 117 | TestCase[$RegisteredTests,"LindbladSolver:ODEFirstOrderSystem", 118 | Block[{t}, 119 | ODEFirstOrderSystem[{{0,"a"[1]},{"a"[2],0}},{t,"x"}]===And[ 120 | Derivative[1]["x"[1]][t]=="a"[1] "x"[2][t],Derivative[1]["x"[2]][t]=="a"[2] "x"[1][t]] 121 | ]] 122 | 123 | 124 | (* ::Subsubsection::Closed:: *) 125 | (*Solving ODE*) 126 | 127 | 128 | TestCase[$RegisteredTests,"LindbladSolver:ODESolver.Numeric", 129 | With[{sol=ODESolver[-2*Pi*I*PauliMatrix[1],{{0,1},0,1}]}, 130 | And[MatchQ[sol,{__InterpolatingFunction}], 131 | TrueQ[Abs[Through[sol[1]].{0,1}]^2-1<=0.0001]] 132 | ]] 133 | 134 | 135 | TestCase[$RegisteredTests,"LindbladSolver:ODESolver.Symbolic", 136 | Block[{t,sol}, 137 | sol=ODESolver[-2*Pi*I*PauliMatrix[1],{{0,1},0}][t]; 138 | TrueQ[sol=={-I*Sin[2*Pi*t],Cos[2*Pi*t]}] 139 | ]] 140 | 141 | 142 | TestCase[$RegisteredTests,"LindbladSolver:SchrodingerSolver.Numeric", 143 | Block[{t}, 144 | MatchQ[ 145 | SchrodingerSolver[Cos[#]PauliMatrix[1]&,{{0,1},0,1}][t], 146 | {InterpolatingFunction[__][t],InterpolatingFunction[__][t]} 147 | ]]] 148 | 149 | 150 | TestCase[$RegisteredTests,"LindbladSolver:SchordingerSolver.Symbolic", 151 | Block[{t,a,b}, 152 | SchrodingerSolver[PauliMatrix[3],{{a,b},0}][t]==={a*Exp[-I*t],b*Exp[I*t]} 153 | ]] 154 | 155 | 156 | TestCase[$RegisteredTests,"LindbladSolver:LindbladSolver.Numeric", 157 | Block[{init={{1,0},{0,0}},sol,t}, 158 | sol=LindbladSolver[{Cos[#]PauliMatrix[1]&,{{{0,1},{0,0}}}}, 159 | {{{1,0},{0,0}},0,1}]; 160 | And[ 161 | Chop@Norm[sol[0]-init]===0, 162 | MatchQ[sol[t], 163 | {{InterpolatingFunction[__][t],InterpolatingFunction[__][t]}, 164 | {InterpolatingFunction[__][t],InterpolatingFunction[__][t]}}] 165 | ] 166 | ]] 167 | 168 | 169 | TestCase[$RegisteredTests,"LindbladSolver:LindbladSolver.Symbolic", 170 | Block[{sol,t}, 171 | sol=LindbladSolver[{0,{{{0,0},{1,0}}}},{{{1,0},{0,0}},0}][t]; 172 | Norm@Simplify[sol-{{Exp[-t],0},{0,1-Exp[-t]}}]===0 173 | ]] 174 | 175 | 176 | TestCase[$RegisteredTests,"LindbladSolver:LindbladSolver.QuantumChannel", 177 | Block[{sol,t,chan}, 178 | chan=QuantumChannel`QuantumChannel[ 179 | {{-1,0,0,0},{0,-(1/2),0,0},{0,0,-(1/2),0},{1,0,0,0}}, 180 | {QuantumChannel`ChannelRep->QuantumChannel`Super, 181 | QuantumChannel`InputDim->2, 182 | QuantumChannel`OutputDim->2, 183 | Tensor`Basis->"Col"}]; 184 | sol=LindbladSolver[chan,{{{1,0},{0,0}},0}][t]; 185 | Norm@Simplify[sol-{{Exp[-t],0},{0,1-Exp[-t]}}]===0 186 | ]] 187 | 188 | 189 | (* ::Subsection::Closed:: *) 190 | (*End*) 191 | 192 | 193 | End[]; 194 | 195 | 196 | (* ::Section:: *) 197 | (*End Package*) 198 | 199 | 200 | EndPackage[]; 201 | -------------------------------------------------------------------------------- /test/M2MTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*M2M Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["M2MTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["M2M`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsection:: *) 62 | (*Matrices and Operations*) 63 | 64 | 65 | TestCase[$RegisteredTests, "M2M:ExpressionToMATLAB", 66 | And[ 67 | ExpressionToMATLAB[a + b] == "(a+b)", 68 | ExpressionToMATLAB[a b] == "(a.*b)", 69 | ExpressionToMATLAB[a.b] == "(a*b)", 70 | ExpressionToMATLAB[Sin[x]] == "sin(x)", 71 | ExpressionToMATLAB[IdentityMatrix[3]] == "[1 0 0; 0 1 0; 0 0 1]" 72 | ] 73 | ] 74 | 75 | 76 | TestCase[$RegisteredTests, "M2M:SimpleFunctionToMATLAB", 77 | SimpleFunctionToMATLAB["f", {x}, Sin[#]-#^2> 3&] == "% f TODO: add documentation here.\nfunction Y = f(x)\n% WARNING: This file was automatically generated by the M2M package for Mathematica.\n% Do not edit the following lines directly.\nY = (((-1.*(x.^2))+sin(x))>3);\nend" 78 | ]; 79 | 80 | 81 | TestCase[$RegisteredTests, "M2M:StatementToMATLAB", 82 | StatementToMATLAB[If[a > 3, b = c, c = b]] == "if (a>3)\n\tb = c;\nelse\n\tc = b;\nend" 83 | ]; 84 | 85 | 86 | TestCase[$RegisteredTests, "M2M:FunctionToMATLAB", 87 | With[{X = PauliMatrix[1]}, 88 | FunctionToMATLAB["f",{x},If[Tr[x.X] < 1, x / Tr[x], 0]] 89 | ] == "% f TODO: add documentation here.\nfunction retval = f(x)\n% WARNING: This file was automatically generated by the M2M package for Mathematica.\n% Do not edit the following lines directly.\nif (trace((x*[0 1; 1 0]))<1)\n\tretval = (x./trace(x));\nelse\n\tretval = 0;\nend\nend" 90 | ]; 91 | 92 | 93 | (* ::Subsection::Closed:: *) 94 | (*End*) 95 | 96 | 97 | End[]; 98 | 99 | 100 | (* ::Section::Closed:: *) 101 | (*End Package*) 102 | 103 | 104 | EndPackage[]; 105 | -------------------------------------------------------------------------------- /test/PerturbationTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Perturbation Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["PerturbationTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["Perturbation`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section::Closed:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsection::Closed:: *) 62 | (*End*) 63 | 64 | 65 | End[]; 66 | 67 | 68 | (* ::Section:: *) 69 | (*End Package*) 70 | 71 | 72 | EndPackage[]; 73 | -------------------------------------------------------------------------------- /test/PredicatesTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Predicates Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["PredicatesTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["Predicates`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section::Closed:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsection::Closed:: *) 62 | (*Fuzzy Logic*) 63 | 64 | 65 | TestCase[$RegisteredTests,"Predicates:PossiblyTrueQ", 66 | And[ 67 | Module[{maybe},PossiblyTrueQ[maybe]], 68 | PossiblyTrueQ[True], 69 | Not@PossiblyTrueQ[0 == 2] 70 | ]]; 71 | 72 | 73 | TestCase[$RegisteredTests,"Predicates:PossiblyFalseQ", 74 | And[ 75 | Module[{maybe}, PossiblyFalseQ[maybe]], 76 | Not@PossiblyFalseQ[True], 77 | PossiblyFalseQ[0 == 2] 78 | ]] 79 | 80 | 81 | TestCase[$RegisteredTests,"Predicates:PossiblyNonzeroQ", 82 | And[ 83 | Module[{maybe}, PossiblyNonzeroQ[maybe]], 84 | Not@PossiblyNonzeroQ[0] 85 | ]] 86 | 87 | 88 | (* ::Subsection::Closed:: *) 89 | (*Numbers and Lists*) 90 | 91 | 92 | TestCase[$RegisteredTests,"Predicates:AnyQ", AnyQ[# >= 2 &, {0, 1, 5}]]; 93 | 94 | 95 | TestCase[$RegisteredTests,"Predicates:AllElementQ", AllElementQ[# >= 2 &, {3, {{{{4}}}}, 5}]]; 96 | 97 | 98 | TestCase[$RegisteredTests,"Predicates:AnyMatchQ", AnyMatchQ[_Integer,{0, 1.2, 5.5}]]; 99 | 100 | 101 | TestCase[$RegisteredTests,"Predicates:AllQ", AnyQ[# >= 2 &, {2, 4, 5}]]; 102 | 103 | 104 | TestCase[$RegisteredTests,"Predicates:AnyElementQ", AnyElementQ[# >= 2 &, {{{{4}, 0}}, 1}]] 105 | 106 | 107 | TestCase[$RegisteredTests,"Predicates:AllMatchQ", AllMatchQ[_Integer,{2, 4, 5}]]; 108 | 109 | 110 | TestCase[$RegisteredTests,"Predicates:AnyNonzeroQ", AnyNonzeroQ[{0, 1, 5}]]; 111 | 112 | 113 | TestCase[$RegisteredTests,"Predicates:AnyPossiblyNonzeroQ", Module[{maybe}, AnyPossiblyNonzeroQ[{0, maybe, 0}]]] 114 | 115 | 116 | (* ::Subsection::Closed:: *) 117 | (*Symbolic Expressions*) 118 | 119 | 120 | TestCase[$RegisteredTests,"Predicates:SymbolQ", 121 | And[ 122 | Not@SymbolQ[12], 123 | Module[{arg},SymbolQ[arg]], 124 | Module[{f},f[x_]:=x; Not@SymbolQ[f]], 125 | With[{x=10},Not@SymbolQ[x]] 126 | ]]; 127 | 128 | 129 | TestCase[$RegisteredTests,"Predicates:CoefficientQ", 130 | Module[{f,g,x,y}, 131 | And[ 132 | CoefficientQ[Sin[3*x]], 133 | CoefficientQ[g[x,y]], 134 | CoefficientQ[f[g[x]]], 135 | CoefficientQ[x], 136 | CoefficientQ[Sin["x"]], 137 | SetAttributes[g,Protected];Not@CoefficientQ[g[x]], 138 | Not@CoefficientQ[KroneckerProduct[x,y]], 139 | Not@CoefficientQ[Dot[1,2]] 140 | ]]]; 141 | 142 | 143 | (* ::Subsection::Closed:: *) 144 | (*Matrices and Lists*) 145 | 146 | 147 | TestCase[$RegisteredTests,"Predicates:NonzeroDimQ", 148 | And[ 149 | Not@NonzeroDimQ[{{{},{}}}], 150 | NonzeroDimQ[{1,2,3}] 151 | ]]; 152 | 153 | 154 | TestCase[$RegisteredTests,"Predicates:DiagonalMatrixQ", 155 | And[ 156 | DiagonalMatrixQ@DiagonalMatrix[{1,2,3}], 157 | Not@DiagonalMatrixQ[{{1,2},{3,4}}] 158 | ]]; 159 | 160 | 161 | TestCase[$RegisteredTests,"Predicates:PureStateQ", 162 | And[ 163 | PureStateQ[{{1,1},{1,1}}/2], 164 | Not@PureStateQ[{{1,0},{0,3}}/4] 165 | ]]; 166 | 167 | 168 | TestCase[$RegisteredTests,"Predicates:ColumnVectorQ", 169 | And[ 170 | ColumnVectorQ[{{0},{1}}], 171 | Not@ColumnVectorQ[{0,0,1}], 172 | Not@ColumnVectorQ[{{0,1}}] 173 | ]]; 174 | 175 | 176 | TestCase[$RegisteredTests,"Predicates:RowVectorQ", 177 | And[ 178 | Not@RowVectorQ[{{0},{1}}], 179 | Not@RowVectorQ[{0,0,1}], 180 | RowVectorQ[{{0,1}}] 181 | ]]; 182 | 183 | 184 | TestCase[$RegisteredTests,"Predicates:GeneralVectorQ", 185 | And[ 186 | GeneralVectorQ[{{0},{1}}], 187 | GeneralVectorQ[{0,0,1}], 188 | Not@GeneralVectorQ[{{0,1}}] 189 | ]]; 190 | 191 | 192 | (* ::Subsection::Closed:: *) 193 | (*End Private*) 194 | 195 | 196 | End[]; 197 | 198 | 199 | (* ::Section::Closed:: *) 200 | (*End Package*) 201 | 202 | 203 | EndPackage[]; 204 | -------------------------------------------------------------------------------- /test/QSimTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*QSim Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["QSimTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["QSim`"]; 38 | Needs["QuantumChannel`"]; 39 | 40 | 41 | (* ::Section::Closed:: *) 42 | (*Results*) 43 | 44 | 45 | Begin["`UnitTests`"]; 46 | 47 | 48 | $Threshold = 10^-5; 49 | 50 | 51 | $RegisteredTests={}; 52 | $TestResults := RunTest[$RegisteredTests]; 53 | 54 | 55 | End[]; 56 | 57 | 58 | (* ::Section:: *) 59 | (*Unit Tests*) 60 | 61 | 62 | Begin["`UnitTests`"]; 63 | 64 | 65 | (* ::Subsection::Closed:: *) 66 | (*Predicates*) 67 | 68 | 69 | (* ::Text:: *) 70 | (*No tests here for now since all of the predicates are tested implicitly in the tests of PulseSim.*) 71 | 72 | 73 | (* ::Subsection:: *) 74 | (*Helper Functions*) 75 | 76 | 77 | (* ::Subsection::Closed:: *) 78 | (*Single Pulse*) 79 | 80 | 81 | (* ::Subsubsection:: *) 82 | (*Drift Pulse*) 83 | 84 | 85 | TestCase[$RegisteredTests,"PulseSim:DriftPulse", 86 | Norm[ 87 | Last@Unitaries@PulseSim[{{0,1},{1,0}},2] 88 | -{{Cos[2],-I Sin[2]},{-I Sin[2],Cos[2]}} 89 | ] < $Threshold 90 | ] 91 | 92 | 93 | TestCase[$RegisteredTests,"PulseSim:DriftPulseTimeDep", 94 | Norm[ 95 | Last@Unitaries@PulseSim[{{0,Cos[#]},{Cos[#],0}}&,5] 96 | -{{0.5742394822354157` +0.` I,0.` +0.8186873744244522` I},{0.` +0.818687374424452` I,0.5742394822354161` +0.` I}} 97 | ] < $Threshold 98 | ] 99 | 100 | 101 | TestCase[$RegisteredTests,"PulseSim:DriftPulseAnalytic", 102 | Module[{a,b,t}, 103 | Last@Unitaries@PulseSim[{{0,a},{a,0}},t,NumericEvaluation->False] 104 | == {{Cos[a t],-I*Sin[a t]},{-I*Sin[a t],Cos[a t]}} 105 | ] 106 | ] 107 | 108 | 109 | TestCase[$RegisteredTests,"PulseSim:DriftPulseWithStates", 110 | Norm[ 111 | Last@States@PulseSim[{{0,1},{1,0}},2,InitialState->{{.7,0},{0,.3}}] 112 | -{{0.36927127582727765` +0.` I,0.` -0.15136049906158555` I},{0.` +0.1513604990615856` I,0.6307287241727222` +0.` I}} 113 | ] < $Threshold 114 | ] 115 | 116 | 117 | TestCase[$RegisteredTests,"PulseSim:DriftPulseLindblad", 118 | Norm[ 119 | Last@States@PulseSim[LindbladForm[{{0,1},{1,0}},{{{1,0},{0,-1}}}],2,InitialState->{{.7,0},{0,.3}}] 120 | -{{0.46937544631719` +0.` I,0.` -0.00990597594838295` I},{0.` +0.009905975948382967` I,0.5306245536828097` +0.` I}} 121 | ] < $Threshold 122 | ] 123 | 124 | 125 | (* ::Subsubsection:: *) 126 | (*Shaped Pulse*) 127 | 128 | 129 | TestCase[$RegisteredTests,"PulseSim:ShapedPulse", 130 | Norm[ 131 | Last@Unitaries@PulseSim[{{1,0},{0,-1}},{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}] 132 | -{{0.9777278846389216` -0.1505870528557579` I,0.12353764730343048` -0.07816759437541426` I},{-0.12353764730342981`- 0.07816759437541462` I,0.9777278846389224` +0.1505870528557493` I}} 133 | ] < $Threshold 134 | ] 135 | 136 | 137 | TestCase[$RegisteredTests,"PulseSim:ShapedPulseTimeDep", 138 | Norm[ 139 | Last@Unitaries@PulseSim[{{0,Cos[#]},{Cos[#],0}}&,{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}] 140 | -{{0.8400832121177894` +0.0297745991183988` I,-0.39781488092880346`+ 0.367582630814888` I},{0.3978148809288031` +0.36758263081488907` I,0.8400832121177911` -0.02977459911839913` I}} 141 | ] < $Threshold 142 | ] 143 | 144 | 145 | TestCase[$RegisteredTests,"PulseSim:ShapedPulseWithStates", 146 | Norm[ 147 | Last@States@PulseSim[{{1,0},{0,-1}},{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}},InitialState->{{.7,0},{0,.3}}] 148 | -{{0.69145131075531` -1.431146867680866`*^-17 I,-0.043606069962172984`+ 0.03801192276805836` I},{-0.04360606996217298`- 0.03801192276805836` I,0.3085486892446788` +0.` I}} 149 | ] < $Threshold 150 | ] 151 | 152 | 153 | TestCase[$RegisteredTests,"PulseSim:ShapedPulseLindblad", 154 | Norm[ 155 | Last@States@PulseSim[LindbladForm[{{0,1},{1,0}},{{{1,0},{0,-1}}}],{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}},InitialState->{{.7,0},{0,.3}}] 156 | -{{0.4999999999481136` -7.71010187685563`*^-16 I,-1.1788512412532763`*^-11+ 1.1788321797058875`*^-11 I},{-1.178745933839757`*^-11- 1.1787315074464443`*^-11 I,0.5000000000518892` -7.621125555523322`*^-16 I}} 157 | ] < $Threshold 158 | ] 159 | 160 | 161 | (* ::Subsubsection:: *) 162 | (*Unitary Pulse*) 163 | 164 | 165 | TestCase[$RegisteredTests,"PulseSim:UnitaryPulse", 166 | Module[{a,b,c,d}, 167 | Norm[ 168 | Last@Unitaries@PulseSim[{{1,0},{0,-1}},{{{a,b},{c,d}},1}] 169 | - {{a,b},{c,d}} 170 | ] < $Threshold 171 | ] 172 | ] 173 | 174 | 175 | TestCase[$RegisteredTests,"PulseSim:UnitaryPulseWithStates", 176 | Module[{a,b,c,d}, 177 | Norm[ 178 | Last@States@PulseSim[{{1,0},{0,-1}},{{{a,b},{c,d}},1},InitialState->{{.7,0},{0,.3}}] 179 | -{{0.7` a Conjugate[a]+0.3` b Conjugate[b],0.7` a Conjugate[c]+0.3` b Conjugate[d]},{0.7` c Conjugate[a]+0.3` d Conjugate[b],0.7` c Conjugate[c]+0.3` d Conjugate[d]}} 180 | ] < $Threshold 181 | ] 182 | ] 183 | 184 | 185 | (* ::Subsubsection:: *) 186 | (*Channel Pulse*) 187 | 188 | 189 | TestCase[$RegisteredTests,"PulseSim:ChannelPulse", 190 | Last@Superoperators@PulseSim[{{1,0},{0,-1}},{Choi[IdentityMatrix[4]],1}] 191 | === Super@Choi[IdentityMatrix[4]] 192 | ] 193 | 194 | 195 | TestCase[$RegisteredTests,"PulseSim:ChannelPulseWithStates", 196 | Norm[ 197 | Last@States@PulseSim[{{1,0},{0,-1}},{Choi[IdentityMatrix[4]],1},InitialState->{{.7,0},{0,.3}}] 198 | -{{1.`,0.`},{0.`,1.`}} 199 | ] < $Threshold 200 | ] 201 | 202 | 203 | (* ::Subsubsection:: *) 204 | (*Polling Interval*) 205 | 206 | 207 | TestCase[$RegisteredTests,"PulseSim:PollingInterval", 208 | Length@Unitaries@PulseSim[{{0,1},{1,0}},2,PollingInterval->0.1] 209 | === 21 210 | ] 211 | 212 | 213 | (* ::Subsubsection:: *) 214 | (*Step Size*) 215 | 216 | 217 | TestCase[$RegisteredTests,"PulseSim:StepSize", 218 | Norm[ 219 | Last@Unitaries@PulseSim[{{0,Cos[#]},{Cos[#],0}}&,{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}] 220 | -Last@Unitaries@PulseSim[{{0,Cos[#]},{Cos[#],0}}&,{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}},StepSize->0.01] 221 | ] < 10^-3 222 | ] 223 | 224 | 225 | (* ::Subsubsection:: *) 226 | (*Force Superoperator*) 227 | 228 | 229 | TestCase[$RegisteredTests,"PulseSim:ForceSuperoperator", 230 | Norm[ 231 | First@Last@Superoperators@PulseSim[{{0,1},{1,0}},2,ForceSuperoperator->True] 232 | -{{0.173178189568194` +0.` I,0.` +0.37840124765396416` I,0.` -0.37840124765396416` I,0.8268218104318061` +0.` I},{0.` +0.37840124765396405` I,0.173178189568194` +0.` I,0.826821810431806` +0.` I,0.` -0.3784012476539641` I},{0.` -0.37840124765396405` I,0.826821810431806` +0.` I,0.173178189568194` +0.` I,0.` +0.3784012476539641` I},{0.8268218104318058` +0.` I,0.` -0.378401247653964` I,0.` +0.378401247653964` I,0.17317818956819397` +0.` I}} 233 | ] < $Threshold 234 | ] 235 | 236 | 237 | (* ::Subsubsection:: *) 238 | (*Observables*) 239 | 240 | 241 | TestCase[$RegisteredTests,"PulseSim:Observables", 242 | Norm@Flatten[ 243 | Observables[PulseSim[{{0,1},{1,0}},1,Observables->{{{1,0},{0,-1}}},PollingInterval->.1,InitialState->{{.7,0},{0,.3}}],TimeVector->True] 244 | -{{{0.`,0.39999999999999997`},{0.1`,0.3920266311364967`},{0.2`,0.3684243976011541`},{0.3`,0.3301342459638715`},{0.4`,0.2786826837388663`},{0.5`,0.21612092234725588`},{0.6`,0.14494310179066938`},{0.7`,0.06798685716009634`},{0.8`,-0.011679808920515677`},{0.9`,-0.090880837877235`},{1.`,-0.16645873461885724`}}} 245 | ] < $Threshold 246 | ] 247 | 248 | 249 | (* ::Subsubsection:: *) 250 | (*Functions*) 251 | 252 | 253 | TestCase[$RegisteredTests,"PulseSim:Functions", 254 | Norm@Flatten[ 255 | Functions[PulseSim[{{0,1},{1,0}},1,Functions->{Total[Abs[Flatten[#]]]&},PollingInterval->.1],TimeVector->True] 256 | -{{{0.`,2.`},{0.1`,2.189675163849708`},{0.2`,2.357471817272606`},{0.3`,2.5017133915738916`},{0.4`,2.620958672623072`},{0.5`,2.7140162009891524`},{0.6`,2.7799561766094287`},{0.7`,2.81811974904436`},{0.8`,2.8281256004933777`},{0.9`,2.8098737557962976`},{1.`,2.7635465813520748`}}} 257 | ] < $Threshold 258 | ] 259 | 260 | 261 | (* ::Subsection::Closed:: *) 262 | (*Pulse Sequence*) 263 | 264 | 265 | TestCase[$RegisteredTests,"PulseSim:PulseSequence", 266 | Norm[ 267 | Last@States@PulseSim[{{0,1},{1,0}},{ 268 | {{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}, 269 | {{{0,1},{1,0}},1}, 270 | 2, 271 | {Choi[DiagonalMatrix[{.1,.2,.8,.1}]],1}, 272 | 1, 273 | {{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}, 274 | {Choi[DiagonalMatrix[{.1,.3,.8,.1}]],1}, 275 | {{{0,1},{1,0}},1}, 276 | 2 277 | },InitialState->{{.7,0},{0,.3}}] 278 | -{{0.21328632515588192` -7.960309225208996`*^-18 I,-2.231833193990433`*^-18+ 0.027377296961943964` I},{2.231833193990433`*^-18- 0.027377296961943964` I,0.16599526671828432` -1.1815538400926602`*^-17 I}} 279 | ] < $Threshold 280 | ] 281 | 282 | 283 | TestCase[$RegisteredTests,"PulseSim:PulseSequenceTimeDep", 284 | Norm[ 285 | Last@States@PulseSim[{{0,Cos[#]},{Cos[#],0}}&,{ 286 | {{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}, 287 | {{{0,1},{1,0}},1}, 288 | 2, 289 | {Choi[DiagonalMatrix[{.1,.2,.8,.1}]],1}, 290 | 1, 291 | {{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}, 292 | {Choi[DiagonalMatrix[{.1,.3,.8,.1}]],1}, 293 | {{{0,1},{1,0}},1}, 294 | 2 295 | },InitialState->{{.7,0},{0,.3}}] 296 | -{{0.19362915131935904` +8.655442582853384`*^-18 I,4.0357821396869856`*^-18- 0.031159266734885976` I},{-4.035782139686985`*^-18+ 0.03115926673488599` I,0.17783775701308532` +6.6101240057425336`*^-18 I}} 297 | ] < $Threshold 298 | ] 299 | 300 | 301 | TestCase[$RegisteredTests,"PulseSim:PulseSequenceLindblad", 302 | Norm[ 303 | Last@States@PulseSim[LindbladForm[{{0,1},{1,0}},{{{1,0},{0,-1}}}],{ 304 | {{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}, 305 | {{{0,1},{1,0}},1}, 306 | 2, 307 | {Choi[DiagonalMatrix[{.1,.2,.8,.1}]],1}, 308 | 1, 309 | {{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,1},{1,0}},{{0,I},{-I,0}}}}, 310 | {Choi[DiagonalMatrix[{.1,.3,.8,.1}]],1}, 311 | {{{0,1},{1,0}},1}, 312 | 2 313 | },InitialState->{{.7,0},{0,.3}}] 314 | -{{0.206484207635503` -6.276578586380288`*^-16 I,1.1247658762996243`*^-17+ 0.0037147409808631167` I},{-1.1247658762996234`*^-17- 0.0037147409808631136` I,0.18351579237203836` -5.581130643869315`*^-16 I}} 315 | ] < $Threshold 316 | ] 317 | 318 | 319 | (* ::Subsection::Closed:: *) 320 | (*Over a Distribution*) 321 | 322 | 323 | TestCase[$RegisteredTests,"PulseSim:OverDist", 324 | Norm[ 325 | Observables@PulseSim[{{b,a},{a,b}},{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,b},{b,0}},{{0,I},{-I,0}}}},{{.5,.5},{{a->1,b->1},{a->2,b->3}}},InitialState->{{.7,0},{0,.3}},Observables->{{{a,0},{b,0}}}] 326 | -{{1.0499999999999998`,0.7748695726561399`}} 327 | ] < $Threshold 328 | ] 329 | 330 | 331 | TestCase[$RegisteredTests,"PulseSim:OverDistTimeDep", 332 | Norm[ 333 | Observables@PulseSim[{{Cos[b #],a},{a,Sin[b #]}}&,{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,b},{b,0}},{{0,I},{-I,0}}}},{{.5,.5},{{a->1,b->1},{a->2,b->3}}},InitialState->{{.7,0},{0,.3}},Observables->{{{a,0},{b,0}}}] 334 | -{{1.0499999999999998`,0.8758200899757376`}} 335 | ] < $Threshold 336 | ] 337 | 338 | 339 | TestCase[$RegisteredTests,"PulseSim:OverDistLindblad", 340 | Norm[ 341 | Observables@PulseSim[LindbladForm[{{b,a},{a,b}},{{{a,0},{0,-b}}}],{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}},{{{0,b},{b,0}},{{0,I},{-I,0}}}},{{.5,.5},{{a->1,b->1},{a->2,b->3}}},InitialState->{{.7,0},{0,.3}},Observables->{{{a,0},{b,0}}}] 342 | -{{1.0499999999999998`,0.7499999999681967`}} 343 | ] < $Threshold 344 | ] 345 | 346 | 347 | (* ::Subsection::Closed:: *) 348 | (*End*) 349 | 350 | 351 | End[]; 352 | 353 | 354 | (* ::Section:: *) 355 | (*End Package*) 356 | 357 | 358 | EndPackage[]; 359 | -------------------------------------------------------------------------------- /test/QuantumSystemsTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Quantum Systems Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["QuantumSystemsTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["QuantumSystems`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section::Closed:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsection::Closed:: *) 62 | (*States and Operators*) 63 | 64 | 65 | (* ::Subsubsection::Closed:: *) 66 | (*Spin Operators*) 67 | 68 | 69 | TestCase[$RegisteredTests,"QuantumSystems:SpinNumbers", 70 | And[ 71 | Spin[0]===Spin["I"], 72 | Spin[1]===Spin["X"], 73 | Spin[2]===Spin["Y"], 74 | Spin[3]===Spin["Z"] 75 | ]]; 76 | 77 | 78 | TestCase[$RegisteredTests,"QuantumSystems:SpinMatrix", 79 | And[ 80 | Spin["I"][1/2]===IdentityMatrix[2], 81 | Spin["X"][1/2]==={{0,1},{1,0}}/2, 82 | Spin["Y"][1/2]==={{0,-I},{I,0}}/2, 83 | Spin["Z"][1/2]==={{1,0},{0,-1}}/2, 84 | Spin["P"][1/2]==={{0,1},{0,0}}, 85 | Spin["M"][1/2]==={{0,0},{1,0}}, 86 | Spin["I"][1]===IdentityMatrix[3], 87 | Spin["X"][1]==={{0,1,0},{1,0,1},{0,1,0}}/Sqrt[2], 88 | Spin["Y"][1]==={{0,-I,0},{I,0,-I},{0,I,0}}/Sqrt[2], 89 | Spin["Z"][1]==={{1,0,0},{0,0,0},{0,0,-1}}, 90 | Spin["P"][1]==={{0,1,0},{0,0,1},{0,0,0}}*Sqrt[2], 91 | Spin["M"][1]==={{0,0,0},{1,0,0},{0,1,0}}*Sqrt[2], 92 | Spin["XX+YY-2ZZ"][1/2]==={{-1,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,-1}}/2 93 | ]]; 94 | 95 | 96 | TestCase[$RegisteredTests,"QuantumSystems:SpinSparseArray", 97 | And[ 98 | Spin["I"][1/2,SparseArray]==IdentityMatrix[2,SparseArray], 99 | Spin["X"][1/2,SparseArray]==SparseArray[{{0,1},{1,0}}/2], 100 | Spin["Y"][1/2,SparseArray]==SparseArray[{{0,-I},{I,0}}/2], 101 | Spin["Z"][1/2,SparseArray]==SparseArray[{{1,0},{0,-1}}/2], 102 | Spin["P"][1/2,SparseArray]==SparseArray[{{0,1},{0,0}}], 103 | Spin["M"][1/2,SparseArray]==SparseArray[{{0,0},{1,0}}], 104 | Spin["I"][1,SparseArray]==IdentityMatrix[3,SparseArray], 105 | Spin["X"][1,SparseArray]==SparseArray[{{0,1,0},{1,0,1},{0,1,0}}/Sqrt[2]], 106 | Spin["Y"][1,SparseArray]==SparseArray[{{0,-I,0},{I,0,-I},{0,I,0}}/Sqrt[2]], 107 | Spin["Z"][1,SparseArray]==SparseArray[{{1,0,0},{0,0,0},{0,0,-1}}], 108 | Spin["P"][1,SparseArray]==SparseArray[{{0,1,0},{0,0,1},{0,0,0}}*Sqrt[2]], 109 | Spin["M"][1,SparseArray]==SparseArray[{{0,0,0},{1,0,0},{0,1,0}}*Sqrt[2]], 110 | Spin["XX+YY-2ZZ"][1/2,SparseArray]==SparseArray[{{-1,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,-1}}/2] 111 | ]]; 112 | 113 | 114 | (* ::Subsubsection::Closed:: *) 115 | (*Cavity Operators*) 116 | 117 | 118 | TestCase[$RegisteredTests,"QuantumSystems:CavityMatrix", 119 | And[ 120 | Cavity["I"][2]===IdentityMatrix[2], 121 | Cavity["a"][2]==={{0,1},{0,0}}, 122 | Cavity["c"][2]==={{0,0},{1,0}}, 123 | Cavity["n"][2]==={{0,0},{0,1}}, 124 | Cavity["I"][4]===IdentityMatrix[4], 125 | Cavity["a"][4]===DiagonalMatrix[Sqrt[{1,2,3}],1], 126 | Cavity["c"][4]===DiagonalMatrix[Sqrt[{1,2,3}],-1], 127 | Cavity["n"][4]===DiagonalMatrix[{0,1,2,3}], 128 | Cavity["ac+ca"][2]==={{0,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,0}} 129 | ]]; 130 | 131 | 132 | TestCase[$RegisteredTests,"QuantumSystems:CavitySparseArray", 133 | And[ 134 | Cavity["I"][2,SparseArray]==IdentityMatrix[2,SparseArray], 135 | Cavity["a"][2,SparseArray]==SparseArray[{{0,1},{0,0}}], 136 | Cavity["c"][2,SparseArray]==SparseArray[{{0,0},{1,0}}], 137 | Cavity["n"][2,SparseArray]==SparseArray[{{0,0},{0,1}}], 138 | Cavity["I"][4,SparseArray]==IdentityMatrix[4,SparseArray], 139 | Cavity["a"][4,SparseArray]==SparseArray[DiagonalMatrix[Sqrt[{1,2,3}],1]], 140 | Cavity["c"][4,SparseArray]==SparseArray[DiagonalMatrix[Sqrt[{1,2,3}],-1]], 141 | Cavity["n"][4,SparseArray]==SparseArray[DiagonalMatrix[{0,1,2,3}]], 142 | Cavity["ac+ca"][2,SparseArray]==SparseArray[{{0,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,0}}] 143 | ]]; 144 | 145 | 146 | (* ::Subsubsection::Closed:: *) 147 | (*Quantum States*) 148 | 149 | 150 | TestCase[$RegisteredTests,"QuantumSystems:QStateBloch", 151 | And[ 152 | QState[{"x","y","z"}]=={{1+"z","x"-I "y"},{"x"+I "y",1-"z"}}/2, 153 | QState[{"x1","y1","z2"},{"x2","y2","z2"}]=={ 154 | {(1+"z2")^2,("x2"-I "y2") (1+"z2"),("x1"-I "y1") (1+"z2"),("x1"-I "y1") ("x2"-I "y2")}, 155 | {("x2"+I "y2") (1+"z2"),(1-"z2") (1+"z2"),("x1"-I "y1") ("x2"+I "y2"),("x1"-I "y1") (1-"z2")}, 156 | {("x1"+I "y1") (1+"z2"),("x1"+I "y1") ("x2"-I "y2"),(1-"z2") (1+"z2"),("x2"-I "y2") (1-"z2")}, 157 | {("x1"+I "y1") ("x2"+I "y2"),("x1"+I "y1") (1-"z2"),("x2"+I "y2") (1-"z2"),(1-"z2")^2}}/4 158 | ]]; 159 | 160 | 161 | TestCase[$RegisteredTests,"QuantumSystems:QStateVector", 162 | And[ 163 | AllMatchQ[{1,0}, QState[#,VectorQ->True]&/@{"Zp","H"}], 164 | AllMatchQ[{0,1}, QState[#,VectorQ->True]&/@{"Zm","V"}], 165 | AllMatchQ[{1,1}/Sqrt[2], QState[#,VectorQ->True]&/@{"Xp","D"}], 166 | AllMatchQ[{1,-1}/Sqrt[2], QState[#,VectorQ->True]&/@{"Xm","A"}], 167 | AllMatchQ[{1,I}/Sqrt[2], QState[#,VectorQ->True]&/@{"Yp","R"}], 168 | AllMatchQ[{1,-I}/Sqrt[2], QState[#,VectorQ->True]&/@{"Ym","L"}], 169 | AllMatchQ[{1,0,0,1}/Sqrt[2],QState[#,VectorQ->True]&/@{"B1","Bell1"}], 170 | AllMatchQ[{0,1,1,0}/Sqrt[2],QState[#,VectorQ->True]&/@{"B2","Bell2"}], 171 | AllMatchQ[{0,1,-1,0}/Sqrt[2],QState[#,VectorQ->True]&/@{"B3","Bell3"}], 172 | AllMatchQ[{1,0,0,-1}/Sqrt[2],QState[#,VectorQ->True]&/@{"B4","Bell4"}] 173 | ]]; 174 | 175 | 176 | TestCase[$RegisteredTests,"QuantumSystems:QStateGeneralVector", 177 | And[ 178 | AllMatchQ[{{1},{0}}, QState[#,ColumnVectorQ->True]&/@{"Zp","H"}], 179 | AllMatchQ[{{0},{1}}, QState[#,ColumnVectorQ->True]&/@{"Zm","V"}], 180 | AllMatchQ[{{1},{1}}/Sqrt[2], QState[#,ColumnVectorQ->True]&/@{"Xp","D"}], 181 | AllMatchQ[{{1},{-1}}/Sqrt[2], QState[#,ColumnVectorQ->True]&/@{"Xm","A"}], 182 | AllMatchQ[{{1},{I}}/Sqrt[2], QState[#,ColumnVectorQ->True]&/@{"Yp","R"}], 183 | AllMatchQ[{{1},{-I}}/Sqrt[2], QState[#,ColumnVectorQ->True]&/@{"Ym","L"}], 184 | AllMatchQ[{{1},{0},{0},{1}}/Sqrt[2],QState[#,ColumnVectorQ->True]&/@{"B1","Bell1"}], 185 | AllMatchQ[{{0},{1},{1},{0}}/Sqrt[2],QState[#,ColumnVectorQ->True]&/@{"B2","Bell2"}], 186 | AllMatchQ[{{0},{1},{-1},{0}}/Sqrt[2],QState[#,ColumnVectorQ->True]&/@{"B3","Bell3"}], 187 | AllMatchQ[{{1},{0},{0},{-1}}/Sqrt[2],QState[#,ColumnVectorQ->True]&/@{"B4","Bell4"}] 188 | ]]; 189 | 190 | 191 | TestCase[$RegisteredTests,"QuantumSystems:QStateDensity", 192 | And[ 193 | QState["I"]==IdentityMatrix[2]/2, 194 | AllMatchQ[{{1,0},{0,0}}, QState[#]&/@{"Zp","H"}], 195 | AllMatchQ[{{0,0},{0,1}}, QState[#]&/@{"Zm","V"}], 196 | AllMatchQ[{{1,1},{1,1}}/2, QState[#]&/@{"Xp","D"}], 197 | AllMatchQ[{{1,-1},{-1,1}}/2, QState[#]&/@{"Xm","A"}], 198 | AllMatchQ[{{1,-I},{I,1}}/2, QState[#]&/@{"Yp","R"}], 199 | AllMatchQ[{{1,I},{-I,1}}/2, QState[#]&/@{"Ym","L"}], 200 | AllMatchQ[{{1,0,0,1},{0,0,0,0},{0,0,0,0},{1,0,0,1}}/2, 201 | QState[#]&/@{"B1","Bell1"}], 202 | AllMatchQ[{{0,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}}/2, 203 | QState[#]&/@{"B2","Bell2"}], 204 | AllMatchQ[{{0,0,0,0},{0,1,-1,0},{0,-1,1,0},{0,0,0,0}}/2, 205 | QState[#]&/@{"B3","Bell3"}], 206 | AllMatchQ[{{1,0,0,-1},{0,0,0,0},{0,0,0,0},{-1,0,0,1}}/2, 207 | QState[#]&/@{"B4","Bell4"}] 208 | ]]; 209 | 210 | 211 | (* ::Subsubsection::Closed:: *) 212 | (*Bra-Ket Notation*) 213 | 214 | 215 | TestCase[$RegisteredTests,"QuantumSystems:KetForm", 216 | And[ 217 | AllMatchQ[Ket[Subscript[0,2],Subscript[0,2]],KetForm/@{{1,0,0,0},{{1},{0},{0},{0}}}], 218 | KetForm[{{1,0,0,0}}]===Bra[Subscript[0,2],Subscript[0,2]], 219 | SameQ[KetForm[{"a",0,0,0,0,"b"},{2,3}], 220 | "a"*Ket[Subscript[0,2],Subscript[0,3]]+"b"*Ket[Subscript[1,2],Subscript[2,3]]], 221 | SameQ[KetForm[Array["a",{2,2}]], 222 | "a"[1,1]*KetBra[{Subscript[0,2]},{Subscript[0,2]}]+ 223 | "a"[1,2]*KetBra[{Subscript[0,2]},{Subscript[1,2]}]+ 224 | "a"[2,1]*KetBra[{Subscript[1,2]},{Subscript[0,2]}]+ 225 | "a"[2,2]*KetBra[{Subscript[1,2]},{Subscript[1,2]}]] 226 | ]]; 227 | 228 | 229 | (* ::Subsubsection::Closed:: *) 230 | (*Vec Form*) 231 | 232 | 233 | TestCase[$RegisteredTests,"QuantumSystems:VecForm", 234 | And[ 235 | SameQ[{{1},{0},{0},{0}},VecForm@Ket[Subscript[0,2],Subscript[0,2]]], 236 | SameQ[{{1,0,0,0}},VecForm@Bra[Subscript[0,2],Subscript[0,2]]], 237 | SameQ[{{"a"},{0},{0},{0},{0},{"b"}}, 238 | VecForm["a"*Ket[Subscript[0,2],Subscript[0,3]]+"b"*Ket[Subscript[1,2],Subscript[2,3]]]], 239 | SameQ[Array["a",{2,2}],VecForm[ 240 | "a"[1,1]*KetBra[{Subscript[0,2]},{Subscript[0,2]}]+ 241 | "a"[1,2]*KetBra[{Subscript[0,2]},{Subscript[1,2]}]+ 242 | "a"[2,1]*KetBra[{Subscript[1,2]},{Subscript[0,2]}]+ 243 | "a"[2,2]*KetBra[{Subscript[1,2]},{Subscript[1,2]}]]], 244 | SameQ[VecForm[Ket[Subscript[0,2],Subscript[0,2]].Bra[Subscript[0,2],Subscript[0,2]]], 245 | DiagonalMatrix[{1,0,0,0}]], 246 | SameQ[VecForm[Spin["Z"],Spin->1],{{1,0,0},{0,0,0},{0,0,-1}}], 247 | SameQ[VecForm[CircleTimes[Spin["P"],Cavity["a"]],Cavity->3], 248 | {{0,0,0,0,1,0},{0,0,0,0,0,Sqrt[2]},{0,0,0,0,0,0}, 249 | {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}}] 250 | ]]; 251 | 252 | 253 | (* ::Subsection::Closed:: *) 254 | (*Symbolic Evaluation*) 255 | 256 | 257 | TestCase[$RegisteredTests,"QuantumSystems:QExpand", 258 | SameQ[QExpand[Spin["3XX+2YY"]] 259 | 3CircleTimes[Spin["X"],Spin["X"]]+2*CircleTimes[Spin["Y"],Spin["Y"]]], 260 | SameQ[QExpand[Cavity["ac-ca"]] 261 | CircleTimes[Spin["a"],Spin["c"]]-CircleTimes[Spin["c"],Spin["a"]]] 262 | ]; 263 | 264 | 265 | TestCase[$RegisteredTests,"QuantumSystems:QSimplify:Spin", 266 | And[ 267 | AllMatchQ[ 268 | -I*Spin["Z"], 269 | {QSimplify[Com[Spin["Y"],Spin["X"]]], 270 | QSimplify[Com[Spin["Y"],Spin["X"]],"SpinAlgebra"->"PM"], 271 | QSimplify[Com[Spin["Y"],Spin["X"]],"SpinAlgebra"->"XY"]}], 272 | AllMatchQ[ 273 | -I*Spin["X"], 274 | {QSimplify[Com[Spin["Z"],Spin["Y"]]], 275 | QSimplify[Com[Spin["Z"],Spin["Y"]],"SpinAlgebra"->"XY"]}], 276 | AllMatchQ[ 277 | -I*Spin["Y"], 278 | {QSimplify[Com[Spin["X"],Spin["Z"]]], 279 | QSimplify[Com[Spin["X"],Spin["Z"]],"SpinAlgebra"->"XY"]}], 280 | AllMatchQ[ 281 | Spin["P"], 282 | {QSimplify[Com[Spin["Z"],Spin["P"]]], 283 | QSimplify[Com[Spin["Z"],Spin["P"]],"SpinAlgebra"->"PM"]}], 284 | SameQ[ 285 | Spin["X"]+I*Spin["Y"], 286 | QSimplify[Com[Spin["Z"],Spin["P"]],"SpinAlgebra"->"XY"]], 287 | AllMatchQ[ 288 | -Spin["M"], 289 | {QSimplify[Com[Spin["Z"],Spin["M"]]], 290 | QSimplify[Com[Spin["Z"],Spin["M"]],"SpinAlgebra"->"PM"]}], 291 | SameQ[ 292 | -Spin["X"]+I*Spin["Y"], 293 | QSimplify[Com[Spin["Z"],Spin["M"]],"SpinAlgebra"->"XY"]], 294 | AllMatchQ[ 295 | Spin["I"]/4, 296 | QSimplify[Spin[#]^2,"SpinHalf"->True]&/@{"X","Y","Z"}], 297 | SameQ[ 298 | QSimplify[Spin["M"].Spin["Z"],"OrderSpin"->True], 299 | Spin["Z"].Spin["M"]+Spin["M"]], 300 | SameQ[ 301 | QSimplify[Spin["P"].Spin["Z"],"OrderSpin"->True], 302 | Spin["Z"].Spin["P"]-Spin["P"]], 303 | SameQ[ 304 | QSimplify[Spin["M"].Spin["P"],"OrderSpin"->True], 305 | Spin["P"].Spin["M"]-2 Spin["Z"]] 306 | ]]; 307 | 308 | 309 | TestCase[$RegisteredTests,"QuantumSystems:QSimplify:Cavity", 310 | And[ 311 | QSimplify@Com[Cavity["c"],Cavity["a"]]===-Cavity["I"], 312 | QSimplify@Com[Cavity["a"],Cavity["n"]]===Cavity["a"], 313 | QSimplify@Com[Cavity["c"],Cavity["n"]]===-Cavity["c"], 314 | AllMatchQ[ 315 | "\[Alpha]" Cavity["c"]+Cavity["a"] Conjugate["\[Alpha]"], 316 | QSimplify[Com[Cavity["n"],"\[Alpha]"Cavity["c"]-Conjugate["\[Alpha]"]Cavity["a"],#]]&/@{1,3}] 317 | ]]; 318 | 319 | 320 | TestCase[$RegisteredTests,"QuantumSystems:QSimplify:SpinCavity", 321 | With[{ 322 | h0="w1"Spin["Z"]\[CircleTimes]Cavity["I"]+"w2"Spin["I"]\[CircleTimes]Cavity["n"], 323 | hJC=QSimplify[ConjugateTranspose[#]+#&[Spin["P"]\[CircleTimes]Cavity["a"]]], 324 | hJCm=QSimplify[ConjugateTranspose[#]-#&[Spin["P"]\[CircleTimes]Cavity["a"]]]}, 325 | And[ 326 | QSimplify@Com[h0,hJC,2]==("w1"-"w2")^2*hJC, 327 | QSimplify@Com[h0,hJC,3]==-("w1"-"w2")^3*hJCm, 328 | QSimplify@Com[h0,hJC,4]==("w1"-"w2")^4*hJC 329 | ]]]; 330 | 331 | 332 | TestCase[$RegisteredTests,"QuantumSystems:QSimplify:Algebra", 333 | And[ 334 | QSimplify[CircleTimes["\[Omega]"*Op["a"],"\[Lambda]"*Op["b"]]]=="\[Omega]"*"\[Lambda]"*CircleTimes[Op["a"],Op["b"]], 335 | QSimplify[Dot["\[Omega]"*Op["a"],"\[Lambda]"*Op["b"]]]=="\[Omega]"*"\[Lambda]"*Dot[Op["a"],Op["b"]], 336 | QSimplify[Com["\[Omega]"*Op["a"],"\[Lambda]"*Op["b"]]]=="\[Omega]"*"\[Lambda]"*Com[Op["a"],Op["b"]], 337 | QSimplify[CircleTimes["\[Omega]"*Op["a"]+"\[Lambda]"*Op["b"],"\[Mu]"*Op["c"]]]=="\[Mu]"("\[Omega]"*CircleTimes[Op["a"],Op["c"]]+"\[Lambda]"*CircleTimes[Op["b"],Op["c"]]), 338 | QSimplify[Dot["\[Omega]"*Op["a"]+"\[Lambda]"*Op["b"],"\[Mu]"*Op["c"]]]=="\[Mu]"("\[Omega]"*Op["a"].Op["c"]+"\[Lambda]"*Op["b"].Op["c"]), 339 | QSimplify[Com["\[Omega]"*Op["a"]+"\[Lambda]"*Op["b"],"\[Mu]"*Op["c"]]]=="\[Mu]"("\[Omega]"*Com[Op["a"],Op["c"]]+"\[Lambda]"*Com[Op["b"],Op["c"]]) 340 | ]]; 341 | 342 | 343 | TestCase[$RegisteredTests,"QuantumSystems:QSimplifyRules", 344 | And[ 345 | SameQ[ 346 | QSimplify[Com[Dot[Op["I"]^3].Op["A"],Op["B"]], 347 | QSimplifyRules[Op,{Op["A"],Op["B"]},Identity->True,Com->{{Op["C"]}}]], 348 | Op["C"]], 349 | SameQ[ 350 | QSimplify[Com[Dot[Op["id"]^3].Op["A"],Op["B"]], 351 | QSimplifyRules[Op,{Op["A"],Op["B"]},Com->{{Op["C"]}},Identity->Op["id"]]], 352 | Op["C"]], 353 | SameQ[ 354 | QSimplify[Op["B"].Op["A"], 355 | QSimplifyRules[Op,{Op["A"],Op["B"]},Com->{{Op["C"]}},"NormalOrder"->True]], 356 | Op["A"].Op["B"]-Op["C"]], 357 | SameQ[ 358 | QSimplify[Op["B"].Op["A"], 359 | QSimplifyRules[Op,{Op["A"],Op["B"]},Com->{{Op["C"]}},"NormalOrder"->{Op["B"],Op["A"]}]], 360 | Op["B"].Op["A"]] 361 | ]]; 362 | 363 | 364 | (* ::Subsection::Closed:: *) 365 | (*Quantum Gates*) 366 | 367 | 368 | (* ::Text:: *) 369 | (*Still need to test all the possible configurations*) 370 | 371 | 372 | TestCase[$RegisteredTests,"QuantumSystems:CGate", 373 | And[ 374 | AllMatchQ[ 375 | {{1,0,0,0},{0,1,0,0},{0,0,0,1},{0,0,1,0}}, 376 | {CGate[PauliMatrix[1],2,1],CGate[PauliMatrix[1],2,{1}], 377 | CGate[{PauliMatrix[1]},{2},1],CGate[{2,2},PauliMatrix[1],2,1], 378 | CGate[{2,2},PauliMatrix[1],2,{1}],CGate[{2,2},{PauliMatrix[1]},{2},1], 379 | CGate[PauliMatrix[1],2,1,Control->1],CGate[PauliMatrix[1],2,1,Control->{1}] 380 | CGate[{2,2},PauliMatrix[1],2,1,Control->1],CGate[{2,2},PauliMatrix[1],2,1,Control->{1}]} 381 | ], 382 | AllMatchQ[ 383 | {{1,0,0,0,0,0,0,0},{0,1,0,0,0,0,0,0},{0,0,1,0,0,0,0,0},{0,0,0,1,0,0,0,0}, 384 | {0,0,0,0,1,0,0,0},{0,0,0,0,0,1,0,0},{0,0,0,0,0,0,0,1},{0,0,0,0,0,0,1,0}}, 385 | {CGate[PauliMatrix[1],3,{1,2}],CGate[{PauliMatrix[1]},{3},{1,2}], 386 | CGate[{2,2,2},PauliMatrix[1],3,{1,2}],CGate[{2,2,2},{PauliMatrix[1]},{3},{1,2}], 387 | CGate[PauliMatrix[1],3,{1,2},Control->1],CGate[PauliMatrix[1],3,{1,2},Control->{1,1}], 388 | CGate[{2,2,2},PauliMatrix[1],3,{1,2},Control->1],CGate[{2,2,2},PauliMatrix[1],3,{1,2},Control->{1,1}]} 389 | ], 390 | AllMatchQ[ 391 | {{1,0,0,0,0,0,0,0},{0,1,0,0,0,0,0,0},{0,0,0,1,0,0,0,0},{0,0,1,0,0,0,0,0}, 392 | {0,0,0,0,1,0,0,0},{0,0,0,0,0,1,0,0},{0,0,0,0,0,0,1,0},{0,0,0,0,0,0,0,1}}, 393 | {CGate[{2,2,2},PauliMatrix[1],3,{1,2},Control->{0,1}], 394 | CGate[PauliMatrix[1],3,{1,2},Control->{0,1}], 395 | CGate[{PauliMatrix[1]},{3},{1,2},Control->{0,1}]} 396 | ], 397 | AllMatchQ[ 398 | {{1,0,0,0,0,0,0,0},{0,1,0,0,0,0,0,0},{0,0,1,0,0,0,0,0},{0,0,0,1,0,0,0,0}, 399 | {0,0,0,0,0,0,1,0},{0,0,0,0,0,0,0,-1},{0,0,0,0,1,0,0,0},{0,0,0,0,0,-1,0,0}}, 400 | {CGate[{PauliMatrix[1],PauliMatrix[3]},{2,3},1], 401 | CGate[{2,2,2},{PauliMatrix[1],PauliMatrix[3]},{2,3},1], 402 | CGate[{2,2,2},{PauliMatrix[1],PauliMatrix[3]},{2,3},{1}], 403 | CGate[{2,2,2},{PauliMatrix[1],PauliMatrix[3]},{2,3},1,Control->1]} 404 | ] 405 | ]]; 406 | 407 | 408 | (* ::Subsection::Closed:: *) 409 | (*State Measures*) 410 | 411 | 412 | TestCase[$RegisteredTests,"QuantumSystems:EntropyH", 413 | And[ 414 | EntropyH[{1,1,1,1}/4]===2, 415 | EntropyH[{1,1}/2]===1, 416 | EntropyH[{1,0}]===0 417 | ]]; 418 | 419 | 420 | TestCase[$RegisteredTests,"QuantumSystems:EntropyS", 421 | And[ 422 | EntropyS[IdentityMatrix[2]/2]===1, 423 | EntropyS[DiagonalMatrix[{1,0}]]===0 424 | ]]; 425 | 426 | 427 | TestCase[$RegisteredTests,"QuantumSystems:MutualInformationS", 428 | With[{bell={{1,0,0,1},{0,0,0,0},{0,0,0,0},{1,0,0,1}}/2,z={{1,0},{0,0}}}, 429 | And[ 430 | MutualInformationS[bell]===2, 431 | MutualInformationS[KroneckerProduct[z,z]]===0, 432 | MutualInformationS[KroneckerProduct[z,bell],{2,4}]===0, 433 | MutualInformationS[KroneckerProduct[z,bell],{4,2}]===2 434 | ]]]; 435 | 436 | 437 | TestCase[$RegisteredTests,"QuantumSystems:RelativeEntropyS", 438 | And[ 439 | RelativeEntropyS[{{1,0},{0,0}},{{1,1},{1,1}}/2]===DirectedInfinity[1], 440 | RelativeEntropyS[{{1,0},{0,0}},{{1,0},{0,1}}/2]===1, 441 | RelativeEntropyS[{{1,0},{0,1}}/2,{{1,0},{0,1}}/2]===0 442 | ]]; 443 | 444 | 445 | TestCase[$RegisteredTests,"QuantumSystems:PNorm", 446 | And[ 447 | 0===Norm[PNorm[DiagonalMatrix[{3,1}/4],2]-Sqrt@Total[{9,1}/16]], 448 | 1===PNorm[{{1-1/2,0},{0,-1/2}},1], 449 | 2===PNorm[{{1,0},{0,-1}},1] 450 | ]]; 451 | 452 | 453 | TestCase[$RegisteredTests,"QuantumSystems:Purity", 454 | And[ 455 | Purity[IdentityMatrix[2]/2]===1/2, 456 | Purity[IdentityMatrix[2]/2,Normalize->True]===0, 457 | Purity[DiagonalMatrix[{1/3,2/3}]]===5/9, 458 | Purity[{{1,0},{0,0}}]===1 459 | ]]; 460 | 461 | 462 | TestCase[$RegisteredTests,"QuantumSystems:Fidelity", 463 | With[{ 464 | v1={1,0}, v2={1,1}/Sqrt[2], v3={0,1}, 465 | m1={{1,0},{0,0}}, m2={{1,1},{1,1}}/2, m3={{0,0},{0,1}}}, 466 | And[ 467 | AllMatchQ[1/Sqrt[2],{Fidelity[v1,v2],Fidelity[v1,m2],Fidelity[m1,v2],Fidelity[m1,m2]}], 468 | AllMatchQ[1,{Fidelity[v2,v2],Fidelity[v2,m2],Fidelity[m2,v2],Fidelity[m2,m2]}], 469 | AllMatchQ[0,{Fidelity[v1,v3],Fidelity[v1,m3],Fidelity[m1,v3],Fidelity[m1,m3]}] 470 | ]]]; 471 | 472 | 473 | TestCase[$RegisteredTests,"QuantumSystems:EntangledQ", 474 | And[ 475 | EntangledQ[{{1,0,0,1},{0,0,0,0},{0,0,0,0},{1,0,0,1}}/2], 476 | Not@EntangledQ[DiagonalMatrix[{1,0,0,0}]] 477 | ]]; 478 | 479 | 480 | TestCase[$RegisteredTests,"QuantumSystems:Concurrence", 481 | And[ 482 | Concurrence[{{3,0,0,2},{0,1,0,0},{0,0,1,0},{2,0,0,3}}/8]===1/4, 483 | Concurrence[{{1,0,0,1},{0,0,0,0},{0,0,0,0},{1,0,0,1}}/2]===1, 484 | Concurrence[{{2,0,0,1},{0,1,0,0},{0,0,1,0},{1,0,0,2}}/6]===0 485 | ]]; 486 | 487 | 488 | TestCase[$RegisteredTests,"QuantumSystems:EntanglementF", 489 | And[ 490 | EntanglementF[{{1,0,0,1},{0,0,0,0},{0,0,0,0},{1,0,0,1}}/2]===1, 491 | EntanglementF[{{2,0,0,1},{0,1,0,0},{0,0,1,0},{1,0,0,2}}/6]===0 492 | ]]; 493 | 494 | 495 | (* ::Subsection::Closed:: *) 496 | (*Random Matrices*) 497 | 498 | 499 | TestCase[$RegisteredTests,"QuantumSystems:RandomDensity", 500 | And[ 501 | AllQ[And[Chop[Tr[#]-1]===0,AllQ[#>=0&,Chop@Eigenvalues[#]]]&, 502 | {RandomDensity[4],RandomDensity[4,1], 503 | RandomDensity[4,"HS"],RandomDensity[4,1,"HS"], 504 | RandomDensity[4,"Bures"],RandomDensity[4,1,"Bures"]}], 505 | Norm@Chop[Eigenvalues[RandomDensity[4,1]]-{1,0,0,0}]===0 506 | ]]; 507 | 508 | 509 | TestCase[$RegisteredTests,"QuantumSystems:RandomUnitary", 510 | 0===Norm@Chop[IdentityMatrix[4]-ConjugateTranspose[#].#&@RandomUnitary[4]] 511 | ]; 512 | 513 | 514 | TestCase[$RegisteredTests,"QuantumSystems:RandomHermitian", 515 | 0===Norm@Chop[#-ConjugateTranspose[#]&@RandomHermitian[4]] 516 | ]; 517 | 518 | 519 | (* ::Subsection::Closed:: *) 520 | (*End*) 521 | 522 | 523 | End[]; 524 | 525 | 526 | (* ::Section::Closed:: *) 527 | (*End Package*) 528 | 529 | 530 | EndPackage[]; 531 | -------------------------------------------------------------------------------- /test/TensorTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Predicates Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["TensorTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["Tensor`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section::Closed:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsection::Closed:: *) 62 | (*Matrices and Operations*) 63 | 64 | 65 | TestCase[$RegisteredTests,"Tensor:CircleTimes", 66 | And[ 67 | Module[{a},CircleTimes[a->3]===CircleTimes[a,a,a]], 68 | CircleTimes[{1,0},{1,0}]==={1,0,0,0}, 69 | CircleTimes[{1,0},{{1,0},{0,0}}]==={{1,0},{0,0},{0,0},{0,0}}, 70 | Module[{b},CircleTimes[3,b->2,{1,0}]===3*CircleTimes[b,b,{1,0}]] 71 | ]]; 72 | 73 | 74 | TestCase[$RegisteredTests,"Tensor:\[DoubleStruckOne]", And[Subscript[\[DoubleStruckOne], 0]==={{}}, Subscript[\[DoubleStruckOne], 3]===IdentityMatrix[3]]]; 75 | 76 | 77 | TestCase[$RegisteredTests,"Tensor:BlockMatrix", 78 | SameQ[ 79 | BlockMatrix[{{1,1},{1,1}},{{2,2},{2,2}}], 80 | {{1,1,0,0},{1,1,0,0},{0,0,2,2},{0,0,2,2}} 81 | ]]; 82 | 83 | 84 | TestCase[$RegisteredTests,"Tensor:UnitArray", UnitArray[{2,2},{1,1}]==={{1,0},{0,0}}]; 85 | 86 | 87 | TestCase[$RegisteredTests,"Tensor:TensorFactorPermutations", 88 | Module[{a,b}, 89 | AllMatchQ[ 90 | CircleTimes[a,a,b]+CircleTimes[a,b,a]+CircleTimes[b,a,a], 91 | {TensorFactorPermutations[{a,2},{b,1}], 92 | TensorFactorPermutations[a->2,b->1]}] 93 | 94 | ]]; 95 | 96 | 97 | TestCase[$RegisteredTests,"Tensor:SwapMatrix", 98 | And[ 99 | SwapMatrix[2,{2,1}]==={{1,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1}}, 100 | SwapMatrix[2,{2,1}]===SwapMatrix[{2,2},{2,1}] 101 | ]]; 102 | 103 | 104 | TestCase[$RegisteredTests,"Tensor:Com", 105 | Module[{a,b}, 106 | And[ 107 | Com[a,b,1]===Com[a,b], 108 | Com[a,b,0]===b, 109 | AllMatchQ[0,{Com[1,b],Com[b,\[Pi]],Com[a,Zeta[3],3],Com[1/2,b,2]}], 110 | Com[PauliMatrix[1],PauliMatrix[2]]===2*I*PauliMatrix[3], 111 | Com[PauliMatrix[1],PauliMatrix[2],5]===32*I*PauliMatrix[3] 112 | ]]]; 113 | 114 | 115 | TestCase[$RegisteredTests,"Tensor:ACom", 116 | Module[{a,b}, 117 | And[ 118 | ACom[a,b,1]===ACom[a,b], 119 | ACom[a,b,0]===b, 120 | Norm[ACom[PauliMatrix[1],PauliMatrix[2]]]===0, 121 | Norm[ACom[PauliMatrix[1],PauliMatrix[2],5]]===0 122 | ]]]; 123 | 124 | 125 | TestCase[$RegisteredTests,"Tensor:OuterProduct", 126 | Module[{a,b}, 127 | SameQ[ 128 | OuterProduct[Array[a,2],Array[b,2]], 129 | {{a[1] Conjugate[b[1]],a[1] Conjugate[b[2]]}, 130 | {a[2] Conjugate[b[1]],a[2] Conjugate[b[2]]}}] 131 | ]]; 132 | 133 | 134 | TestCase[$RegisteredTests,"Tensor:Projector", 135 | With[{m={{1,0},{0,0}}}, 136 | And[ 137 | Projector[{1,0}]===m, 138 | Projector[{{1,0}}]===m, 139 | Projector[{{1},{0}}]===m 140 | ] 141 | ]]; 142 | 143 | 144 | (* ::Subsection::Closed:: *) 145 | (*Matrix-Tensor Manipulations*) 146 | 147 | 148 | TestCase[$RegisteredTests,"Tensor:MatrixToTensor", 149 | Module[{a,b}, 150 | SameQ[ 151 | Dimensions[ 152 | MatrixToTensor[ 153 | KroneckerProduct[Array[a,{2,3}],Array[b,{4,5}]], 154 | {{2,4},{3,5}}]], 155 | {2,4,3,5}] 156 | ]]; 157 | 158 | 159 | TestCase[$RegisteredTests,"Tensor:MatrixTranspose", 160 | SameQ[ 161 | MatrixTranspose[IdentityMatrix[4],{2,2},{2,1}], 162 | {{1,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1}}] 163 | ]; 164 | 165 | 166 | TestCase[$RegisteredTests,"Tensor:Swap", 167 | Module[{a,b}, 168 | 0===Norm[Swap[ 169 | KroneckerProduct[Array[a,{2,2}],Array[b,{2,2}]],{2,1}] 170 | -KroneckerProduct[Array[b,{2,2}],Array[a,{2,2}]]] 171 | ]]; 172 | 173 | 174 | TestCase[$RegisteredTests,"Tensor:Reshuffle", 175 | And[ 176 | SameQ[ 177 | Reshuffle[IdentityMatrix[4],{2,2,2,2}], 178 | {{1,0,0,1},{0,0,0,0},{0,0,0,0},{1,0,0,1}}], 179 | SameQ[ 180 | Reshuffle[IdentityMatrix[4],{2,2,2,2},Basis->"Row"], 181 | {{1,0,0,1},{0,0,0,0},{0,0,0,0},{1,0,0,1}}] 182 | ]]; 183 | 184 | 185 | TestCase[$RegisteredTests,"Tensor:Unravel", 186 | With[{X=PauliMatrix[1],Y=PauliMatrix[2],Z=PauliMatrix[3]}, 187 | And[ 188 | Unravel[KroneckerProduct[X,Y,Z,X,Y,Z],2]===KroneckerProduct[X,X,Y,Y,Z,Z], 189 | Unravel[KroneckerProduct[X,Y,Z,X,Y,Z],{2,2,2}]===KroneckerProduct[X,X,Y,Y,Z,Z], 190 | Unravel[KroneckerProduct[X,Y,Z,X,Y,Z]]===KroneckerProduct[X,X,Y,Y,Z,Z] 191 | ]]]; 192 | 193 | 194 | TestCase[$RegisteredTests,"Tensor:Reravel", 195 | With[{X=PauliMatrix[1],Y=PauliMatrix[2],Z=PauliMatrix[3]}, 196 | And[ 197 | Reravel[KroneckerProduct[X,X,Y,Y,Z,Z],2]===KroneckerProduct[X,Y,Z,X,Y,Z], 198 | Reravel[KroneckerProduct[X,X,Y,Y,Z,Z],{2,2,2}]===KroneckerProduct[X,Y,Z,X,Y,Z], 199 | Reravel[KroneckerProduct[X,X,Y,Y,Z,Z]]===KroneckerProduct[X,Y,Z,X,Y,Z] 200 | ]]]; 201 | 202 | 203 | (* ::Subsection::Closed:: *) 204 | (*Matrix-Tensor Contractions*) 205 | 206 | 207 | TestCase[$RegisteredTests,"Tensor:PartialTr", 208 | Module[{a,b}, 209 | Norm@Simplify[ 210 | PartialTr[KroneckerProduct[Array[a,{2,2}],Array[b,{3,3}]],{2,3},{2}] 211 | -Tr[Array[b,{3,3}]]*Array[a,{2,2}] 212 | ]===0 213 | ]]; 214 | 215 | 216 | TestCase[$RegisteredTests,"Tensor:TensorPairContract", 217 | Module[{a,b}, 218 | SameQ[ 219 | TensorPairContract[Array[a,{2,3}],Array[b,{3,4}],{{2,1}}], 220 | Array[a,{2,3}].Array[b,{3,4}]] 221 | ]]; 222 | 223 | 224 | TestCase[$RegisteredTests,"Tensor:MatrixContract", 225 | Module[{a,b}, 226 | Norm@Simplify[ 227 | MatrixContract[KroneckerProduct[Array[a,{2,2}],Array[b,{3,3}]],{2,3},{{2,4}}] 228 | -Tr[Array[b,{3,3}]]*Array[a,{2,2}] 229 | ]===0 230 | ]]; 231 | 232 | 233 | TestCase[$RegisteredTests,"Tensor:MatrixPairContract", 234 | Module[{a,b}, 235 | Norm@Simplify[ 236 | MatrixPairContract[ 237 | {KroneckerProduct[Array[a,{2,2}],Array[b,{3,3}]],{2,3}}, 238 | {{{1,0},{0,0}},{2}},{{1,1},{3,2}}] 239 | -a[1,1]*Array[b,{3,3}] 240 | ]===0 241 | ]]; 242 | 243 | 244 | (* ::Subsection::Closed:: *) 245 | (*Matrix Bases*) 246 | 247 | 248 | TestCase[$RegisteredTests,"Tensor:Basis", 249 | Basis["PO"]===PauliMatrix/@Range[0,3]]; 250 | 251 | 252 | TestCase[$RegisteredTests,"Tensor:BasisLabels", 253 | BasisLabels["PO",2]==={ 254 | "I"\[CircleTimes]"I","I"\[CircleTimes]"X","I"\[CircleTimes]"Y","I"\[CircleTimes]"Z", 255 | "X"\[CircleTimes]"I","X"\[CircleTimes]"X","X"\[CircleTimes]"Y","X"\[CircleTimes]"Z", 256 | "Y"\[CircleTimes]"I","Y"\[CircleTimes]"X","Y"\[CircleTimes]"Y","Y"\[CircleTimes]"Z", 257 | "Z"\[CircleTimes]"I","Z"\[CircleTimes]"X","Z"\[CircleTimes]"Y","Z"\[CircleTimes]"Z"}]; 258 | 259 | 260 | TestCase[$RegisteredTests,"Tensor:ExpressInBasis", 261 | ExpressInBasis[PauliMatrix[1]]==={0,1,0,0}]; 262 | 263 | 264 | (* ::Subsection::Closed:: *) 265 | (*Vectorization*) 266 | 267 | 268 | TestCase[$RegisteredTests,"Tensor:Vec", 269 | Module[{a}, 270 | And[ 271 | Vec[{{a[1],a[2]},{a[3],a[4]}}]==={{a[1]},{a[3]},{a[2]},{a[4]}}, 272 | Vec[{{a[1],a[2]},{a[3],a[4]}},Basis->"Row"]==={{a[1]},{a[2]},{a[3]},{a[4]}}, 273 | Vec[PauliMatrix[1],Basis->"Pauli"]==={{0},{Sqrt[2]},{0},{0}} 274 | ] 275 | ]]; 276 | 277 | 278 | TestCase[$RegisteredTests,"Tensor:Devec", 279 | Module[{a}, 280 | And[ 281 | Devec[{{a[1]},{a[3]},{a[2]},{a[4]}}]==={{a[1],a[2]},{a[3],a[4]}}, 282 | Devec[{{a[1]},{a[2]},{a[3]},{a[4]}},Basis->"Row"]==={{a[1],a[2]},{a[3],a[4]}}, 283 | Devec[{{0},{Sqrt[2]},{0},{0}},Basis->"Pauli"]===PauliMatrix[1] 284 | ] 285 | ]]; 286 | 287 | 288 | TestCase[$RegisteredTests,"Tensor:ProductIdentity", 289 | And[ 290 | SameQ[ 291 | ProductIdentity[PauliMatrix[1],PauliMatrix[2]], 292 | -1*KroneckerProduct[PauliMatrix[2],PauliMatrix[1]]], 293 | SameQ[ 294 | ProductIdentity[PauliMatrix[1],PauliMatrix[2],Basis->"Row"], 295 | -1*KroneckerProduct[PauliMatrix[1],PauliMatrix[2]]] 296 | ]]; 297 | 298 | 299 | TestCase[$RegisteredTests,"Tensor:BasisMatrix", 300 | BasisMatrix["Col"->"Pauli"]==={{1,0,0,1},{0,1,1,0},{0,-I,I,0},{1,0,0,-1}}/Sqrt[2]]; 301 | 302 | 303 | TestCase[$RegisteredTests,"Tensor:BasisTransformation", 304 | BasisTransformation[{0,1,1,0},"Col"->"Pauli"]==={0,Sqrt[2],0,0}]; 305 | 306 | 307 | (* ::Subsection::Closed:: *) 308 | (*Tensor Product Parser*) 309 | 310 | 311 | TestCase[$RegisteredTests,"Tensor:TP", 312 | And[ 313 | TP["XXX"]===CircleTimes[PauliMatrix[1],PauliMatrix[1],PauliMatrix[1]], 314 | Module[{f},TP["ab",Replace->{"a"->"A","b"->"B"},Method->f]===f["A","B"]] 315 | ]]; 316 | 317 | 318 | (* ::Subsection::Closed:: *) 319 | (*End*) 320 | 321 | 322 | End[]; 323 | 324 | 325 | (* ::Section::Closed:: *) 326 | (*End Package*) 327 | 328 | 329 | EndPackage[]; 330 | -------------------------------------------------------------------------------- /test/VisualizationTests.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | (* ::Title:: *) 4 | (*QuantumUtils for Mathematica*) 5 | (*Visualization Unit Tests*) 6 | 7 | 8 | (* ::Subsection::Closed:: *) 9 | (*Copyright and License Information*) 10 | 11 | 12 | (* ::Text:: *) 13 | (*This package is part of QuantumUtils for Mathematica.*) 14 | (**) 15 | (*Copyright (c) 2015 and later, Christopher J. Wood, Christopher E. Granade, Ian N. Hincks*) 16 | (**) 17 | (*Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:*) 18 | (*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.*) 19 | (*2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.*) 20 | (*3. Neither the name of quantum-utils-mathematica nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.*) 21 | (**) 22 | (*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*) 23 | 24 | 25 | (* ::Subsection::Closed:: *) 26 | (*Preamble*) 27 | 28 | 29 | BeginPackage["VisualizationTests`"]; 30 | 31 | 32 | (* ::Text:: *) 33 | (*The following packages are needed, but their contexts should not be loaded globally.*) 34 | 35 | 36 | Needs["QUDevTools`"]; 37 | Needs["Visualization`"]; 38 | 39 | 40 | (* ::Section::Closed:: *) 41 | (*Results*) 42 | 43 | 44 | Begin["`UnitTests`"]; 45 | 46 | 47 | $RegisteredTests={}; 48 | $TestResults := RunTest[$RegisteredTests]; 49 | 50 | 51 | End[]; 52 | 53 | 54 | (* ::Section::Closed:: *) 55 | (*Unit Tests*) 56 | 57 | 58 | Begin["`UnitTests`"]; 59 | 60 | 61 | (* ::Subsection::Closed:: *) 62 | (*End*) 63 | 64 | 65 | End[]; 66 | 67 | 68 | (* ::Section:: *) 69 | (*End Package*) 70 | 71 | 72 | EndPackage[]; 73 | -------------------------------------------------------------------------------- /test/test.m: -------------------------------------------------------------------------------- 1 | (* ::Package:: *) 2 | 3 | #!/usr/local/bin/MathematicaScript -script 4 | 5 | Needs["QUTesting`"]; 6 | RunAllTests[]; 7 | --------------------------------------------------------------------------------