├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE │ ├── BUG_REPORT.md │ └── FEATURE_REQUEST.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── circuits └── example.qasm ├── examples └── webpack │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── dist │ └── index.html │ ├── example.qasm │ ├── package-lock.json │ ├── package.json │ ├── src │ └── index.js │ └── webpack.config.js ├── lerna.json ├── package-lock.json ├── package.json ├── packages ├── qiskit-algo-anu │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── genHex.js │ │ └── utils.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ └── functional.js ├── qiskit-algo-ibm │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── buildCircuit.js │ │ ├── buildCircuits.js │ │ ├── genBin.js │ │ └── utils.js │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ ├── functional.js │ │ ├── integration.js │ │ └── unit.js ├── qiskit-algo-js │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── factor.js │ │ ├── genHex.js │ │ └── utils.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ ├── functional.js │ │ └── unit.js ├── qiskit-algo │ ├── README.md │ ├── cfg.json │ ├── index.js │ ├── lib │ │ └── utils.js │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ └── functional.js ├── qiskit-cloud │ ├── README.md │ ├── cfg.json │ ├── index.js │ ├── lib │ │ ├── massageJob.js │ │ ├── parser.js │ │ ├── request.js │ │ └── utils.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ ├── errorRe.js │ │ ├── functional │ │ ├── 0-new.js │ │ ├── 1-login.js │ │ ├── 2-backend.js │ │ ├── 3-credits.js │ │ ├── 4-run.js │ │ └── 5-jobs.js │ │ └── unit │ │ └── parser.js ├── qiskit-qasm │ ├── README.md │ ├── __snapshots__ │ │ └── parser.test.js │ ├── core │ │ └── qelib1.inc │ ├── example.qasm │ ├── index.js │ ├── lib │ │ ├── Parser.js │ │ ├── QasmError.js │ │ ├── grammar.jison │ │ └── utils.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ └── functional │ │ ├── parser.test.js │ │ └── qasmError.test.js ├── qiskit-sim │ ├── README.md │ ├── example │ │ ├── bell.js │ │ └── deutsch-oracle.js │ ├── index.js │ ├── lib │ │ ├── Circuit.js │ │ ├── gates.js │ │ └── utils.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ └── functional │ │ ├── Circuit.js │ │ ├── gates.js │ │ └── index.js ├── qiskit-utils │ ├── .npmignore │ ├── README.md │ ├── index.js │ ├── lib │ │ └── genRandom.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── .eslintrc.json │ │ └── functional.js └── qiskit │ ├── README.md │ ├── bin │ ├── cmds │ │ ├── backend.js │ │ ├── backends.js │ │ ├── calibration.js │ │ ├── circuit.js │ │ ├── credits.js │ │ ├── factor.js │ │ ├── job.js │ │ ├── jobs.js │ │ ├── login.js │ │ ├── params.js │ │ ├── parse.js │ │ ├── queue.js │ │ ├── random.js │ │ └── result.js │ ├── index.js │ └── lib │ │ ├── logger.js │ │ ├── storage.js │ │ └── utils.js │ ├── index.js │ ├── package-lock.json │ ├── package.json │ └── test │ ├── .eslintrc.json │ └── functional │ ├── bin.js │ └── index.js └── utils-test └── index.js /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @jesusprubio @jelcaf 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at qiskit@qiskit.org. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG_REPORT.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug report 3 | about: Create a report to help us improve 🤔. 4 | --- 5 | 6 | 7 | 8 | 9 | ### Environment (please complete the following information): 10 | 11 | - **Qiskit.js version**: 12 | - **Node.js version**: 13 | - **Operating system**: 14 | 15 | ### What is the current behavior? 16 | 17 | 18 | 19 | ### Steps to reproduce the problem 20 | 21 | 22 | 23 | ### What is the expected behavior? 24 | 25 | 26 | 27 | ### Suggested solutions 28 | 29 | 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature request 3 | about: Suggest an idea for this project 💡! 4 | --- 5 | 6 | 7 | 8 | 9 | ### What is the expected behavior? 10 | 11 | 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ### Summary 12 | 13 | 14 | 15 | ### Details and comments 16 | 17 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.csv 2 | *.dat 3 | *.iml 4 | *.log 5 | *.out 6 | *.pid 7 | *.seed 8 | *.swo 9 | *.swp 10 | *.tgz 11 | *.xml 12 | .DS_Store 13 | .idea 14 | .project 15 | .strong-pm 16 | coverage 17 | *.lock 18 | *.sublime-* 19 | 20 | # Node.js. 21 | node_modules 22 | npm-debug.log 23 | .jshintrc 24 | .jslintrc 25 | .editorconfig 26 | lerna-debug.log 27 | 28 | dist/*.js 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "10" 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | **We appreciate all kinds of help, so thank you!** :clap: :kissing_heart: 4 | 5 | You can contribute in many ways to this project. 6 | 7 | ## Issue reporting 8 | 9 | :fire: This is a goog point to start, when you find a problem please add it to the [issue traker](https://github.com/Qiskit/qiskit-js/issues). 10 | 11 | ## Doubts solving 12 | 13 | :two_women_holding_hands: To help less advanced users is another wonderful way to start. You can help us to close some opened issues. This kind of tickets should be labeled as `question`. 14 | 15 | ## Improvement proposal 16 | 17 | :smiling_imp: If you have an idea for a new feature please open a ticket labeled as `enhancement`. If you could also add a piece of code with the idea or a partial implementation it would be awesome. 18 | 19 | ## Documentation 20 | 21 | :eyes: We all know the doc always need fixes/upgrades :wink:, so please feel free to send a PR (see next point) with what you found. 22 | 23 | ## Code 24 | 25 | :star: This section include some tips that will help you to push source code. 26 | 27 | ### Doc 28 | 29 | Review the parts of the documentation regarding the new changes and update it if it is needed. 30 | 31 | ### License 32 | 33 | All our open source sofware is published under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0.txt). 34 | 35 | Please, add your name in the head comment of each file you contribute to (under the tag "Authors"). 36 | 37 | ### Pull requests 38 | 39 | * We use [GitHub pull requests](https://help.github.com/articles/about-pull-requests) to accept the contributions. 40 | * Review the parts of the documentation regarding the new changes and update it if it's needed. 41 | * New features often imply changes in the existent tests or new ones are needed. Once they're updated/added please be sure they keep passing. 42 | 43 | ### Commits 44 | 45 | Please follow the next rules for the commit messages: 46 | 47 | * It should be formed by a one-line subject, followed by one line of white space. Followed by one or more descriptive paragraphs, each separated by one line of white space. All of them finished by a dot. 48 | * If it fixes an issue, it should include a reference to the issue ID in the first line of the commit. 49 | * It should provide enough information for a reviewer to understand the changes and their relation to the rest of the code. 50 | 51 | From here, depending of the nature of the project, we have specific recommendations about the code style, the debuggins engine or how to run the tests and the rest of security checks. Please visit the one regarding your project. 52 | 53 | ## Environment 54 | 55 | * A better way to install [Node.js](https://nodejs.org) for developers is to use [nvm](https://github.com/creationix/nvm), to test different versions. 56 | * Get the code and install all dependencies: 57 | 58 | ```sh 59 | https://github.com/Qiskit/qiskit-js 60 | cd qiskit-js 61 | npm i 62 | npm start -- --help 63 | ``` 64 | 65 | ### Style guide 66 | 67 | Submit clean code and please make effort to follow existing conventions in order to keep it as readable as possible. We love ES6, so we use [ESLint](http://eslint.org/) and the [Airbnb](https://github.com/airbnb/javascript) style guide. It's the most complete, so it forces the developers to keep a consistent style. Moreover, we auto-format the code in each commit, thanks to [Prettier](https://github.com/prettier/prettier). Please run to be sure your code fits with it: 68 | 69 | ```sh 70 | npm run lint 71 | ``` 72 | 73 | ### Test 74 | 75 | We've chosen the [Mocha](https://mochajs.org) testing engine with the core ["assert"](https://nodejs.org/api/assert.html) module. 76 | 77 | ```sh 78 | npm test 79 | 80 | # To include also the ones which need an API key. 81 | QX_KEY=your_api_key npm test 82 | ``` 83 | 84 | This command also checks for: 85 | 86 | * Style linting. 87 | * Outdated/lost/unused dependencies. 88 | * Insecure dependencies. 89 | 90 | ### Debugging 91 | 92 | To debug we use the [visionmedia module](https://github.com/visionmedia/debug). So you have to use the proper environment variable with the name of the project: 93 | 94 | ```sh 95 | DEBUG=qiskit* npm start 96 | DEBUG=qiskit:bin* npm start 97 | ``` 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js 2 | 3 | [![Build Status](https://travis-ci.com/Qiskit/qiskit-js.svg?branch=master)](https://travis-ci.com/Qiskit/qiskit-js) 4 | [![stability-experimental](https://img.shields.io/badge/stability-experimental-orange.svg)](https://github.com/emersion/stability-badges#experimental) 5 | [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lernajs.io/) 6 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) 7 | [![Downloads](https://img.shields.io/npm/dm/qiskit.svg)](https://npmjs.com/qiskit) 8 | 9 | :atom_symbol: [Quantum Information Science Kit](https://qiskit.org) for JavaScript, I was born as a clone of [my big brother](https://github.com/Qiskit/qiskit-terra). 10 | 11 |
12 |

13 | logo 14 |

15 |

16 | :gift: Follow us on Twitter if you like this project 17 |

18 |
19 | 20 | **Alpha**: Until v1 breaking changes could be included. 21 | 22 | ## Philosophy 23 | 24 | :orange_book: The basic concept of our quantum program is an array of quantum circuits. The program workflow consists of three stages: Build, Compile, and Run. Build allows you to make different quantum circuits that represent the problem you are solving. Compile allows you to rewrite them to run on different backends (simulators/real chips of different quantum volumes, sizes, fidelity, etc); and Run launches the jobs. After the jobs have been run, the data is collected. There are methods for putting this data together, depending on the program. This either gives you the answer you wanted or allows you to make a better program for the next instance. 25 | 26 | If you want to learn more about Quantum Computing, you're invited to visit our [Quamtum Experience](https://quantumexperience.ng.bluemix.net) project. 27 | 28 | ## Structure 29 | 30 | :handbag: The components of this repository are exposed as these libraries: 31 | 32 | * [qiskit](./packages/qiskit): Meta-package, documented in this file. It also includes a command line client, which is your friend if you want to play with all these features without having to use any programming language. 33 | * [@qiskit/algo](./packages/qiskit-algo): High level algorithms, thought for developers. 34 | * [@qiskit/algo-js](./packages/qiskit-algo-js): JavaScript engine. 35 | * [@qiskit/algo-anu](./packages/qiskit-algo-anu): [Australian National University](http://www.anu.edu.au) [Quantum Random Numbers Server](https://qrng.anu.edu.au) engine. 36 | * [@qiskit/algo-ibm](./packages/qiskit-algo-ibm): Quantum Experience engine. 37 | * [@qiskit/cloud](./packages/qiskit-cloud): Library to make easier the interaction with the Quantum Experience. 38 | * [@qiskit/utils](./packages/qiskit-utils): Helpers shared among all packages. 39 | * [@qiskit/qasm](./packages/qiskit-qasm): Some [OpenQASM](https://github.com/IBM/qiskit-openqasm) tools, like parser. 40 | * [@qiskit/sim](./packages/qiskit-sim): An experimental JS simulator for OpenQASM circuits we're working on. 41 | 42 | ### Qiskit for the browser 43 | 44 | :inbox_tray: All components are compatible with [browserify](http://browserify.org). 45 | 46 | ## Install 47 | 48 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 49 | 50 | ```sh 51 | npm i -g qiskit 52 | ``` 53 | 54 | ## Use 55 | 56 | ### CLI 57 | 58 | :rocket: The command line client allows to play with the circuits without having to use any programming language API. 59 | 60 | ```sh 61 | qiskitjs --help 62 | ``` 63 | ``` 64 | qiskitjs 65 | 66 | Commands: 67 | backend [name] - Get latest calibration stats for a backend [aliases: b] 68 | backends [onlySims] - Get latest calibration stats for a backend [aliases: bs] 69 | calibration [backend] - Get latest calibration stats for a backend [aliases: c] 70 | circuit [backend] [shots] [name] [seed] [maxCredits] - Send the circuit to be run in the Quantum 71 | Experience (https://quantumexperience.ng.bluemix.net) [aliases: ci] 72 | credits - Information about your credits [aliases: cr] 73 | factor - Calculate a factor of a number [aliases: f] 74 | job - Get the info of a specific job [aliases: j] 75 | jobs [limit] [offset] - Get all your jobs. Ordered by creation date [aliases: js] 76 | login [printToken] - Use an API key to get a token to make requests [aliases: l] 77 | params [backend] - Get latest parameter stats for a backend [aliases: p] 78 | parse - Parse the circuit to our IR (intermediate representation - JSON format) [aliases: p] 79 | queue [backend] - Get the status of a backend queue [aliases: q] 80 | random [engine] [length] [format] [backend] - Generate a true random number among 0 and 1 [aliases: r] 81 | result - Get the result of a background job generated by an algorithm method. The engine is ommited 82 | because IBM Q is the unique which uses background jobs for now [aliases: re] 83 | 84 | Options: 85 | --help Show help [boolean] 86 | --version Show version number [boolean] 87 | ``` 88 | 89 | ### Programatically 90 | 91 | :pencil: As you can see in the next section, we have to use it like in the rest of independent modules. The only difference is we need to select the proper field of the main object before. 92 | 93 | ```js 94 | const qiskit = require('qiskit'); 95 | 96 | console.log('True random numbers\n'); 97 | 98 | qiskit.algo.random().then(rand => console.log(`JavaScript: ${rand}`)); 99 | 100 | const cloud = new qiskit.Cloud(); 101 | cloud.login('YOUR_PERSONAL_TOKEN_HERE').then(() => { 102 | cloud.backends().then(data => { 103 | console.log('(IBM Backends'); 104 | console.log(data); 105 | }); 106 | 107 | qiskit.algo.random({ 108 | engine: 'ibm', 109 | custom: cloud, 110 | // default: simulator 111 | // engine: "ibmqx4" 112 | }).then(rand => console.log(`IBM Cloud: ${rand}`)) 113 | }); 114 | 115 | qiskit.algo.random({ 116 | engine: 'anu', 117 | length: 8, 118 | }).then(rand => console.log(`ANU Server: ${rand}`)); 119 | ``` 120 | 121 | ## API 122 | 123 | :eyes: Full specification. 124 | 125 | ### `version` 126 | 127 | The actual version of the library. 128 | 129 | * `version` (string) - Version number. 130 | 131 | ### `qasm` 132 | 133 | A wrapper for the [`qiskit-qasm`](./packages/qiskit-qasm) project. 134 | 135 | * `qasm` (object) - The same object provided in the original library. 136 | 137 | ### `sim` 138 | 139 | A wrapper for the [`qiskit-sim`](./packages/qiskit-sim) project. 140 | 141 | * `sim` (object) - The same object provided in the original library. 142 | 143 | ### `Cloud` 144 | 145 | A wrapper for the [`qiskit-cloud`](./packages/qiskit-cloud) project. 146 | 147 | * `Cloud` (object) - The same constructor provided in the original library. 148 | 149 | ### `utils` 150 | 151 | A wrapper for the [`qiskit-utils`](./packages/qiskit-utils) project. 152 | 153 | * `utils` (object) - The same object provided in the original library. 154 | 155 | ### `algo` 156 | 157 | A wrapper for the [`qiskit-algo`](./packages/qiskit-algo) project. 158 | 159 | * `algo` (object) - The same object provided in the original library. 160 | 161 | ## Authors 162 | 163 | :alien: https://github.com/Qiskit/qiskit-js/graphs/contributors 164 | 165 | Original code (Python) authors [here](https://github.com/Qiskit/qiskit-sdk-py#authors-alphabetical). 166 | 167 | ## Other Qiskit projects 168 | 169 | :school_satchel: 170 | 171 | * [Python Qiskit](https://github.com/Qiskit/qiskit-terra) 172 | * [ibmqx backend information](https://github.com/Qiskit/ibmqx-backend-information): Information about the different IBM Q experience backends. 173 | * [ibmqx user guide](https://github.com/Qiskit/ibmqx-user-guides): The users guides for the IBM Q experience. 174 | * [OpenQasm](https://github.com/Qiskit/openqasm): Examples and tools for the OpenQASM intermediate representation. 175 | * [Python API](https://github.com/Qiskit/qiskit-api-py): API Client to use IBM Q experience in Python. 176 | * [Tutorials](https://github.com/Qiskit/qiskit-tutorial): Jupyter notebooks for using Qiskit. 177 | 178 | ## License 179 | 180 | :penguin: Qiskit is released under the [Apache license, v2.0](https://www.apache.org/licenses/LICENSE-2.0). 181 | 182 | ## Do you want to help? 183 | 184 | :sunglasses: If you'd like to help please take a look to our [contribution guidelines](./CONTRIBUTING.md). 185 | -------------------------------------------------------------------------------- /circuits/example.qasm: -------------------------------------------------------------------------------- 1 | 2 | OPENQASM 2.0; 3 | // include "qelib1.inc"; 4 | qreg q[3]; 5 | qreg r[3]; 6 | h q; 7 | // Should error: Undefined gate 8 | //uu q; 9 | 10 | // Should error: too many params 11 | //h q a 12 | 13 | // Should error: no ; 14 | // h q 15 | cx q, r; 16 | // cx q[0], r[2]; 17 | creg c[3]; 18 | creg d[3]; 19 | barrier q; 20 | // barrier q[0]; 21 | // barrier q[0],q[1]; 22 | measure q->c; 23 | // measure q[0]->c[0]; 24 | measure r->d; 25 | -------------------------------------------------------------------------------- /examples/webpack/.gitignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | node_modules 3 | dist/main.js 4 | -------------------------------------------------------------------------------- /examples/webpack/README.md: -------------------------------------------------------------------------------- 1 | ### Qiskit/qasm Webpack example 2 | The purpose of this project is to serve as an example of how the qiskit-js QASM 3 | parser can be used in a browser environment. 4 | 5 | ### Install 6 | ```console 7 | $ npm i 8 | ``` 9 | ### Build 10 | ``` 11 | $ npm run build 12 | ``` 13 | 14 | ### Run 15 | ```console 16 | $ open dist/index.html 17 | ``` 18 | -------------------------------------------------------------------------------- /examples/webpack/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Qiskit Webpack example 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/webpack/example.qasm: -------------------------------------------------------------------------------- 1 | IBMQASM 2.0; 2 | include "qelib1.inc"; 3 | qreg q[1]; 4 | creg c[1]; 5 | 6 | x q[1]; 7 | measure q -> c; 8 | -------------------------------------------------------------------------------- /examples/webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qiskit-webpack-example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "build": "webpack" 7 | }, 8 | "files": [ 9 | "package.json", 10 | "README.md", 11 | "LICENSE", 12 | "index.js" 13 | ], 14 | "devDependencies": { 15 | "@babel/core": "^7.5.5", 16 | "@babel/preset-env": "^7.5.5", 17 | "babel-loader": "^8.0.6", 18 | "brfs": "^2.0.2", 19 | "transform-loader": "^0.2.4", 20 | "webpack": "^4.39.1", 21 | "webpack-cli": "^3.3.6" 22 | }, 23 | "dependencies": { 24 | "@qiskit/sim": "^0.10.0" 25 | }, 26 | "type": "module" 27 | } 28 | -------------------------------------------------------------------------------- /examples/webpack/src/index.js: -------------------------------------------------------------------------------- 1 | import sim from '@qiskit/sim' 2 | 3 | function component() { 4 | const element = document.createElement('div'); 5 | element.innerHTML = `@Qiskit/sim: ${sim.version}`; 6 | return element; 7 | } 8 | 9 | document.body.appendChild(component()); 10 | -------------------------------------------------------------------------------- /examples/webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/index.js', 5 | mode: "development", 6 | target: 'web', 7 | node: { 8 | fs: 'empty' 9 | }, 10 | output: { 11 | filename: 'main.js', 12 | path: path.resolve(__dirname, 'dist') 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.m?js$/, 18 | loader: `transform-loader?brfs`, 19 | }, 20 | ], 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.9.0", 3 | "lerna": "2.0.0", 4 | "packages": [ 5 | "packages/*" 6 | ], 7 | "publishConfig": { 8 | "ignore": [ 9 | "test/**" 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qiskit-js", 3 | "scripts": { 4 | "start": "node packages/qiskit/bin", 5 | "install": "lerna bootstrap", 6 | "clean": "lerna clean --yes", 7 | "publish": "npm i && lerna publish", 8 | "precommit": "lint-staged", 9 | "lint": "eslint .", 10 | "deps": "depcheck --ignore-dirs=dist --ignores='mocha,lint-staged,prettier,eslint-config-airbnb-base,eslint-config-prettier,eslint-plugin-import' && lerna run deps", 11 | "test-algo": "lerna run test --scope @qiskit/algo", 12 | "test-algo-js": "lerna run test --scope @qiskit/algo-js", 13 | "test-algo-ibm": "lerna run test --scope @qiskit/algo-ibm", 14 | "test-algo-anu": "lerna run test --scope @qiskit/algo-anu", 15 | "test-qasm": "lerna run test --scope @qiskit/qasm", 16 | "test-cloud": "lerna run test --scope @qiskit/cloud", 17 | "test-sdk": "lerna run test --scope qiskit", 18 | "test-sim": "lerna run test --scope @qiskit/sim", 19 | "test-utils": "lerna run test --scope @qiskit/utils", 20 | "pretest": "npm i && npm run lint && npm run deps", 21 | "test": "lerna run test" 22 | }, 23 | "lint-staged": { 24 | "*.js": [ 25 | "eslint --fix", 26 | "prettier --write", 27 | "git add" 28 | ] 29 | }, 30 | "devDependencies": { 31 | "depcheck": "^0.8.0", 32 | "eslint": "^5.16.0", 33 | "eslint-config-airbnb-base": "^13.1.0", 34 | "eslint-config-prettier": "^4.3.0", 35 | "eslint-plugin-import": "^2.17.2", 36 | "lerna": "^3.14.1", 37 | "lint-staged": "^8.1.7", 38 | "mocha": "^6.1.4", 39 | "prettier": "^1.17.1", 40 | "snap-shot-it": "^7.4.4", 41 | "strip-color": "^0.1.0" 42 | }, 43 | "engines": { 44 | "node": ">=10" 45 | }, 46 | "private": true, 47 | "eslintConfig": { 48 | "extends": [ 49 | "airbnb-base", 50 | "prettier" 51 | ], 52 | "env": { 53 | "es6": true, 54 | "node": true 55 | }, 56 | "rules": { 57 | "strict": [ 58 | "off" 59 | ] 60 | } 61 | }, 62 | "eslintIgnore": [ 63 | "**/node_modules/*", 64 | "dist", 65 | "*.jison", 66 | "snapshots__", 67 | "examples/webpack" 68 | ], 69 | "prettier": { 70 | "singleQuote": true, 71 | "trailingComma": "all" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/qiskit-algo-anu/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js algo (ANU) 2 | 3 | The [Australian National University](http://www.anu.edu.au) [Quantum Random Numbers Server](https://qrng.anu.edu.au) engine (chip) for the [Qiskit algorithms package](https://github.com/Qiskit/qiskit-js/tree/master/packages/qiskit-algo). 4 | 5 | ## Install 6 | 7 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 8 | 9 | ```sh 10 | npm i @qiskit/algo-anu 11 | ``` 12 | 13 | ## Use 14 | 15 | :pencil: You can visit the complete example [in this test](./test/functional.js). 16 | 17 | ```js 18 | const qiskit = require('@qiskit/algo-anu'); 19 | 20 | console.log('Version'); 21 | console.log(qiskit.version); 22 | ``` 23 | 24 | ## API 25 | 26 | :eyes: Please check the [main doc](../../README.md#API). The methods signature is the same but: 27 | 28 | * As expected, the `engine` parameter is omitted here. 29 | * Only the `random` method is supported. 30 | -------------------------------------------------------------------------------- /packages/qiskit-algo-anu/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const genHex = require('./lib/genHex'); 15 | const { version } = require('./package'); 16 | 17 | module.exports.version = version; 18 | 19 | module.exports.random = async opts => utils.genRandom(genHex, opts); 20 | -------------------------------------------------------------------------------- /packages/qiskit-algo-anu/lib/genHex.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const rp = require('request-promise-native'); 13 | 14 | const utils = require('./utils'); 15 | 16 | const dbg = utils.dbg(__filename); 17 | 18 | async function getHex(len) { 19 | if (len < 1) { 20 | throw new Error('Invalid length (< 1)'); 21 | } 22 | 23 | const body = await rp({ 24 | uri: 'http://qrng.anu.edu.au/API/jsonI.php', 25 | qs: { 26 | type: 'hex16', 27 | size: '1', 28 | length: len, 29 | }, 30 | json: true, 31 | }); 32 | 33 | if (!body.success) { 34 | throw new Error('Unknown error'); 35 | } 36 | 37 | return body.data; 38 | } 39 | 40 | module.exports = async (len = 16) => { 41 | // "/2" The library expects the number of octects and we ask for number of 42 | // hexadecimal digits (8 octets = 16 hex chars). 43 | const octects = await getHex(len / 2); 44 | dbg('Generated number (octects):', { octects, len: octects.length }); 45 | 46 | if (!octects || !utils.isArray(octects)) { 47 | throw new Error('Parsing the result (octects)'); 48 | } 49 | 50 | const strHex = octects.join(''); 51 | dbg('Random string (hex):', { strHex }); 52 | 53 | return strHex; 54 | }; 55 | -------------------------------------------------------------------------------- /packages/qiskit-algo-anu/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const pkgName = require('../package.json').name; 15 | 16 | utils.dbg = fullPath => utils.debug(`${pkgName}:${utils.pathToTag(fullPath)}`); 17 | 18 | module.exports = utils; 19 | -------------------------------------------------------------------------------- /packages/qiskit-algo-anu/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/algo-anu", 3 | "version": "0.9.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "lodash": { 8 | "version": "4.17.11", 9 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", 10 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" 11 | }, 12 | "psl": { 13 | "version": "1.1.31", 14 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", 15 | "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" 16 | }, 17 | "punycode": { 18 | "version": "2.1.1", 19 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 20 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 21 | }, 22 | "request-promise-core": { 23 | "version": "1.1.2", 24 | "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", 25 | "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", 26 | "requires": { 27 | "lodash": "^4.17.11" 28 | } 29 | }, 30 | "request-promise-native": { 31 | "version": "1.0.7", 32 | "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", 33 | "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", 34 | "requires": { 35 | "request-promise-core": "1.1.2", 36 | "stealthy-require": "^1.1.1", 37 | "tough-cookie": "^2.3.3" 38 | } 39 | }, 40 | "stealthy-require": { 41 | "version": "1.1.1", 42 | "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", 43 | "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" 44 | }, 45 | "tough-cookie": { 46 | "version": "2.5.0", 47 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 48 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 49 | "requires": { 50 | "psl": "^1.1.28", 51 | "punycode": "^2.1.1" 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/qiskit-algo-anu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/algo-anu", 3 | "version": "0.9.0", 4 | "description": "Australia National University engine for Qiskit algorithms", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://github.com/Qiskit/qiskit-js", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "files": [ 18 | "lib", 19 | "index.js" 20 | ], 21 | "scripts": { 22 | "deps": "depcheck", 23 | "test": "mocha --recursive test --timeout 20000 --color" 24 | }, 25 | "keywords": [ 26 | "quantum", 27 | "computing", 28 | "information", 29 | "algorithms", 30 | "random", 31 | "shor", 32 | "Australian National University" 33 | ], 34 | "bugs": { 35 | "url": "https://github.com/Qiskit/qiskit-js/issues" 36 | }, 37 | "dependencies": { 38 | "@qiskit/utils": "^0.9.0", 39 | "request-promise-native": "^1.0.7" 40 | }, 41 | "engines": { 42 | "node": ">=10" 43 | }, 44 | "license": "Apache-2.0", 45 | "publishConfig": { 46 | "access": "public" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/qiskit-algo-anu/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit-algo-anu/test/functional.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const utils = require('@qiskit/utils'); 15 | 16 | const qiskit = require('..'); 17 | const { name, version } = require('../package'); 18 | const genHex = require('../lib/genHex'); 19 | 20 | const dbg = utils.debug(`${name}:test`); 21 | 22 | describe('algo:anu:api', () => { 23 | it('should include all documented items', () => { 24 | assert.equal( 25 | utils.difference(['version', 'random'], Object.keys(qiskit)), 26 | 0, 27 | ); 28 | }); 29 | }); 30 | 31 | describe('algo:anu:version', () => { 32 | it('should be included', () => assert.equal(qiskit.version, version)); 33 | }); 34 | 35 | describe('algo:anu:random', () => { 36 | it('should return a number between 0 and 1 without options', async function t() { 37 | this.retries(4); 38 | 39 | const res = await qiskit.random(); 40 | dbg('Result', res); 41 | 42 | assert.ok(res >= 0); 43 | assert.ok(res <= 1); 44 | }); 45 | }); 46 | 47 | describe('algo:anu:genHex', () => { 48 | it('should return a hex string of the default length without options', async function t() { 49 | this.retries(4); 50 | 51 | const res = await genHex(); 52 | dbg('Result', res); 53 | 54 | assert.ok(typeof res === 'string'); 55 | assert.ok(res.length === 16); 56 | }); 57 | 58 | it('algo:anu:should return a hex string of the desired length if passed', async function t() { 59 | this.retries(4); 60 | 61 | const len = 8; 62 | const res = await genHex(len); 63 | dbg('Result', res); 64 | 65 | assert.ok(typeof res === 'string'); 66 | assert.ok(res.length === len); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js algo (IBM Q) 2 | 3 | [IBM Q](https://www.research.ibm.com/ibm-q) engine (chip and remote simulator) for the [Qiskit algorithms package](https://github.com/Qiskit/qiskit-js/tree/master/packages/qiskit-algo). 4 | 5 | ## Install 6 | 7 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 8 | 9 | ```sh 10 | npm i @qiskit/algo-ibm 11 | ``` 12 | 13 | ## Use 14 | 15 | :pencil: You can visit the complete example [in this test](./test/functional.js). 16 | 17 | ```js 18 | const Cloud = require('qiskit/cloud'); 19 | const qiskit = require('qiskit/algo-ibm'); 20 | 21 | const cloud = new Cloud(); 22 | cloud.login('YOUR_PERSONAL_TOKEN_HERE') 23 | .then(() => { 24 | cloud.backends() 25 | .then(data => { 26 | console.log('Backends:'); 27 | console.log(data); 28 | }); 29 | 30 | qiskit.random({ 31 | custom: cloud, 32 | // default: simulator 33 | // engine: "ibmqx4" 34 | }) 35 | .then(rand => console.log(`Random: ${rand}`)) 36 | }); 37 | ``` 38 | 39 | ## API 40 | 41 | :eyes: Please check the [main doc](../../README.md#API). The method signature is the same but: 42 | 43 | - As expected, the `engine` parameter is omitted here. 44 | - All algorithms need a background job, so a `jobId` is returned. 45 | - About the options: 46 | - `custom` (object): Mandatory here, it should be a logged [qiskit-cloud](../qiskit-cloud) instance. 47 | - `backend` (string): Name of the backend to use. (default: simulator) 48 | - `shots` (number): Number of times to run the circuit. (default: 1) 49 | - `maxCredits` (number): Max number of the credits to run this job. The task will be cancelled if it needs more. 50 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('./lib/utils'); 13 | const genBin = require('./lib/genBin'); 14 | const { version } = require('./package'); 15 | 16 | const dbg = utils.dbg(__filename); 17 | 18 | module.exports.version = version; 19 | 20 | module.exports.random = async (opts = {}) => { 21 | dbg('Passed opts:', opts); 22 | 23 | // We use opts being required to respect the qiskit-algo methods signature. 24 | if (!opts.custom || typeof opts.custom !== 'object') { 25 | throw new Error( 26 | 'The "opts.custom" option is mandatory (a "@qiskit/cloud" logged instance)', 27 | ); 28 | } 29 | 30 | if (opts.length) { 31 | if (typeof opts.length !== 'number') { 32 | throw new TypeError('A number expected in "length" option'); 33 | } 34 | } 35 | const length = opts.length || 16; 36 | 37 | if (opts.shots) { 38 | if (typeof opts.shots !== 'number') { 39 | throw new TypeError('A number expected in "shots" option'); 40 | } 41 | } 42 | const shots = opts.shots || 1; 43 | 44 | if (opts.maxCredits) { 45 | if (typeof opts.maxCredits !== 'number') { 46 | throw new TypeError('A number expected in "shots" option'); 47 | } 48 | } 49 | const maxCredits = opts.maxCredits || null; 50 | 51 | if (opts.backend && typeof opts.backend !== 'string') { 52 | throw new TypeError('A string expected in "backend" option'); 53 | } 54 | const backend = opts.backend || 'simulator'; 55 | 56 | dbg('Parsed opts:', { length, shots, backend }); 57 | 58 | return genBin(opts.custom, { 59 | length, 60 | backend, 61 | shots, 62 | maxCredits, 63 | }); 64 | }; 65 | 66 | module.exports.result = async (jobId, opts = {}) => { 67 | // We use opts being required to respect the qiskit-algo methods signature. 68 | if (!opts.custom || typeof opts.custom !== 'object') { 69 | throw new Error( 70 | 'The "opts.custom" option is mandatory (a "@qiskit/cloud" logged instance)', 71 | ); 72 | } 73 | 74 | if (!jobId || typeof jobId !== 'string') { 75 | throw new TypeError('The "jobId" parameter is mandatory (string)'); 76 | } 77 | const cloud = opts.custom; 78 | 79 | const res = await cloud.job(jobId); 80 | 81 | const result = { status: res.status.toLowerCase() }; 82 | 83 | if (result.status !== 'completed') { 84 | return result; 85 | } 86 | 87 | const binaryArray = utils.map(res.circuits, resCircuit => { 88 | if ( 89 | !resCircuit.result || 90 | !resCircuit.result.data || 91 | !resCircuit.result.data.counts || 92 | typeof resCircuit.result.data.counts !== 'object' 93 | ) { 94 | throw new Error(`Parsing the circuits result: ${JSON.stringify(res)}`); 95 | } 96 | 97 | return Object.keys(resCircuit.result.data.counts)[0]; 98 | }); 99 | dbg('Generated partial number (binary-array):', { 100 | binaryArray, 101 | len: binaryArray.length, 102 | }); 103 | 104 | const binary = binaryArray.join(''); 105 | dbg('Generated partial number (binary):', { binary }); 106 | 107 | const decimal = utils.ayb.parseInt(binary, 2, 10); 108 | dbg('Generated number (decimal):', { decimal }); 109 | 110 | // To return a value between 0 and 1 (similar to "Math.floor") 111 | result.data = decimal / 10 ** decimal.toString().length; 112 | 113 | return result; 114 | }; 115 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/lib/buildCircuit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('./utils'); 13 | const { version } = require('../package'); 14 | 15 | const dbg = utils.debug(__filename); 16 | 17 | module.exports = (neededQubits = 4) => { 18 | let circuit = 19 | `// Cirtuit generated by Qiskit.js, version: ${version}\n\n` + 20 | // Includes. 21 | 'include "qelib1.inc";\n\n' + 22 | // Register declarations. 23 | `qreg q[${neededQubits}];\n` + 24 | `creg c[${neededQubits}];\n\n`; 25 | 26 | let i = 0; 27 | utils.times(neededQubits, () => { 28 | circuit += `h q[${i}];\n`; 29 | i += 1; 30 | }); 31 | 32 | circuit += '\n'; 33 | 34 | i = 0; 35 | utils.times(neededQubits, () => { 36 | circuit += `measure q[${i}] -> c[${i}];\n`; 37 | i += 1; 38 | }); 39 | 40 | dbg('Built circuit:', { circuit }); 41 | return circuit; 42 | }; 43 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/lib/buildCircuits.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('./utils'); 13 | const buildCircuit = require('./buildCircuit'); 14 | 15 | const dbg = utils.debug(__filename); 16 | 17 | module.exports = (len = 16, backendQubits = 4) => { 18 | // TODO: Add types/values checking. 19 | 20 | // 1 hex char : 4 bits 21 | const neededQubits = len * 4; 22 | const circuits = []; 23 | 24 | // ie: 25 | // - len = 4 -> neededQubits = 16 26 | // - backendQubits = 16 27 | // ------------------------------ 28 | // - len = 3 -> neededQubits = 4 29 | // - backendQubits = 16 30 | if (neededQubits <= backendQubits) { 31 | return [buildCircuit(neededQubits)]; 32 | } 33 | 34 | const circuit = buildCircuit(backendQubits); 35 | // ie: 36 | // - len = 8 -> neededQubits = 32 37 | // - backendQubits = 4 38 | // - blocksNumber = 32 / 4 = 7 39 | // - blocksNumberExtra = 32 % 4 = 0 40 | // -------------------------- 41 | // - len = 8 -> neededQubits = 32 42 | // - backendQubits = 5 43 | // - blocksNumber = 32 / 5 = 6.5 -> 6, 6*5 = 35 44 | // - blocksNumberExtra = 32 % 5 = 2 45 | const circuitsNumber = Math.floor(neededQubits / backendQubits); 46 | const circuitExtraQubits = neededQubits % backendQubits; 47 | dbg('Parameters', { backendQubits, circuitsNumber, circuitExtraQubits }); 48 | 49 | utils.times(circuitsNumber, () => circuits.push(circuit)); 50 | 51 | dbg('Built circuits', { circuits }); 52 | 53 | if (circuitExtraQubits) { 54 | const circuitExtra = buildCircuit(circuitExtraQubits); 55 | dbg('Built circuit (extra)', { circuitExtra }); 56 | 57 | circuits.push(circuitExtra); 58 | } 59 | 60 | return circuits; 61 | }; 62 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/lib/genBin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('./utils'); 13 | const buildCircuits = require('./buildCircuits'); 14 | 15 | const dbg = utils.debug(__filename); 16 | 17 | function buildParam(circuit) { 18 | return { qasm: circuit }; 19 | } 20 | 21 | // TODO: Reuse "utils.genRandom" like in the other "qiskit-algo=*" packages. 22 | module.exports = async (cloud, opts = {}) => { 23 | const len = opts.length || 16; 24 | const backendName = opts.backend || 'simulator'; 25 | 26 | const backendQubits = (await cloud.backend(backendName)).nQubits; 27 | const circuits = buildCircuits(len, backendQubits); 28 | const circuitsMassaged = utils.map(circuits, buildParam); 29 | 30 | // Marking it to know how to parse the response later' 31 | // TODO: It would be better to mark the whole job, but the library and/or API 32 | // doesn't support it for now. 33 | circuitsMassaged[0].name = 'random'; 34 | dbg('Massaged circuits', circuitsMassaged); 35 | 36 | const res = await cloud.runBatch(circuitsMassaged, { 37 | backend: opts.backend || 'simulator', 38 | shots: opts.shots || 1, 39 | maxCredits: opts.maxCredits || null, 40 | }); 41 | 42 | if (!res.status || res.status !== 'RUNNING') { 43 | throw new Error(`Running the circuit: ${res}`); 44 | } 45 | 46 | return res.id; 47 | }; 48 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const pkgName = require('../package.json').name; 15 | 16 | utils.dbg = fullPath => utils.debug(`${pkgName}:${utils.pathToTag(fullPath)}`); 17 | 18 | module.exports = utils; 19 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/algo-ibm", 3 | "version": "0.9.0", 4 | "description": "IBM Q engine for Qiskit algorithms", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://github.com/Qiskit/qiskit-js", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "files": [ 18 | "lib", 19 | "index.js" 20 | ], 21 | "scripts": { 22 | "deps": "depcheck", 23 | "test": "mocha --recursive test --timeout 20000 --color" 24 | }, 25 | "keywords": [ 26 | "quantum", 27 | "experience", 28 | "computing", 29 | "information", 30 | "algorithms", 31 | "random", 32 | "shor", 33 | "factor", 34 | "IBM" 35 | ], 36 | "bugs": { 37 | "url": "https://github.com/Qiskit/qiskit-js/issues" 38 | }, 39 | "dependencies": { 40 | "@qiskit/utils": "^0.9.0" 41 | }, 42 | "devDependencies": { 43 | "@qiskit/cloud": "^0.9.0" 44 | }, 45 | "engines": { 46 | "node": ">=10" 47 | }, 48 | "license": "Apache-2.0", 49 | "publishConfig": { 50 | "access": "public" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/test/functional.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | // eslint-disable-next-line import/no-extraneous-dependencies 15 | const Cloud = require('@qiskit/cloud'); 16 | 17 | const algo = require('..'); 18 | const { version } = require('../package'); 19 | 20 | const cloud = new Cloud(); 21 | global.qiskit = {}; 22 | 23 | // TODO: Use utils.difference instead. 24 | function multiIncludes(text, values) { 25 | return values.every(val => text.includes(val)); 26 | } 27 | 28 | describe('algo:ibm:api', () => { 29 | it('should include all documented items', () => { 30 | assert.ok(multiIncludes(Object.keys(algo), ['random', 'result'])); 31 | }); 32 | 33 | it('should return the the correct result for its methods', () => 34 | assert.equal(algo.version, version)); 35 | }); 36 | 37 | describe('algo:ibm:version', () => 38 | it('should be correct', () => assert.equal(algo.version, version))); 39 | 40 | let jobId; 41 | describe('algo:ibm:random', () => { 42 | before(async function t() { 43 | if (!process.env.QX_KEY) { 44 | cloud.token = 'notvalid'; 45 | cloud.userId = 'notvalid'; 46 | 47 | /* eslint-disable no-console */ 48 | console.log( 49 | '\n\n\n\t-------------------------------------------------------------', 50 | ); 51 | console.log('\tWARNING'); 52 | console.log('\tQX_KEY env var not found, so skipping integration tests.'); 53 | console.log( 54 | '\t-------------------------------------------------------------\n\n\n', 55 | ); 56 | /* eslint-enable no-console */ 57 | 58 | this.skip(); 59 | } 60 | 61 | global.qiskit.cloud = cloud; 62 | await cloud.login(process.env.QX_KEY); 63 | }); 64 | 65 | it('should return a jobId', async () => { 66 | if (!global.qiskit || !global.qiskit.cloud) { 67 | this.skip(); 68 | } 69 | 70 | const res = await algo.random({ custom: cloud }); 71 | assert.equal(typeof res, 'string'); 72 | assert(res.length >= 0); 73 | 74 | jobId = res; 75 | }); 76 | }); 77 | 78 | describe('algo:ibm:result', () => { 79 | it('should return the result passing jobId', async function t() { 80 | if (!global.qiskit || !global.qiskit.cloud) { 81 | this.skip(); 82 | } 83 | 84 | const res = await algo.result(jobId, { custom: cloud }); 85 | 86 | assert.equal(res.status, 'running'); 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/test/integration.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const genBin = require('../lib/genBin'); 15 | 16 | describe('algo:ibm:genBin', () => { 17 | it('should return a jobId', async function t() { 18 | if (!global.qiskit || !global.qiskit.cloud) { 19 | this.skip(); 20 | } 21 | const res = await genBin(global.qiskit.cloud); 22 | 23 | assert.equal(typeof res, 'string'); 24 | assert(res.length >= 0); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/qiskit-algo-ibm/test/unit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const buildCircuit = require('../lib/buildCircuit'); 15 | const buildCircuits = require('../lib/buildCircuits'); 16 | const utils = require('../lib/utils'); 17 | const { version } = require('../package.json'); 18 | 19 | const expectedCircuit = 20 | `// Cirtuit generated by Qiskit.js, version: ${version}\n\n` + 21 | 'include "qelib1.inc";\n\n' + 22 | 'qreg q[4];\n' + 23 | 'creg c[4];\n\n' + 24 | 'h q[0];\n' + 25 | 'h q[1];\n' + 26 | 'h q[2];\n' + 27 | 'h q[3];\n\n' + 28 | 'measure q[0] -> c[0];\n' + 29 | 'measure q[1] -> c[1];\n' + 30 | 'measure q[2] -> c[2];\n' + 31 | 'measure q[3] -> c[3];\n'; 32 | 33 | describe('algo:ibm:buildCircuit', () => { 34 | it('should return a circuit for the default lenght', () => 35 | assert.equal(buildCircuit(), expectedCircuit)); 36 | 37 | it('should return a circuit with the provided option "lenght"', () => { 38 | const circuit = buildCircuit(2); 39 | 40 | assert.equal(circuit.slice(0, 10), expectedCircuit.slice(0, 10)); 41 | 42 | const splitted = circuit.split('\n').filter(Boolean); 43 | assert.equal(splitted[splitted.length - 1], 'measure q[1] -> c[1];'); 44 | }); 45 | }); 46 | 47 | describe('algo:ibm:buildCircuits', () => { 48 | it('should return a group of circuits for the default options', () => { 49 | const circuits = buildCircuits(); 50 | 51 | assert.equal(16, circuits.length); 52 | utils.map(circuits, circuit => assert.equal(circuit, expectedCircuit)); 53 | }); 54 | 55 | it( 56 | 'should return a group of circuits for "lenght" option' + 57 | 'higher than the supported by "backendQubits" (odd)', 58 | () => { 59 | const circuits = buildCircuits(4, 5); 60 | 61 | assert.equal(4, circuits.length); 62 | 63 | const splitted = circuits[2].split('\n').filter(Boolean); 64 | assert.equal(splitted[splitted.length - 1], 'measure q[4] -> c[4];'); 65 | 66 | const splitted3 = circuits[3].split('\n').filter(Boolean); 67 | assert.equal(splitted3[splitted3.length - 1], 'measure q[0] -> c[0];'); 68 | }, 69 | ); 70 | 71 | const message = 72 | 'should return a single circuits (keeping array format) for' + 73 | ' "lenght" option lower than the supported by "backendQubits"'; 74 | 75 | it(message, () => { 76 | const circuits = buildCircuits(4, 16); 77 | 78 | assert.equal(1, circuits.length); 79 | const splitted = circuits[0].split('\n').filter(Boolean); 80 | assert.equal(splitted[splitted.length - 1], 'measure q[15] -> c[15];'); 81 | }); 82 | 83 | it(`${message} (odd)`, () => { 84 | let circuits = buildCircuits(4, 7); 85 | 86 | assert.equal(3, circuits.length); 87 | let splitted = circuits[0].split('\n').filter(Boolean); 88 | assert.equal(splitted[splitted.length - 1], 'measure q[6] -> c[6];'); 89 | 90 | circuits = buildCircuits(3, 16); 91 | 92 | assert.equal(1, circuits.length); 93 | splitted = circuits[0].split('\n').filter(Boolean); 94 | assert.equal(splitted[splitted.length - 1], 'measure q[11] -> c[11];'); 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js algo (pure JavaScript) 2 | 3 | Pure JS engine ([jsqubits](https://www.npmjs.com/package/jsqubits) based) engine (simulator) for the [Qiskit algorithms package](https://github.com/Qiskit/qiskit-js/tree/master/packages/qiskit-algo). 4 | 5 | ## Install 6 | 7 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 8 | 9 | ```sh 10 | npm i @qiskit/algo-js 11 | ``` 12 | 13 | ## Use 14 | 15 | :pencil: You can visit the complete example [in this test](test/functional.js). 16 | 17 | ```js 18 | const qiskit = require('@qiskit/algo-js'); 19 | 20 | console.log('Version'); 21 | console.log(qiskit.version); 22 | ``` 23 | 24 | ## API 25 | 26 | :eyes: Please check the [main doc](../../README.md#API). The methods signature is the same but: 27 | 28 | * As expected, the `engine` parameter is omitted here. 29 | * All algorithms doesn't need a background job, so a result is returned (vs a `jobId`). 30 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const genHex = require('./lib/genHex'); 15 | const factor = require('./lib/factor'); 16 | const { version } = require('./package'); 17 | 18 | module.exports.version = version; 19 | 20 | module.exports.random = opts => utils.genRandom(genHex, opts); 21 | 22 | // TODO: Make it fit with the doc. 23 | module.exports.factor = factor; 24 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/lib/factor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | // Shor's factoring algorithm. 13 | // See https://cs.uwaterloo.ca/~watrous/lecture-notes/519/11.pdf 14 | // Initially forked from from here: 15 | // https://github.com/davidbkemp/qubits/blob/master/examples/algorithms/factoring.js 16 | 17 | const qubits = require('jsqubits').jsqubits; 18 | 19 | const qubitsMath = qubits.QMath; 20 | const utils = require('./utils'); 21 | 22 | const dbg = utils.dbg(__filename); 23 | 24 | function computeOrder(a, n) { 25 | const numOutBits = Math.ceil(Math.log(n) / Math.log(2)); 26 | const numInBits = 2 * numOutBits; 27 | const inputRange = 2 ** numInBits; 28 | const outputRange = 2 ** numOutBits; 29 | const accuracyRequiredForContinuedFraction = 30 | 1 / (2 * outputRange * outputRange); 31 | const outBits = { 32 | from: 0, 33 | to: numOutBits - 1, 34 | }; 35 | const inputBits = { 36 | from: numOutBits, 37 | to: numOutBits + numInBits - 1, 38 | }; 39 | const f = x => qubitsMath.powerMod(a, x, n); 40 | const f0 = f(0); 41 | 42 | // Quantum computation 43 | // It returns either the frequency of the function f or some integer multiple 44 | // (where "frequency" is the number of times the period of f will fit into 2^numInputBits) 45 | function determineFrequency(fu) { 46 | let qstate = new qubits.QState(numInBits + numOutBits).hadamard(inputBits); 47 | qstate = qstate.applyFunction(inputBits, outBits, fu); 48 | // We do not need to measure the outBits, but it does speed up the simulation. 49 | qstate = qstate.measure(outBits).newState; 50 | 51 | return qstate.qft(inputBits).measure(inputBits).result; 52 | } 53 | 54 | // Determine the period of f (i.e. find r such that f(x) = f(x+r). 55 | function findPeriod() { 56 | let bestSoFar = 1; 57 | 58 | for (let attempts = 0; attempts < 2 * numOutBits; attempts += 1) { 59 | // NOTE: Here we take advantage of the fact that, for Shor's algorithm, 60 | // we know that f(x) = f(x+i) ONLY when i is an integer multiple of the rank r. 61 | if (f(bestSoFar) === f0) { 62 | dbg(`The period of ${a}^x mod ${n} is ${bestSoFar}`); 63 | return bestSoFar; 64 | } 65 | 66 | dbg('Starting quantum computation ...'); 67 | const sample = determineFrequency(f); 68 | dbg('Done quantum computation, result', { sample }); 69 | 70 | // Each "sample" has a high probability of being approximately equal to some 71 | // integer multiple of (inputRange/r) rounded to the nearest integer. 72 | // So we use a continued fraction function to find r (or a divisor of r). 73 | const continuedFraction = qubitsMath.continuedFraction( 74 | sample / inputRange, 75 | accuracyRequiredForContinuedFraction, 76 | ); 77 | // The denominator is a "candidate" for being r or a divisor of r (hence we need to find 78 | // the least common multiple of several of these). 79 | const candidateDivisor = continuedFraction.denominator; 80 | dbg('Candidate divisor of r: ', { candidateDivisor }); 81 | 82 | // Reduce the chances of getting the wrong answer by ignoring obviously wrong results! 83 | if (candidateDivisor > 1 && candidateDivisor <= outputRange) { 84 | if (f(candidateDivisor) === f0) { 85 | dbg('This is a multiple of the rank'); 86 | bestSoFar = candidateDivisor; 87 | } else { 88 | const lcm = qubitsMath.lcm(candidateDivisor, bestSoFar); 89 | if (lcm <= outputRange) { 90 | dbg('This is a good candidate'); 91 | bestSoFar = lcm; 92 | } 93 | } 94 | } 95 | dbg('Least common multiple so far: ', { bestSoFar, attempts }); 96 | } 97 | dbg(`Giving up trying to find rank of ${a}`); 98 | return 'failed'; 99 | } 100 | 101 | // Step 2: compute the period of a^x mod n 102 | return findPeriod(); 103 | } 104 | 105 | module.exports = n => { 106 | if (n % 2 === 0) { 107 | dbg('Even number!'); 108 | return 2; 109 | } 110 | 111 | const powerFactor = qubitsMath.powerFactor(n); 112 | if (powerFactor > 1) { 113 | dbg('Power factor!'); 114 | 115 | return powerFactor; 116 | } 117 | 118 | for (let attempts = 0; attempts < 8; attempts += 1) { 119 | const randomChoice = 2 + Math.floor(Math.random() * (n - 2)); 120 | dbg(`Step 1: choose random number between 2 and ${n}`, { randomChoice }); 121 | const gcd = qubitsMath.gcd(randomChoice, n); 122 | if (gcd > 1) { 123 | dbg( 124 | `Lucky guess, ${n} and randomly chosen ${randomChoice} have a common factor`, 125 | { gcd }, 126 | ); 127 | return gcd; 128 | } 129 | 130 | const r = computeOrder(randomChoice, n); 131 | if (r !== 'failed' && r % 2 !== 0) { 132 | dbg(`Need a period with an even number. Sadly, ${r} is not`); 133 | } else if (r !== 'failed' && r % 2 === 0) { 134 | const powerMod = qubitsMath.powerMod(randomChoice, r / 2, n); 135 | const candidateFactor = qubitsMath.gcd(powerMod - 1, n); 136 | dbg('Candidate factor computed from period', { candidateFactor }); 137 | if (candidateFactor > 1 && n % candidateFactor === 0) { 138 | return candidateFactor; 139 | } 140 | } 141 | dbg('Try again'); 142 | } 143 | 144 | // throw new Error('Failed'); 145 | return 'failed'; 146 | }; 147 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/lib/genHex.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qubits = require('jsqubits').jsqubits; 13 | 14 | const utils = require('./utils'); 15 | 16 | const dbg = utils.dbg(__filename); 17 | 18 | module.exports = (len = 16) => { 19 | let strHex = ''; 20 | 21 | // We make it in steps (char by char) to avoid a huge CPU load. It's not 22 | // the best strategy for a cloud engine but this is a local one. 23 | utils.times(len, () => { 24 | // 1 char : 4 bits 25 | const binChar = qubits('|0000>') 26 | .hadamard(qubits.ALL) 27 | .measure(qubits.ALL) 28 | .asBitString(); 29 | 30 | strHex += utils.ayb.parseInt(binChar, 2, 16); 31 | }); 32 | 33 | dbg('Random string (hex):', { strHex }); 34 | return strHex; 35 | }; 36 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const pkgName = require('../package.json').name; 15 | 16 | utils.dbg = fullPath => utils.debug(`${pkgName}:${utils.pathToTag(fullPath)}`); 17 | 18 | module.exports = utils; 19 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/algo-js", 3 | "version": "0.9.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "jsqubits": { 8 | "version": "1.1.0", 9 | "resolved": "https://registry.npmjs.org/jsqubits/-/jsqubits-1.1.0.tgz", 10 | "integrity": "sha512-T2bijcpQjOGxNDnwrLRLPmUneg0Lekp/aoaeWF9QKVEcR90zIXODoLh3nbGzYOvnOehkvi/teFOLIrdFnTKWng==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/algo-js", 3 | "version": "0.9.0", 4 | "description": "Pure JavaScript engine for Qiskit algorithms", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://github.com/Qiskit/qiskit-js", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "files": [ 18 | "lib", 19 | "index.js" 20 | ], 21 | "scripts": { 22 | "deps": "depcheck --skip-missing=true", 23 | "test": "mocha --recursive test --timeout 20000 --color" 24 | }, 25 | "keywords": [ 26 | "quantum", 27 | "experience", 28 | "computing", 29 | "information", 30 | "algorithms", 31 | "random", 32 | "shor", 33 | "factor" 34 | ], 35 | "bugs": { 36 | "url": "https://github.com/Qiskit/qiskit-js/issues" 37 | }, 38 | "dependencies": { 39 | "@qiskit/utils": "^0.9.0", 40 | "jsqubits": "^1.1.0" 41 | }, 42 | "engines": { 43 | "node": ">=10" 44 | }, 45 | "license": "Apache-2.0", 46 | "publishConfig": { 47 | "access": "public" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/test/functional.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const utils = require('../lib/utils'); 15 | 16 | const qiskit = require('..'); 17 | const { version } = require('../package'); 18 | 19 | const dbg = utils.dbg(__filename); 20 | 21 | describe('algo:js:api', () => { 22 | it('should include all documented items', () => { 23 | assert.equal( 24 | utils.difference(['version', 'random', 'factor'], Object.keys(qiskit)), 25 | 0, 26 | ); 27 | }); 28 | }); 29 | 30 | describe('algo:js:version', () => { 31 | it('should be included', () => assert.equal(qiskit.version, version)); 32 | }); 33 | 34 | describe('algo:js:random', () => { 35 | it('should return a number between 0 and 1 without options', async () => { 36 | const res = await qiskit.random(); 37 | dbg('Result', res); 38 | 39 | assert.ok(res >= 0); 40 | assert.ok(res <= 1); 41 | }); 42 | }); 43 | 44 | describe('algo:js:factor', () => { 45 | it('should work for a small integer', async () => { 46 | const res = await qiskit.factor(15); 47 | dbg('Result', res); 48 | 49 | assert(res === 3 || res === 5); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /packages/qiskit-algo-js/test/unit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const utils = require('../lib/utils'); 15 | const genHex = require('../lib/genHex'); 16 | 17 | const dbg = utils.dbg(__filename); 18 | 19 | describe('algo:js:genHex', () => { 20 | it('should return a hex string of the default length without options', async () => { 21 | const res = await genHex(); 22 | dbg('Result', res); 23 | 24 | assert.ok(typeof res === 'string'); 25 | assert.ok(res.length === 16); 26 | }); 27 | 28 | it('should return a hex string of the desired length if passed', async () => { 29 | const len = 8; 30 | const res = await genHex(len); 31 | dbg('Result', res); 32 | 33 | assert.ok(typeof res === 'string'); 34 | assert.ok(res.length === len); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /packages/qiskit-algo/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit for developers 2 | 3 | :atom_symbol: Quantum Information Science Kit algorithms for developers. The idea is to hide all quantum mechanics complexity exposing only the upper layer. 4 | 5 | Please visit the [main repository](https://github.com/Qiskit/qiskit-js) of the project to know about the rest of the tools. 6 | 7 | ## Install 8 | 9 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 10 | 11 | ```sh 12 | npm i @qiskit/algo 13 | ``` 14 | 15 | ## Use 16 | 17 | :pencil: As you can see in the next section, we have to use it like in the rest of independent modules. The only difference is we need to pass the engine as any other option. 18 | 19 | ```js 20 | const qiskit = require('@qiskit/algo'); 21 | 22 | // With the default engine and length. 23 | qiskit.random().then(rand => console.log(`Random number(default): ${rand}`)); 24 | 25 | qiskit 26 | .random({ 27 | engine: 'anu', 28 | length: 8, 29 | }) 30 | .then(rand => console.log(`Random number: ${rand}`)); 31 | ``` 32 | 33 | ## API 34 | 35 | :eyes: Full specification. Here are reflected the common options among the different engines, but some of them can receive (even need) extra ones, ie: an API key. Please check the [packages]. 36 | 37 | ### `version` 38 | 39 | The actual version of the library. 40 | 41 | - `version` (string) - Version number. 42 | 43 | ### `async random(opts) -> rand | jobId` 44 | 45 | Generate a true random number among 0 and 1. 46 | 47 | - `opts` (object) - Optional parameters: 48 | - `engine` (string) - Where to run the operation. Please visit the [packages] to see the supported ones. The number of digits depends on the selected engine. (default: "js") 49 | - `length` (number) - Number of random hex characters to ask for to the engine. As you can see in the doc referenced before each engine has different limit, they will throw in it's overpassed. (default: 16) 50 | - `format` (string) - To ask for the result in a different format, supported ("hex"). 51 | - `custom` (string/object) - Custom stuff (API key, inited connector instance, etc) needed for some backends (visit each specific doc). 52 | - `rand` (number) - Generated random number in the desired format if the operation doesn't involves a background job. 53 | - `jobId` (string) - Identifier for the generated background job (see next method). 54 | 55 | ### `async result(jobId, opts) -> result` 56 | 57 | Get the result of a background job generated by an algorithm method. The engine is ommited because IBM Q is the unique which uses background jobs for now. 58 | 59 | - `jobId` (string) - Job identifier got as initial response. 60 | - `opts`(object) - Optional parameters: 61 | - `custom` 62 | - `result` (?) - Depending on the used agorithm: 63 | - "random": (object) - With nex fields: 64 | - `status` (string) - To know if the job has finished correctly. Supported: "running", "completed", TODO. 65 | - `data` (number) - Generated random number. Only present if "status" is "completed". 66 | 67 | ### `async factor(number) -> prime` 68 | 69 | Integer factorization in prime numbers using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm). **Only supported in the local simulator for now**, so the engine is also ommited here for now. The result can be invalid, retry in this clase. 70 | 71 | - `number` (number/string) - Number to factorize, an integer for now. 72 | - `prime` (number) - Prime factor of the passed one. 73 | 74 | [packages]: ./.. 75 | -------------------------------------------------------------------------------- /packages/qiskit-algo/cfg.json: -------------------------------------------------------------------------------- 1 | { 2 | "engines": { 3 | "supported": ["js", "anu", "ibm"], 4 | "default": "js" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/qiskit-algo/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const engineJs = require('@qiskit/algo-js'); 13 | const engineAnu = require('@qiskit/algo-anu'); 14 | const engineIbm = require('@qiskit/algo-ibm'); 15 | 16 | const utils = require('./lib/utils'); 17 | const { version } = require('./package'); 18 | const cfg = require('./cfg'); 19 | 20 | const dbg = utils.dbg(__filename); 21 | const enginesList = cfg.engines.supported; 22 | const engines = { 23 | js: engineJs, 24 | anu: engineAnu, 25 | ibm: engineIbm, 26 | }; 27 | 28 | module.exports.version = version; 29 | 30 | module.exports.random = async (opts = {}) => { 31 | dbg('Passed opts:', opts); 32 | 33 | const engine = opts.engine || cfg.engines.default; 34 | 35 | if (!utils.includes(enginesList, engine)) { 36 | throw new TypeError(`Bad engine, supported: ${JSON.stringify(engines)}`); 37 | } 38 | 39 | return engines[engine].random(opts); 40 | }; 41 | 42 | // TODO: For now we only have "ibm" supporting background jobs. 43 | // We should do the same that for "random". 44 | module.exports.result = engines.ibm.result; 45 | 46 | module.exports.factor = async n => engines.js.factor(n); 47 | -------------------------------------------------------------------------------- /packages/qiskit-algo/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const pkgName = require('../package.json').name; 15 | 16 | utils.dbg = fullPath => utils.debug(`${pkgName}:${utils.pathToTag(fullPath)}`); 17 | 18 | module.exports = utils; 19 | -------------------------------------------------------------------------------- /packages/qiskit-algo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/algo", 3 | "version": "0.9.0", 4 | "description": "Quantum Information algorithms for developers", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://github.com/Qiskit/qiskit-js", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "files": [ 18 | "lib", 19 | "cfg.json", 20 | "index.js" 21 | ], 22 | "scripts": { 23 | "deps": "depcheck", 24 | "test": "mocha --recursive test --timeout 20000 --color" 25 | }, 26 | "keywords": [ 27 | "quantum", 28 | "experience", 29 | "computing", 30 | "information", 31 | "algorithms", 32 | "random", 33 | "shor", 34 | "factor", 35 | "IBM" 36 | ], 37 | "bugs": { 38 | "url": "https://github.com/Qiskit/qiskit-js/issues" 39 | }, 40 | "dependencies": { 41 | "@qiskit/algo-anu": "^0.9.0", 42 | "@qiskit/algo-ibm": "^0.9.0", 43 | "@qiskit/algo-js": "^0.9.0", 44 | "@qiskit/utils": "^0.9.0" 45 | }, 46 | "engines": { 47 | "node": ">=10" 48 | }, 49 | "license": "Apache-2.0", 50 | "publishConfig": { 51 | "access": "public" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/qiskit-algo/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit-algo/test/functional.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const algo = require('..'); 15 | const { version } = require('../package'); 16 | 17 | // TODO: Use utils.difference instead. 18 | function multiIncludes(text, values) { 19 | return values.every(val => text.includes(val)); 20 | } 21 | 22 | describe('algo:api', () => { 23 | it('should include all documented items', () => 24 | assert.ok( 25 | multiIncludes(Object.keys(algo), [ 26 | 'version', 27 | 'random', 28 | 'factor', 29 | 'result', 30 | ]), 31 | )); 32 | }); 33 | 34 | describe('algo:version', () => 35 | it('should be correct', () => assert.equal(algo.version, version))); 36 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js cloud 2 | 3 | :atom_symbol: Quantum Information Science Kit library to use the [Quamtum Experience](https://quantumexperience.ng.bluemix.net). 4 | 5 | Please visit the [main repository](https://github.com/Qiskit/qiskit-js) of the project to know about the rest of the tools. 6 | 7 | ## Install 8 | 9 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 10 | 11 | ```sh 12 | npm i @qiskit/cloud 13 | ``` 14 | 15 | ## Use 16 | 17 | :pencil: You can visit more advanced examples in the [test folder](test). 18 | 19 | ```js 20 | 'use strict'; 21 | 22 | const Cloud = require('@qiskit/cloud'); 23 | 24 | const cloud = new Cloud(); 25 | 26 | console.log('Version'); 27 | console.log(cloud.version); 28 | 29 | cloud 30 | .login('YOUR_PERSONAL_TOKEN_HERE') 31 | .then(() => cloud.backends()) 32 | .then(backs => console.log(backs)); 33 | ``` 34 | 35 | ## API 36 | 37 | :eyes: Full specification. 38 | 39 | ### `Cloud(opts) -> cloud` 40 | 41 | The constructor accepts next options: 42 | 43 | - `token` (string) - Long term access token, see next point. 44 | - `cloud` (object) - New instance. 45 | 46 | ### `token` 47 | 48 | To force the long term access token, ie: to avoid the re-connection (login) in a worker. 49 | 50 | - `token` (string) - Token. 51 | 52 | ### `userId` 53 | 54 | To force user idendifier, ie: to avoid the re-connection (login) in a worker. 55 | 56 | - `userId` (string) - User identifier. 57 | 58 | ### `version` 59 | 60 | The actual version of the library. 61 | 62 | - `version` (string) - Version number. 63 | 64 | ### `async calibration(name) -> info` 65 | 66 | Get latest calibration stats for a backend. 67 | 68 | - `name` (string): Name of the backend to inspect. (default: `ibmqx4`) 69 | - `info` (object): Including next fields: 70 | - `lastUpdateDate` (string): Date of the last read. 71 | - `qubits` ([object]): Error in each qubit. 72 | - `multiQubitGates:` ([object]): Error in each gate. 73 | 74 | ### `async parameters(name) -> info` 75 | 76 | Get the latest parameters stats of the backend (more recent values that the ones returned by the `backendCalibration` method). 77 | 78 | - `name` (string): Name of the backend to inspect. (default: `ibmqx4`) 79 | - `info` (object): Including next fields: 80 | - `lastUpdateDate` (string): Date of the last read. 81 | - `fridgeParameters` (string): Information about the cooler. 82 | - `qubits` ([object]): Error in each qubit. 83 | 84 | ### `async queues(name) -> info` 85 | 86 | Get the status of a backend queue. 87 | 88 | - `name` (string): Name of the backend to inspect. (default: `ibmqx4`) 89 | - `info` (object): Including next fields: 90 | - `state` (boolean): If the queue is up or down. 91 | - `status` (string): Actual status of the devices, ie: "busy", "calibration", etc. 92 | - `lengthQueue` (number): Number of jobs in the queue. 93 | 94 | ### `async login(apiKey) -> info` 95 | 96 | To authenticate yourself. **This method should be called before the rest ones documented from this point**. 97 | 98 | - `apiKey` (string): QE API key, you can get it [here](https://quantumexperience.ng.bluemix.net/qx/account). 99 | - `info` (object): New token and its metadata: 100 | - `token` (string) - HTTP API authentication token. 101 | - `ttl` (number) - Time to live (in seconds). 102 | - `created` (string) - When the account was created. 103 | - `userId` (string). 104 | 105 | ### `async backend(name) -> info` 106 | 107 | Get the information of one the chips or simulator. 108 | 109 | - `name` (string): Name of the backend to inspect. (default: `ibmqx4`) 110 | - `info` ([object]): An object with next fields: 111 | - `name` (string) - Descriptive name of the device. 112 | - `status` (string) - If it´s "on" or "off". 113 | - `serialNumber` (string) 114 | - `description` (string) 115 | - `id` (string) 116 | - `topologyId` (string) 117 | - `simulator` (boolean): To mark the simulators. 118 | - `nQubits` (number): Number of Qubits the device has. 119 | - `couplingMap` ([[number]]): To show how the Qubits are connected in this device. 120 | 121 | ### `async backends(onlySims) -> infos` 122 | 123 | Get the information of all available chips and simulators. 124 | 125 | - `onlySims` (boolean): To get only info of the simulators. (default: false) 126 | - `infos` ([object]): A list of "info" objects (see last method). 127 | 128 | ### `async run(circuit, opts) -> info` 129 | 130 | Run a circuit in any of the avaliable backends. This method generates a new execution. 131 | 132 | - `circuit` (string): Circuit in OpenQASM. 133 | - `opts` (object): With next fields: 134 | - `backend` (string): Name of the backend to use. (default: simulator) 135 | - `shots` (number): Number of times to run the circuit. (default: 1) 136 | - `name` (string): Human friendly indetifier. 137 | - `seed` (string): Noise entropy, only allowed if using the simulator. 138 | - `maxCredits` (number): Max number of the credits to run this job. The task will be cancelled if it needs more. 139 | - `info` (object): Including next fields: 140 | - `id` (string): Unique identifier for the job created to run this circuit. 141 | - `status` (string): To know if the complete job has finished. Supported: "RUNNING", "ERROR_CREATING_JOB", "ERROR_RUNNING_JOB" or "COMPLETED". 142 | - `name` (string): Passed (or generated) human friendly indetifier. 143 | 144 | ### `async runBatch(circuits, opts) -> infos` 145 | 146 | Run a batch of circuits in any of the avaliable backends. This method can generate multiple executions. _Note: For convenience the descriptions not included are the same that for last method_ 147 | 148 | - `circuits` ([object]): Batch of circuits. Being "object": 149 | - `qasm` (string): Circuit in OpenQASM. The unique mandatory field. 150 | - `name` 151 | - `shots`: Only to overwrite this parameter defined in "opts" for this piece of code. 152 | - `seed`: Same than "shots". 153 | - `opts` 154 | - `backend` 155 | - `shots` 156 | - `seed` 157 | - `maxCredits` 158 | - `infos` ([object]): Including next fields: 159 | - `id` 160 | - `status` 161 | 162 | ### `async job(id) -> info` 163 | 164 | Get the info of a specific job. 165 | 166 | - `id` (string): Job identifier. 167 | - `info` (object): Including next fields: 168 | - `id` (string): Unique identifier for the job. 169 | - `backend` (string): Passed name of the backend to use. 170 | - `shots` (number): Passed number of times to run the circuit. 171 | - `creationDate` (string): When the job has entered into the system. 172 | - `usedCredits` (number): Number of consumed credits by the run. 173 | - `status` (string): To know if the complete job has finished. Supported: "RUNNING", "ERROR_CREATING_JOB", "ERROR_RUNNING_JOB" or "COMPLETED". 174 | - `maxCredits` (number): Max number passed of credits to use in this run before cancel it. 175 | - `circuits` ([object]): Batch of circuits. Being "object": 176 | - `qasm` (string): Passed circuit. 177 | - `name` (string): Passed (or generated) human friendly indetifier. 178 | - `shots` (number): If the parameter defined in "opts" was overwritten. 179 | - `seed` (string): If the parameter defined in "opts" was overwritten. 180 | - `execution` (object): Generated execution info, with these fields: 181 | - `id` (string): Identifier of the execution of this program. 182 | - `status` (string): Status of this execution of the program. Supported: "WORKING_IN_PROGRESS", "DONE", "ERROR", "NOT_APPROVED". 183 | - `result` (object): Present only when the job has finished. 184 | - `date` (string): When the job finished. 185 | - `data` (object): 186 | - `time` (number): How long it took, in seconds. 187 | - `count` (object): For each shot (value/key pair) the keys represent the final state of the qubits, and the value their probability. ie: { "00000": 189, "00001": 10 } 188 | 189 | ### `async jobs(limit, skip) -> infos` 190 | 191 | Get all your jobs. Ordered by creation date. 192 | 193 | - `limit` (number): Limit the number of instances to return. (default: 50) 194 | - `offset` (number): Skip the specified number of instances. Use it with "limit" to implement result pagination. 195 | - `infos` ([object]): The info for the required jobs. The object structure is like the one returned by the method `job`. 196 | 197 | ## `async credits() -> info` 198 | 199 | Get info about your account credits. 200 | 201 | - `info` (object): Including next fields: 202 | - `remaining` (number): Number of them the user still hasn't consumed. 203 | - `maxUserType` (number): Limit of max allowed for this type of user (out of promotion). 204 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/cfg.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaults": { 3 | "uri": "https://quantumexperience.ng.bluemix.net/api", 4 | "backend": { 5 | "run": "ibmq_qasm_simulator", 6 | "reads": "ibmqx4" 7 | }, 8 | "shots": 1 9 | }, 10 | "limits": { 11 | "shots": [0, 8192] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const { version } = require('./package'); 13 | const utils = require('./lib/utils'); 14 | const request = require('./lib/request'); 15 | const massageJob = require('./lib/massageJob'); 16 | const parser = require('./lib/parser'); 17 | const cfg = require('./cfg.json'); 18 | 19 | const dbg = utils.dbg(__filename); 20 | // To avoid requests that are going to fail to the API. 21 | const errLoginBefore = 'Please use "login" before'; 22 | 23 | class Cloud { 24 | constructor(opts = {}) { 25 | dbg('Starting', opts); 26 | 27 | this.version = version; 28 | this.uri = process.env.QE_URI || cfg.defaults.uri; 29 | 30 | // Both are also set after a successful login. 31 | if (opts.token) { 32 | this.token = opts.token; 33 | } 34 | if (opts.userId) { 35 | this.userId = opts.userId; 36 | } 37 | } 38 | 39 | // Token not needed. 40 | 41 | async calibration(name = cfg.defaults.backend.reads) { 42 | dbg('Getting the calibration info', { name }); 43 | 44 | const backName = parser.string(name); 45 | 46 | return request(`${this.uri}/Backends/${backName}/calibration`); 47 | } 48 | 49 | async parameters(name = cfg.defaults.backend.reads) { 50 | dbg('Getting the parameters info', { name }); 51 | 52 | const backName = parser.string(name); 53 | 54 | return request(`${this.uri}/Backends/${backName}/parameters`); 55 | } 56 | 57 | async queues(name = cfg.defaults.backend.reads) { 58 | dbg('Getting the status of the queue for', { name }); 59 | 60 | const backName = parser.string(name); 61 | 62 | // TODO: The API returns undefined if the backend doesn´t exists. 63 | // Using empty object to be consistent with parameters and calibration. 64 | // return request(`${this.uri}/Backends/${name}/queue/status`); 65 | const res = await request(`${this.uri}/Backends/${backName}/queue/status`); 66 | 67 | // The message is redundant with the status. 68 | if (res && res.message) { 69 | delete res.message; 70 | } 71 | 72 | return res || {}; 73 | } 74 | 75 | async login(tokenPersonal) { 76 | dbg('Getting a long term token'); 77 | 78 | const t = parser.string(tokenPersonal); 79 | 80 | const res = await request(`${this.uri}/users/loginWithToken`, { 81 | body: { apiToken: t }, 82 | }); 83 | 84 | this.token = res.id; 85 | this.userId = res.userId; 86 | 87 | dbg('Massaging the response', res); 88 | res.token = res.id; 89 | delete res.id; 90 | 91 | return res; 92 | } 93 | 94 | // Token needed. 95 | 96 | async credits() { 97 | dbg('Getting user credits info'); 98 | 99 | if (!this.token || !this.userId) { 100 | throw new Error(errLoginBefore); 101 | } 102 | 103 | const res = await request(`${this.uri}/users/${this.userId}`, { 104 | token: this.token, 105 | }); 106 | 107 | const creditInfo = res.credit; 108 | 109 | delete creditInfo.promotionalCodesUsed; 110 | delete creditInfo.lastRefill; 111 | delete creditInfo.promotional; 112 | 113 | return creditInfo; 114 | } 115 | 116 | async backend(name = cfg.defaults.backend.reads) { 117 | dbg('Getting info for a backend', { name }); 118 | 119 | if (!this.token) { 120 | throw new Error(errLoginBefore); 121 | } 122 | 123 | // TODO: The API returns undefined if the backend doesn´t exists. 124 | // Using empty object to be consistent with parameters and calibration. 125 | // return request(`${this.uri}/Backends/${parser.string(name)}`, { token: this.token }); 126 | const res = await request(`${this.uri}/Backends/${parser.string(name)}`, { 127 | token: this.token, 128 | }); 129 | 130 | return res || {}; 131 | } 132 | 133 | async backends(onlySims = false) { 134 | dbg('Getting the available backends', { onlySims }); 135 | 136 | if (!this.token) { 137 | throw new Error(errLoginBefore); 138 | } 139 | if (onlySims) { 140 | parser.bool(onlySims); 141 | } 142 | 143 | let res = await request(`${this.uri}/Backends`, { token: this.token }); 144 | // TODO: This endpoint doesn´t allow the filter param. 145 | res = utils.filter(res, el => el.status === 'on'); 146 | 147 | if (onlySims) { 148 | dbg('Returning only the simulators'); 149 | 150 | return utils.filter( 151 | res, 152 | el => el.status === 'on' && el.simulator === true, 153 | ); 154 | } 155 | 156 | return res; 157 | } 158 | 159 | async run(circuit, opts = {}) { 160 | dbg('Running experiment ...'); 161 | 162 | if (!this.token || !this.userId) { 163 | throw new Error(errLoginBefore); 164 | } 165 | 166 | dbg('Parsing mandatory params ...', { circuit }); 167 | let qasm = parser.string(circuit); 168 | // TODO: Dirty trick because the API adds this line again. 169 | qasm = qasm.replace('IBMQASM 2.0;', '').replace('OPENQASM 2.0;', ''); 170 | 171 | dbg('Parsing optional params ...', opts); 172 | 173 | let backend; 174 | if (opts.backend) { 175 | backend = parser.string(opts.backend); 176 | } else { 177 | backend = cfg.defaults.backend.run; 178 | } 179 | 180 | const reqOpts = { 181 | token: this.token, 182 | body: { 183 | qasms: [{ qasm }], 184 | backend: { name: backend }, 185 | }, 186 | }; 187 | if (opts.shots) { 188 | reqOpts.body.shots = parser.number( 189 | opts.shots, 190 | cfg.limits.shots[0], 191 | cfg.limits.shots[1], 192 | ); 193 | } else { 194 | reqOpts.body.shots = cfg.defaults.shots; 195 | } 196 | if (opts.seed) { 197 | reqOpts.body.seed = parser.string(opts.seed); 198 | } 199 | if (opts.maxCredits) { 200 | reqOpts.body.maxCredits = parser.number(opts.maxCredits, 0); 201 | } 202 | if (opts.name) { 203 | reqOpts.body.qasms[0].name = parser.string(opts.name); 204 | } 205 | 206 | dbg('Making the request ...', reqOpts); 207 | const res = await request(`${this.uri}/Jobs`, reqOpts); 208 | 209 | dbg('Massaging the result ...', res); 210 | // TODO: Add info about the status of the job in the queue. 211 | const resMassaged = { id: res.id, status: res.status }; 212 | // To avoid a break if any API error or something. 213 | if (res.qasms && res.qasms[0] && res.qasms[0]) { 214 | resMassaged.name = res.qasms[0].name; 215 | } 216 | 217 | dbg('Massaged ...', resMassaged); 218 | return resMassaged; 219 | } 220 | 221 | async runBatch(circuits, opts = {}) { 222 | dbg('Running batch of experiment ...', { circuits, opts }); 223 | 224 | if (!this.token || !this.userId) { 225 | throw new Error(errLoginBefore); 226 | } 227 | 228 | dbg('Parsing mandatory params ...', { circuits }); 229 | 230 | let qasms; 231 | if (!circuits || !utils.isArray(circuits) || utils.isEmpty(circuits)) { 232 | throw new Error(`Array format expected, found: ${circuits}`); 233 | } else { 234 | qasms = utils.map(circuits, el => { 235 | // TODO: Dirty trick because the API adds this line again. 236 | if (!utils.isObject(el)) { 237 | throw new Error(`Object format expected: ${el}`); 238 | } 239 | const parsed = { 240 | qasm: parser 241 | .string(el.qasm) 242 | .replace('IBMQASM 2.0;', '') 243 | .replace('OPENQASM 2.0;', ''), 244 | }; 245 | if (el.shots) { 246 | parsed.shots = parser.number( 247 | el.shots, 248 | cfg.limits.shots[0], 249 | cfg.limits.shots[1], 250 | ); 251 | } 252 | if (el.seed) { 253 | parsed.seed = parser.string(el.seed); 254 | } 255 | if (el.name) { 256 | parsed.name = parser.string(el.name); 257 | } 258 | 259 | return parsed; 260 | }); 261 | } 262 | 263 | dbg('Parsing optional params ...', opts); 264 | 265 | let backend; 266 | if (opts.backend) { 267 | backend = parser.string(opts.backend); 268 | } else { 269 | backend = cfg.defaults.backend.run; 270 | } 271 | 272 | let shots; 273 | if (opts.shots) { 274 | shots = parser.number( 275 | opts.shots, 276 | cfg.limits.shots[0], 277 | cfg.limits.shots[1], 278 | ); 279 | } else { 280 | // eslint-disable-next-line prefer-destructuring 281 | shots = cfg.defaults.shots; 282 | } 283 | 284 | const reqOpts = { 285 | token: this.token, 286 | body: { 287 | qasms, 288 | shots, 289 | backend: { name: backend }, 290 | }, 291 | }; 292 | 293 | if (opts.seed) { 294 | reqOpts.body.seed = parser.string(opts.seed); 295 | } 296 | 297 | if (opts.maxCredits) { 298 | reqOpts.body.maxCredits = parser.number(opts.maxCredits, 0); 299 | } 300 | 301 | dbg('Making the request ...', reqOpts); 302 | const res = await request(`${this.uri}/Jobs`, reqOpts); 303 | 304 | dbg('Massaging the result ...', res); 305 | 306 | return { 307 | id: res.id, 308 | status: res.status, 309 | }; 310 | } 311 | 312 | async job(id) { 313 | dbg('Getting info for a job', { id }); 314 | 315 | if (!this.token) { 316 | throw new Error(errLoginBefore); 317 | } 318 | 319 | const res = await request(`${this.uri}/Jobs/${parser.string(id)}`, { 320 | token: this.token, 321 | }); 322 | 323 | return massageJob(res); 324 | } 325 | 326 | async jobs(limit = 50, skip) { 327 | dbg('Getting the jobs'); 328 | 329 | if (!this.token) { 330 | throw new Error(errLoginBefore); 331 | } 332 | 333 | const reqOpts = { 334 | token: this.token, 335 | filter: { order: 'creationDate DESC' }, 336 | }; 337 | if (limit) { 338 | reqOpts.filter.limit = parser.number(limit, 0); 339 | } 340 | if (skip) { 341 | reqOpts.filter.skip = parser.number(skip, 0); 342 | } 343 | 344 | const res = await request(`${this.uri}/Jobs`, reqOpts); 345 | 346 | return res.map(massageJob); 347 | } 348 | } 349 | 350 | module.exports = Cloud; 351 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/lib/massageJob.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('./utils'); 13 | 14 | const dbg = utils.dbg(__filename); 15 | 16 | module.exports = resJob => { 17 | dbg('Massaging the result ...', resJob); 18 | 19 | const result = { 20 | id: resJob.id, 21 | backend: resJob.backend.name, 22 | shots: resJob.shots, 23 | creationDate: resJob.creationDate, 24 | usedCredits: resJob.usedCredits, 25 | status: resJob.status, 26 | circuits: utils.map(resJob.qasms, el => { 27 | const massaged = { 28 | qasm: el.qasm, 29 | execution: { 30 | id: el.executionId, 31 | status: el.status, 32 | }, 33 | }; 34 | 35 | if (el.name) { 36 | massaged.name = el.name; 37 | } 38 | if (el.shots) { 39 | massaged.shots = el.shots; 40 | } 41 | if (el.seed) { 42 | massaged.seed = el.seed; 43 | } 44 | if (el.result) { 45 | massaged.result = el.result; 46 | } 47 | 48 | return massaged; 49 | }), 50 | }; 51 | 52 | if (resJob.maxCredits) { 53 | result.maxCredits = resJob.maxCredits; 54 | } 55 | if (resJob.seed) { 56 | result.seed = resJob.seed; 57 | } 58 | 59 | dbg('Massaged ...', result); 60 | return result; 61 | }; 62 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/lib/parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | module.exports.number = (num, min, max) => { 13 | if (!num || typeof num !== 'number') { 14 | throw new Error(`Number format expected, found: ${num}`); 15 | } 16 | 17 | if (((min || min === 0) && num < min) || (max && num > max)) { 18 | throw new Error(`Out of range, found: ${num}`); 19 | } 20 | 21 | return num; 22 | }; 23 | 24 | module.exports.string = str => { 25 | if (!str || typeof str !== 'string') { 26 | throw new Error(`String format expected, found: ${str}`); 27 | } 28 | 29 | return str; 30 | }; 31 | 32 | module.exports.bool = value => { 33 | if (!value || typeof value !== 'boolean') { 34 | throw new Error(`Boolean format expected, found: ${value}`); 35 | } 36 | 37 | return value; 38 | }; 39 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/lib/request.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const rp = require('request-promise-native'); 13 | 14 | async function request(uri, opts = {}) { 15 | if (!uri) { 16 | throw new Error('Required parameter: uri'); 17 | } 18 | 19 | const cfg = { 20 | uri, 21 | // Extra querystring params comes here (all but token). 22 | qs: opts.qs || {}, 23 | // TODO: Monitor this in the backend. 24 | headers: { 'User-Agent': 'qiskit.js' }, 25 | json: true, 26 | }; 27 | if (opts.body) { 28 | cfg.method = 'POST'; 29 | cfg.body = opts.body; 30 | } 31 | // -> uri + '?access_token=xxxxx%20xxxxx' 32 | if (opts.token) { 33 | cfg.qs.access_token = opts.token; 34 | } 35 | if (opts.filter) { 36 | cfg.qs.filter = JSON.stringify(opts.filter); 37 | } 38 | 39 | // Massaging the error, to avoid return specific HTTP stuff. 40 | let res; 41 | try { 42 | res = await rp(cfg); 43 | } catch (err) { 44 | if (err.error && err.error.error && err.error.error.code) { 45 | throw new Error(err.error.error.code); 46 | } else { 47 | // If we can´t find a custom error the original (HTTP) is returned. 48 | throw err.message; 49 | } 50 | } 51 | 52 | return res; 53 | } 54 | 55 | module.exports = request; 56 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const pkgName = require('../package.json').name; 15 | 16 | utils.dbg = fullPath => utils.debug(`${pkgName}:${utils.pathToTag(fullPath)}`); 17 | 18 | module.exports = utils; 19 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/cloud", 3 | "version": "0.9.0", 4 | "description": "Quantum Information Science kit to connect to the Quantum Experience", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://github.com/Qiskit/qiskit-js", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "files": [ 18 | "lib", 19 | "cfg.json", 20 | "index.js" 21 | ], 22 | "scripts": { 23 | "deps": "depcheck", 24 | "test": "mocha --recursive --timeout 20000 test --color" 25 | }, 26 | "keywords": [ 27 | "quantum", 28 | "experience", 29 | "computing", 30 | "information", 31 | "qasm", 32 | "openqasm", 33 | "qiskit", 34 | "IBM" 35 | ], 36 | "bugs": { 37 | "url": "https://github.com/Qiskit/qiskit-js/issues" 38 | }, 39 | "dependencies": { 40 | "@qiskit/utils": "^0.9.0", 41 | "request": "^2.88.0", 42 | "request-promise-native": "^1.0.7" 43 | }, 44 | "engines": { 45 | "node": ">=10" 46 | }, 47 | "license": "Apache-2.0", 48 | "publishConfig": { 49 | "access": "public" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/errorRe.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | module.exports = { 13 | formatUri: /URI format expected/, 14 | formatStr: /String format expected/, 15 | formatBool: /Boolean format expected/, 16 | formatNumber: /Number format expected/, 17 | formatArr: /Array format expected/, 18 | formatObj: /Object format expected/, 19 | loginBefore: /Please use "login" before/, 20 | outRange: /Out of range/, 21 | badQasm: /QASM_NOT_VALID/, 22 | }; 23 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/functional/0-new.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const Cloud = require('../..'); 15 | const pkgInfo = require('../../package'); 16 | 17 | const { version } = pkgInfo; 18 | let cloud; 19 | 20 | describe('cloud:new', () => { 21 | it('should work without options', () => 22 | assert.equal(new Cloud().version, version)); 23 | 24 | it('should work with empty options', () => { 25 | cloud = new Cloud({}); 26 | assert.ok(true); 27 | }); 28 | }); 29 | 30 | describe('cloud:version', () => 31 | it('should return the package version', () => 32 | assert.equal(cloud.version, pkgInfo.version))); 33 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/functional/1-login.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | const utilsTest = require('../../../../utils-test'); 14 | 15 | const Cloud = require('../..'); 16 | const expErrRegex = require('../errorRe'); 17 | 18 | const cloud = new Cloud(); 19 | 20 | global.qiskit = {}; 21 | 22 | describe('cloud:login', () => { 23 | it('should fail if "token" parameter no present', async () => 24 | // TODO: Emit proper error. 25 | utilsTest.throwsAsync(() => cloud.login(), expErrRegex.formatStr)); 26 | 27 | it('should fail if bad format in the "token" parameter', async () => 28 | utilsTest.throwsAsync(() => cloud.login(1), expErrRegex.formatStr)); 29 | 30 | // TODO: Mocha automagically added stuff to this.* not supported with arrow functions. 31 | // https://github.com/mochajs/mocha/issues/1856 32 | // it('should return the user info with a valid login', async () => { 33 | it('should return the user info with a valid login', async function t() { 34 | if (!process.env.QX_KEY) { 35 | // Dirty trick to allow the tests which don´t need the API to run. 36 | cloud.token = 'notvalid'; 37 | cloud.userId = 'notvalid'; 38 | 39 | /* eslint-disable no-console */ 40 | console.log( 41 | '\n\n\n\t-------------------------------------------------------------', 42 | ); 43 | console.log('\tWARNING'); 44 | console.log('\tQX_KEY env var not found, so skipping integration tests.'); 45 | console.log( 46 | '\t-------------------------------------------------------------\n\n\n', 47 | ); 48 | 49 | /* eslint-enable no-console */ 50 | this.skip(); 51 | } 52 | 53 | // To reuse in the rest of test files of this folder and avoid multiple re-login. 54 | // Also to detect if we want to run integration tests without exposing sensitive data. 55 | global.qiskit.cloud = cloud; 56 | const res = await cloud.login(process.env.QX_KEY); 57 | 58 | assert.deepEqual(Object.keys(res), ['ttl', 'created', 'userId', 'token']); 59 | assert.equal(typeof res.ttl, 'number'); 60 | assert.ok(typeof res.created === 'string'); 61 | assert.ok(typeof res.userId === 'string'); 62 | assert.ok(typeof res.token === 'string'); 63 | }); 64 | 65 | it('should set the token properly', async () => { 66 | assert.equal(typeof cloud.token, 'string'); 67 | assert.notEqual(cloud.token.length, 0); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/functional/2-backend.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const utilsTest = require('../../../../utils-test'); 15 | const expErrRegex = require('../errorRe'); 16 | const Cloud = require('../..'); 17 | 18 | const cloudNoToken = new Cloud(); 19 | // To avoid no token related errors. 20 | const cloudFaked = new Cloud(); 21 | cloudFaked.token = 'a'; 22 | cloudFaked.userId = 'a'; 23 | 24 | describe('cloud:calibration', () => { 25 | it('should fail if bad format in the "name" parameter', async () => 26 | utilsTest.throwsAsync( 27 | () => cloudNoToken.calibration(1), 28 | expErrRegex.formatStr, 29 | )); 30 | 31 | it( 32 | 'should return the calibration info for the' + 33 | 'default backend if no parameter', 34 | async () => { 35 | const res = await cloudNoToken.calibration(); 36 | 37 | assert.deepEqual(Object.keys(res), [ 38 | 'lastUpdateDate', 39 | 'qubits', 40 | 'multiQubitGates', 41 | ]); 42 | assert.equal(typeof res.lastUpdateDate, 'string'); 43 | assert.equal(typeof res.qubits, 'object'); 44 | assert.equal(typeof res.multiQubitGates, 'object'); 45 | }, 46 | ); 47 | 48 | // We use a non existent one because we can´t know in advance the returned values here. 49 | // TODO: The API should return an error in this case. 50 | it('should return the calibration info for the selected backend', async () => 51 | assert.deepEqual( 52 | Object.keys(await cloudNoToken.calibration('nonexistent')), 53 | [], 54 | )); 55 | }); 56 | 57 | describe('cloud:parameters', () => { 58 | it('should fail if bad format in the "name" parameter', async () => 59 | utilsTest.throwsAsync( 60 | () => cloudNoToken.parameters(1), 61 | expErrRegex.formatStr, 62 | )); 63 | 64 | it( 65 | 'should return the parameters info for the' + 66 | 'default backend if no parameter', 67 | async () => { 68 | const res = await cloudNoToken.parameters(); 69 | 70 | assert.deepEqual(Object.keys(res), [ 71 | 'lastUpdateDate', 72 | 'fridgeParameters', 73 | 'qubits', 74 | ]); 75 | assert.equal(typeof res.lastUpdateDate, 'string'); 76 | assert.equal(typeof res.fridgeParameters, 'object'); 77 | assert.equal(typeof res.qubits, 'object'); 78 | }, 79 | ); 80 | 81 | // We use a non existent one because we can´t know in advance the returned values here. 82 | // TODO: The API should return an error in this case. 83 | it('should return the parameters info for the selected backend', async () => 84 | assert.deepEqual( 85 | Object.keys(await cloudNoToken.parameters('nonexistent')), 86 | [], 87 | )); 88 | }); 89 | 90 | describe('cloud:queues', () => { 91 | it('should fail if bad format in the "name" parameter', async () => 92 | utilsTest.throwsAsync(() => cloudNoToken.queues(1), expErrRegex.formatStr)); 93 | 94 | it('should return the status of the queue of the default backend if no parameter', async () => { 95 | const res = await cloudNoToken.queues(); 96 | 97 | assert.deepEqual(Object.keys(res), [ 98 | 'state', 99 | 'status', 100 | 'lengthQueue', 101 | 'backend_version', 102 | ]); 103 | assert.equal(typeof res.state, 'boolean'); 104 | assert.equal(typeof res.status, 'string'); 105 | assert.equal(typeof res.lengthQueue, 'number'); 106 | }); 107 | 108 | // We use a non existent one because we can´t know in advance the returned values here. 109 | // TODO: The API should return an error in this case. 110 | it('should return the queue info for the selected backend', async () => 111 | assert.deepEqual(await cloudNoToken.queues('nonexistent'), {})); 112 | }); 113 | 114 | const expectedKeys = [ 115 | 'name', 116 | 'version', 117 | 'status', 118 | 'serialNumber', 119 | 'description', 120 | 'attributes', 121 | 'gateSet', 122 | 'basisGates', 123 | 'onlineDate', 124 | 'chipName', 125 | 'deleted', 126 | 'specificConfiguration', 127 | 'id', 128 | 'topologyId', 129 | 'qconsole', 130 | 'url', 131 | 'internalId', 132 | 'simulator', 133 | 'allowQObject', 134 | 'nQubits', 135 | 'couplingMap', 136 | ]; 137 | 138 | describe('cloud:backend', () => { 139 | it('should fail if no logged', async () => 140 | utilsTest.throwsAsync( 141 | () => cloudNoToken.backend(), 142 | expErrRegex.loginBefore, 143 | )); 144 | 145 | it('should fail if bad format in the "name" parameter', async () => 146 | utilsTest.throwsAsync(() => cloudFaked.backend(1), expErrRegex.formatStr)); 147 | 148 | it('should return a backend with the default "name" parameter', async function t() { 149 | if (!global.qiskit || !global.qiskit.cloud) { 150 | this.skip(); 151 | } 152 | 153 | const res = await global.qiskit.cloud.backend(); 154 | 155 | assert.deepEqual(Object.keys(res), expectedKeys); 156 | assert.equal(res.name, 'ibmqx4'); 157 | }); 158 | 159 | it('should return a backend info for a valid "name" parameter', async function t() { 160 | if (!global.qiskit || !global.qiskit.cloud) { 161 | this.skip(); 162 | } 163 | 164 | const name = 'ibmqx5'; 165 | const res = await global.qiskit.cloud.backend(name); 166 | 167 | // TODO: Cloning to fix API inconsistency. 168 | const expectedFix = expectedKeys.slice(0); 169 | expectedFix.splice(5, 1); 170 | expectedFix.splice(10, 1); 171 | 172 | assert.deepEqual(Object.keys(res), expectedFix); 173 | assert.equal(res.name, name); 174 | }); 175 | 176 | // We use a non existent one because we can´t know in advance the returned values here. 177 | // TODO: The API should return an error in this case. 178 | it('should return the queue info for the selected backend', async function t() { 179 | if (!global.qiskit || !global.qiskit.cloud) { 180 | this.skip(); 181 | } 182 | 183 | assert.deepEqual(await global.qiskit.cloud.backend('nonexistent'), {}); 184 | }); 185 | }); 186 | 187 | describe('cloud:backends', () => { 188 | it('should fail if no logged', async () => 189 | utilsTest.throwsAsync( 190 | () => cloudNoToken.backends(), 191 | expErrRegex.loginBefore, 192 | )); 193 | 194 | it('should return the online backends info', async function t() { 195 | if (!global.qiskit || !global.qiskit.cloud) { 196 | this.skip(); 197 | } 198 | 199 | const res = await global.qiskit.cloud.backends(); 200 | 201 | assert.equal(res.length, 5); 202 | assert.deepEqual(Object.keys(res[0]), expectedKeys); 203 | }); 204 | 205 | it('should fail if bad format in the "onlySims" parameter', async () => 206 | utilsTest.throwsAsync( 207 | () => cloudFaked.backends(1), 208 | expErrRegex.formatBool, 209 | )); 210 | 211 | it('should allow to ask only for simulators info', async function t() { 212 | if (!global.qiskit || !global.qiskit.cloud) { 213 | this.skip(); 214 | } 215 | 216 | const res = await global.qiskit.cloud.backends(true); 217 | 218 | assert.equal(res.length, 1); 219 | assert.equal(Object.keys(res[0]).length, 13); 220 | assert.equal(res[0].name, 'ibmq_qasm_simulator'); 221 | assert.equal(res[0].status, 'on'); 222 | assert.equal(res[0].description, 'online qasm simulator'); 223 | assert.equal(res[0].basisGates, 'u1,u2,u3,cx,id'); 224 | assert.equal(res[0].simulator, true); 225 | assert(typeof res[0].onlineDate === 'string'); 226 | assert.equal(res[0].allowQObject, true); 227 | assert.equal(res[0].nQubits, 32); 228 | assert.equal(res[0].couplingMap, 'all-to-all'); 229 | }); 230 | }); 231 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/functional/3-credits.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | const utilsTest = require('../../../../utils-test'); 14 | 15 | const Cloud = require('../..'); 16 | const expErrRegex = require('../errorRe'); 17 | 18 | describe('cloud:credits', () => { 19 | it('should fail if no logged', async () => 20 | utilsTest.throwsAsync( 21 | () => new Cloud().credits(), 22 | expErrRegex.loginBefore, 23 | )); 24 | 25 | it('should return the info of my credits in the platform', async function t() { 26 | if (!global.qiskit || !global.qiskit.cloud) { 27 | this.skip(); 28 | } 29 | 30 | const res = await global.qiskit.cloud.credits(); 31 | 32 | assert.deepEqual(Object.keys(res).sort(), ['maxUserType', 'remaining']); 33 | assert.equal(typeof res.remaining, 'number'); 34 | assert.equal(typeof res.maxUserType, 'number'); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/functional/4-run.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | const utilsTest = require('../../../../utils-test'); 14 | 15 | const Cloud = require('../..'); 16 | const expErrRegex = require('../errorRe'); 17 | 18 | const cloudFaked = new Cloud(); 19 | cloudFaked.token = 'a'; 20 | cloudFaked.userId = 'a'; 21 | const circuit = 22 | 'OPENQASM 2.0;' + 23 | 'include "qelib1.inc";' + 24 | 'qreg q[1];' + 25 | 'creg c[1];' + 26 | 'measure q -> c;'; 27 | 28 | describe('cloud:run', () => { 29 | it('should fail if no logged', async () => 30 | utilsTest.throwsAsync(() => new Cloud().run('a'), expErrRegex.loginBefore)); 31 | 32 | // TODO: Emit proper error. 33 | it('should fail if "circuit" parameter no present', async () => 34 | utilsTest.throwsAsync(() => cloudFaked.run(), expErrRegex.formatStr)); 35 | 36 | it('should fail if bad format in the "circuit" parameter', async () => 37 | utilsTest.throwsAsync(() => cloudFaked.run(1), expErrRegex.formatStr)); 38 | 39 | it('should fail if bad format in the "backend" option', async () => 40 | utilsTest.throwsAsync( 41 | () => cloudFaked.run('a', { backend: 1 }), 42 | expErrRegex.formatStr, 43 | )); 44 | 45 | it('should fail if bad format in the "name" option', async () => 46 | utilsTest.throwsAsync( 47 | () => cloudFaked.run('a', { name: 1 }), 48 | expErrRegex.formatStr, 49 | )); 50 | 51 | it('should fail if bad format in the "shots" option', async () => 52 | utilsTest.throwsAsync( 53 | () => cloudFaked.run('a', { shots: 'a' }), 54 | expErrRegex.formatNumber, 55 | )); 56 | 57 | it('should fail if under min. in the "shots" option', async () => 58 | utilsTest.throwsAsync( 59 | () => cloudFaked.run('a', { shots: -1 }), 60 | expErrRegex.outRange, 61 | )); 62 | 63 | it('should fail if over max. in the "shots" option', async () => 64 | utilsTest.throwsAsync( 65 | () => cloudFaked.run('a', { shots: 8193 }), 66 | expErrRegex.outRange, 67 | )); 68 | 69 | it('should fail if bad format in the "seed" option', async () => 70 | utilsTest.throwsAsync( 71 | () => cloudFaked.run('a', { seed: 1 }), 72 | expErrRegex.formatStr, 73 | )); 74 | 75 | it('should fail if bad format in the "maxCredits" option', async () => 76 | utilsTest.throwsAsync( 77 | () => cloudFaked.run('a', { maxCredits: 'a' }), 78 | expErrRegex.formatNumber, 79 | )); 80 | 81 | it('should fail if under min. in the "maxCredits" option', async () => 82 | utilsTest.throwsAsync( 83 | () => cloudFaked.run('a', { maxCredits: -1 }), 84 | expErrRegex.outRange, 85 | )); 86 | 87 | it('should fail if a controlled API error', async function t() { 88 | if (!global.qiskit || !global.qiskit.cloud) { 89 | this.skip(); 90 | } 91 | 92 | utilsTest.throwsAsync( 93 | () => global.qiskit.cloud.run('a'), 94 | expErrRegex.badQasm, 95 | ); 96 | }); 97 | 98 | it('should return the run info for a valid circuit', async function t() { 99 | if (!global.qiskit || !global.qiskit.cloud) { 100 | this.skip(); 101 | } 102 | 103 | const res = await global.qiskit.cloud.run(circuit); 104 | 105 | // To use in the Job endpoint related tests. 106 | global.qiskit.jobId = res.id; 107 | 108 | assert.deepEqual(Object.keys(res), ['id', 'status', 'name']); 109 | assert.equal(typeof res.id, 'string'); 110 | assert.equal(typeof res.status, 'string'); 111 | }); 112 | }); 113 | 114 | describe('cloud:runBatch', () => { 115 | it('should fail if no logged', async () => 116 | utilsTest.throwsAsync( 117 | () => new Cloud().runBatch('a'), 118 | expErrRegex.loginBefore, 119 | )); 120 | 121 | it('should fail if "circuits" parameter no present', async () => 122 | // TODO: Emit proper error. 123 | utilsTest.throwsAsync(() => cloudFaked.runBatch(), expErrRegex.formatArr)); 124 | 125 | it('should fail if bad format in the "circuits" parameter', async () => 126 | utilsTest.throwsAsync(() => cloudFaked.runBatch(1), expErrRegex.formatArr)); 127 | 128 | it('should fail if empty "circuits" parameter', async () => 129 | utilsTest.throwsAsync( 130 | () => cloudFaked.runBatch([]), 131 | expErrRegex.formatArr, 132 | )); 133 | 134 | it('should fail if bad format on the elements of "circuits"', async () => 135 | utilsTest.throwsAsync( 136 | () => cloudFaked.runBatch([1]), 137 | expErrRegex.formatObj, 138 | )); 139 | 140 | it('should fail if "qasm" subfield not present', async () => 141 | utilsTest.throwsAsync( 142 | () => cloudFaked.runBatch([{}]), 143 | expErrRegex.formatStr, 144 | )); 145 | 146 | it('should fail if bad format in the "qasm" subfield', async () => 147 | utilsTest.throwsAsync( 148 | () => cloudFaked.runBatch([{ qasm: 1 }]), 149 | expErrRegex.formatStr, 150 | )); 151 | 152 | it('should fail if bad format in the "shots" subfield', async () => 153 | utilsTest.throwsAsync( 154 | () => cloudFaked.runBatch([{ qasm: 'a', shots: 'a' }]), 155 | expErrRegex.formatNumber, 156 | )); 157 | 158 | it('should fail if under min. in the "shots" subfield', async () => 159 | utilsTest.throwsAsync( 160 | () => cloudFaked.runBatch([{ qasm: 'a', shots: -1 }]), 161 | expErrRegex.outRange, 162 | )); 163 | 164 | it('should fail if over max. in the "shots" subfield', async () => 165 | utilsTest.throwsAsync( 166 | () => cloudFaked.runBatch([{ qasm: 'a', shots: 8193 }]), 167 | expErrRegex.outRange, 168 | )); 169 | 170 | it('should fail if bad format in the "seed" subfield', async () => 171 | utilsTest.throwsAsync( 172 | () => cloudFaked.runBatch([{ qasm: 'a', seed: 1 }]), 173 | expErrRegex.formatStr, 174 | )); 175 | 176 | it('should fail if bad format in the "name" subfield', async () => 177 | utilsTest.throwsAsync( 178 | () => cloudFaked.runBatch([{ qasm: 'a', name: 1 }]), 179 | expErrRegex.formatStr, 180 | )); 181 | 182 | it('should fail if bad format in the "backend" option', async () => 183 | utilsTest.throwsAsync(() => 184 | cloudFaked.runBatch( 185 | ([{ qasm: 'a' }], { backend: 1 }), 186 | expErrRegex.formatStr, 187 | ), 188 | )); 189 | 190 | it('should fail if bad format in the "name" option', async () => 191 | utilsTest.throwsAsync(() => 192 | cloudFaked.runBatch( 193 | ([{ qasm: 'a' }], { name: 1 }), 194 | expErrRegex.formatStr, 195 | ), 196 | )); 197 | 198 | it('should fail if bad format in the "shots" option', async () => 199 | utilsTest.throwsAsync(() => 200 | cloudFaked.runBatch( 201 | ([{ qasm: 'a' }], { shots: 'a' }), 202 | expErrRegex.formatNumber, 203 | ), 204 | )); 205 | 206 | it('should fail if under min. in the "shots" option', async () => 207 | utilsTest.throwsAsync(() => 208 | cloudFaked.runBatch( 209 | ([{ qasm: 'a' }], { shots: -1 }), 210 | expErrRegex.outRange, 211 | ), 212 | )); 213 | 214 | it('should fail if over max. in the "shots" option', async () => 215 | utilsTest.throwsAsync(() => 216 | cloudFaked.runBatch( 217 | ([{ qasm: 'a' }], { shots: 8193 }), 218 | expErrRegex.outRange, 219 | ), 220 | )); 221 | 222 | it('should fail if bad format in the "seed" option', async () => 223 | utilsTest.throwsAsync(() => 224 | cloudFaked.runBatch( 225 | ([{ qasm: 'a' }], { seed: 1 }), 226 | expErrRegex.formatStr, 227 | ), 228 | )); 229 | 230 | it('should fail if bad format in the "maxCredits" option', async () => 231 | utilsTest.throwsAsync(() => 232 | cloudFaked.runBatch( 233 | ([{ qasm: 'a' }], { maxCredits: 'a' }), 234 | expErrRegex.formatNumber, 235 | ), 236 | )); 237 | 238 | it('should fail if under min. in the "maxCredits" option', async () => 239 | utilsTest.throwsAsync(() => 240 | cloudFaked.runBatch( 241 | ([{ qasm: 'a' }], { maxCredits: -1 }), 242 | expErrRegex.formatStr, 243 | ), 244 | )); 245 | 246 | it('should fail if a controlled API error', async function t() { 247 | if (!global.qiskit || !global.qiskit.cloud) { 248 | this.skip(); 249 | } 250 | 251 | utilsTest.throwsAsync(() => 252 | global.qiskit.cloud.runBatch([{ qasm: 'a' }], expErrRegex.badQasm), 253 | ); 254 | }); 255 | 256 | it('should return the run info for a valid batch of circuits', async function t() { 257 | if (!global.qiskit || !global.qiskit.cloud) { 258 | this.skip(); 259 | } 260 | 261 | const res = await global.qiskit.cloud.runBatch([{ qasm: circuit }]); 262 | 263 | assert.deepEqual(Object.keys(res), ['id', 'status']); 264 | assert.equal(typeof res.id, 'string'); 265 | assert.equal(res.status, 'RUNNING'); 266 | }); 267 | }); 268 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/functional/5-jobs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const utils = require('../../lib/utils'); 15 | const utilsTest = require('../../../../utils-test'); 16 | 17 | const Cloud = require('../..'); 18 | const expErrRegex = require('../errorRe'); 19 | 20 | const cloudFaked = new Cloud(); 21 | cloudFaked.token = 'a'; 22 | cloudFaked.userId = 'a'; 23 | 24 | function checkJob(res) { 25 | assert.deepEqual(Object.keys(res), [ 26 | 'id', 27 | 'backend', 28 | 'shots', 29 | 'creationDate', 30 | 'usedCredits', 31 | 'status', 32 | 'circuits', 33 | ]); 34 | assert.equal(typeof res.id, 'string'); 35 | assert.equal(typeof res.backend, 'string'); 36 | assert.equal(typeof res.shots, 'number'); 37 | assert.equal(typeof res.creationDate, 'string'); 38 | assert.equal(typeof res.usedCredits, 'number'); 39 | assert.equal(typeof res.status, 'string'); 40 | assert.equal(res.circuits.length, 1); 41 | // "result" can be present or not. 42 | assert.equal( 43 | utils.difference(['qasm', 'execution'], Object.keys(res.circuits[0])), 44 | 0, 45 | ); 46 | assert.equal(typeof res.circuits[0].qasm, 'string'); 47 | 48 | // If job has errored this is not present (execution) or Maybe it has still not finished (result). 49 | if (!res.circuits[0].execution.result) { 50 | return; 51 | } 52 | 53 | assert.deepEqual(Object.keys(res.circuits[0].execution), ['id', 'status']); 54 | assert.equal(typeof res.circuits[0].execution.id, 'string'); 55 | assert.equal(typeof res.circuits[0].execution.status, 'string'); 56 | 57 | assert.deepEqual(Object.keys(res.circuits[0].execution.result), [ 58 | 'date', 59 | 'data', 60 | ]); 61 | assert.equal(typeof res.circuits[0].execution.result.date, 'string'); 62 | assert.deepEqual(Object.keys(res.circuits[0].execution.result.data), [ 63 | 'time', 64 | 'count', 65 | ]); 66 | assert.equal(typeof res.circuits[0].execution.result.data.time, 'string'); 67 | assert.equal(typeof res.circuits[0].execution.result.data.count, 'object'); 68 | } 69 | 70 | describe('cloud:job', () => { 71 | it('should fail if no logged', async () => 72 | utilsTest.throwsAsync(() => new Cloud().job(), expErrRegex.loginBefore)); 73 | 74 | it('should fail if "id" parameter no present', async () => 75 | utilsTest.throwsAsync(() => cloudFaked.job(), expErrRegex.formatStr)); 76 | 77 | it('should fail if bad format in the "id" parameter', async () => 78 | utilsTest.throwsAsync(() => cloudFaked.job(1), expErrRegex.formatStr)); 79 | 80 | it('should return the info for a valid job', async function t() { 81 | if (!global.qiskit || !global.qiskit.cloud) { 82 | this.skip(); 83 | } 84 | 85 | const res = await global.qiskit.cloud.job(global.qiskit.jobId); 86 | checkJob(res); 87 | }); 88 | }); 89 | 90 | let oldId; 91 | describe('cloud:jobs', () => { 92 | it('should fail if no logged', async () => 93 | utilsTest.throwsAsync(() => new Cloud().jobs(), expErrRegex.loginBefore)); 94 | 95 | it('should fail if bad format in the "limit" option', async () => 96 | utilsTest.throwsAsync( 97 | () => cloudFaked.jobs('a'), 98 | expErrRegex.formatNumber, 99 | )); 100 | 101 | it('should fail if under min. in the "limit" option', async () => 102 | utilsTest.throwsAsync(() => cloudFaked.jobs(-1), expErrRegex.outRange)); 103 | 104 | it('should fail if bad format in the "offset" option', async () => 105 | utilsTest.throwsAsync( 106 | () => cloudFaked.jobs(1, 'a'), 107 | expErrRegex.formatNumber, 108 | )); 109 | 110 | it('should fail if under min. in the "offset" option', async () => 111 | utilsTest.throwsAsync(() => cloudFaked.jobs(1, -1), expErrRegex.outRange)); 112 | 113 | it('should return all jobs info without parameters', async function t() { 114 | if (!global.qiskit || !global.qiskit.cloud) { 115 | this.skip(); 116 | } 117 | 118 | const res = await global.qiskit.cloud.jobs(); 119 | assert.ok(res.length > 1); 120 | checkJob(res[0]); 121 | }); 122 | 123 | it('should return selected number of jobs info with "limit" parameter', async function t() { 124 | if (!global.qiskit || !global.qiskit.cloud) { 125 | this.skip(); 126 | } 127 | 128 | const res = await global.qiskit.cloud.jobs(1); 129 | 130 | assert.equal(res.length, 1); 131 | checkJob(res[0]); 132 | oldId = res[0].id; 133 | }); 134 | 135 | it('should skip selected number of jobs info with "offset" parameter', async function t() { 136 | if (!global.qiskit || !global.qiskit.cloud) { 137 | this.skip(); 138 | } 139 | 140 | const res = await global.qiskit.cloud.jobs(1, 1); 141 | 142 | assert.equal(res.length, 1); 143 | checkJob(res[0]); 144 | assert.notEqual(res[0].id, oldId); 145 | }); 146 | }); 147 | -------------------------------------------------------------------------------- /packages/qiskit-cloud/test/unit/parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const parser = require('../../lib/parser'); 15 | const expErrRegex = require('../errorRe'); 16 | 17 | describe('parser:number', () => { 18 | it('should fail without parameter', () => 19 | assert.throws(() => { 20 | parser.number(); 21 | }, expErrRegex.formatNumber)); 22 | 23 | it('should fail with bad format in the parameter', () => 24 | assert.throws(() => { 25 | parser.number(true); 26 | }, expErrRegex.formatNumber)); 27 | 28 | it('should return the result with a good parameter', () => 29 | assert.equal(parser.number(1), 1)); 30 | }); 31 | 32 | describe('parser:string', () => { 33 | it('should fail without parameter', () => 34 | assert.throws(() => { 35 | parser.string(); 36 | }, expErrRegex.formatStr)); 37 | 38 | it('should fail with bad format in the parameter', () => 39 | assert.throws(() => { 40 | parser.string(1); 41 | }, expErrRegex.formatStr)); 42 | 43 | it('should return the result with a good parameter', () => 44 | assert.equal(parser.string('a'), 'a')); 45 | }); 46 | 47 | describe('parser:bool', () => { 48 | it('should fail without parameter', () => 49 | assert.throws(() => { 50 | parser.bool(); 51 | }, expErrRegex.formatBool)); 52 | 53 | it('should fail with bad format in the parameter', () => 54 | assert.throws(() => { 55 | parser.bool('a'); 56 | }, expErrRegex.formatBool)); 57 | 58 | it('should return the result with a good parameter', () => 59 | assert.ok(parser.bool(true))); 60 | }); 61 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js OpenQASM 2 | 3 | :atom_symbol: Quantum Information Science Kit [OpenQASM](https://github.com/IBM/qiskit-openqasm) library. 4 | 5 | Please visit the [main repository](https://github.com/Qiskit/qiskit-js) of the project to know about the rest of the tools. 6 | 7 | ## Install 8 | 9 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 10 | 11 | ```sh 12 | npm i @qiskit/qasm 13 | ``` 14 | 15 | ## Use 16 | 17 | :pencil: You can visit the complete example [in this test](./test/functional/). 18 | 19 | ```js 20 | const qasm = require('@qiskit/qasm'); 21 | const fs = require('fs'); 22 | const util = require('util'); 23 | 24 | console.log('Version'); 25 | console.log(qasm.version); 26 | 27 | const parser = new qasm.Parser(); 28 | 29 | const circuit = fs.readFileSync('./example.qasm', 'utf8'); 30 | 31 | console.log(util.inspect(parser.parse(circuit), { depth: null })); 32 | ``` 33 | 34 | ## API 35 | 36 | :eyes: Full specification. 37 | 38 | ### `version` 39 | 40 | The actual version of the library. 41 | 42 | * `version` (string) - Version number. 43 | 44 | ### `Parser(opts) -> parser` 45 | 46 | The constructor accepts next option: 47 | 48 | * `core` (boolean) - To include core libraries. (default: true) 49 | 50 | ### `parser.parse(circuit) -> circuitJson` 51 | 52 | **NOTE: Method still partially implemented** 53 | Get the intermediate representation of the circuit using the OpenQASM parser. 54 | 55 | * `circuit` (string) - QASM circuit representation. 56 | * `circuitJson` (object): The same information in JSON format. 57 | 58 | ### `QasmError(msg, opts) -> error` 59 | 60 | Custom QASM error class. 61 | 62 | * `msg` (string) - Error message. 63 | * `opts` (object) - Optional parameter, including next fields: 64 | * `line` (number) - Line number where the error happened. 65 | * `column` (number) - Column number where the error happened. 66 | * `text` (string) - Text extracted from where the error happened. 67 | * `token` (string) - Identifier found where the error happened. 68 | * `expected` (string) - Regular expresion for supported values. 69 | * `error` (Error) - A common JS error including also next fields: 70 | * `name` (string) - Error name ("QasmError"). 71 | * `message` (string) - Error message. 72 | * `stack` (string) - Error stack. 73 | * From here the same fields that for `opts` are included. 74 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/__snapshots__/parser.test.js: -------------------------------------------------------------------------------- 1 | exports['qasm:parse should work with "IBMQASM 2.0" as version header 1'] = [ 2 | { 3 | "type": "qubit", 4 | "identifier": "q", 5 | "number": "1" 6 | }, 7 | { 8 | "type": "clbit", 9 | "identifier": "c", 10 | "number": "1" 11 | }, 12 | { 13 | "type": "measure", 14 | "qreg": { 15 | "name": "q" 16 | }, 17 | "creg": { 18 | "name": "c" 19 | } 20 | } 21 | ] 22 | 23 | exports['qasm:parse should work with with "OPENQASM 2.0" as version header 1'] = [ 24 | { 25 | "type": "qubit", 26 | "identifier": "q", 27 | "number": "1" 28 | }, 29 | { 30 | "type": "clbit", 31 | "identifier": "c", 32 | "number": "1" 33 | }, 34 | { 35 | "type": "measure", 36 | "qreg": { 37 | "name": "q" 38 | }, 39 | "creg": { 40 | "name": "c" 41 | } 42 | } 43 | ] 44 | 45 | exports['qasm:parse should work with "include" 1'] = [ 46 | { 47 | "type": "qubit", 48 | "identifier": "q", 49 | "number": "5" 50 | }, 51 | { 52 | "type": "clbit", 53 | "identifier": "c", 54 | "number": "5" 55 | }, 56 | { 57 | "type": "gate", 58 | "name": "x", 59 | "identifiers": [ 60 | { 61 | "name": "q", 62 | "index": "0" 63 | } 64 | ] 65 | }, 66 | { 67 | "type": "measure", 68 | "qreg": { 69 | "name": "q" 70 | }, 71 | "creg": { 72 | "name": "c" 73 | } 74 | } 75 | ] 76 | 77 | exports['qasm:parse should work with RESET 1'] = [ 78 | { 79 | "type": "qubit", 80 | "identifier": "q", 81 | "number": "1" 82 | }, 83 | { 84 | "type": "clbit", 85 | "identifier": "c", 86 | "number": "1" 87 | }, 88 | { 89 | "type": "reset", 90 | "qreg": { 91 | "name": "q", 92 | "index": "0" 93 | } 94 | } 95 | ] 96 | 97 | exports['qasm:parse should fail with "include" 1'] = [ 98 | { 99 | "type": "qubit", 100 | "identifier": "q", 101 | "number": "1" 102 | }, 103 | { 104 | "type": "clbit", 105 | "identifier": "c", 106 | "number": "1" 107 | }, 108 | { 109 | "type": "gate", 110 | "name": "x", 111 | "identifiers": [ 112 | { 113 | "name": "q", 114 | "index": "1" 115 | } 116 | ] 117 | } 118 | ] 119 | 120 | exports['qasm:parse should work with OPAQUE gate (1) 1'] = [ 121 | { 122 | "type": "qubit", 123 | "identifier": "q", 124 | "number": "1" 125 | }, 126 | { 127 | "type": "clbit", 128 | "identifier": "c", 129 | "number": "1" 130 | }, 131 | { 132 | "type": "opaque", 133 | "bitList": [ 134 | "a", 135 | "b", 136 | "c" 137 | ] 138 | } 139 | ] 140 | 141 | exports['qasm:parse should work with OPAQUE gate (2) 1'] = [ 142 | { 143 | "type": "qubit", 144 | "identifier": "q", 145 | "number": "1" 146 | }, 147 | { 148 | "type": "clbit", 149 | "identifier": "c", 150 | "number": "1" 151 | }, 152 | { 153 | "type": "opaque", 154 | "bitList": [ 155 | "a", 156 | "b", 157 | "c" 158 | ] 159 | } 160 | ] 161 | 162 | exports['qasm:parse should work with OPAQUE gate (3) 1'] = [ 163 | { 164 | "type": "qubit", 165 | "identifier": "q", 166 | "number": "1" 167 | }, 168 | { 169 | "type": "clbit", 170 | "identifier": "c", 171 | "number": "1" 172 | }, 173 | { 174 | "type": "opaque", 175 | "bitList": [ 176 | "a", 177 | "b", 178 | "c" 179 | ], 180 | "gateIdList": [ 181 | "x", 182 | "y" 183 | ] 184 | } 185 | ] 186 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/core/qelib1.inc: -------------------------------------------------------------------------------- 1 | // Quantum Experience (QE) Standard Header 2 | // file: qelib1.inc 3 | 4 | // --- QE Hardware primitives --- 5 | 6 | // 3-parameter 2-pulse single qubit gate 7 | gate u3(theta,phi,lambda) q { U(theta,phi,lambda) q; } 8 | // 2-parameter 1-pulse single qubit gate 9 | gate u2(phi,lambda) q { U(pi/2,phi,lambda) q; } 10 | // 1-parameter 0-pulse single qubit gate 11 | gate u1(lambda) q { U(0,0,lambda) q; } 12 | // controlled-NOT 13 | gate cx c,t { CX c,t; } 14 | // idle gate (identity) 15 | gate id a { U(0,0,0) a; } 16 | // idle gate (identity) with length gamma*sqglen 17 | gate u0(gamma) q { U(0,0,0) q; } 18 | 19 | // --- QE Standard Gates --- 20 | 21 | // Pauli gate: bit-flip 22 | gate x a { u3(pi,0,pi) a; } 23 | // Pauli gate: bit and phase flip 24 | gate y a { u3(pi,pi/2,pi/2) a; } 25 | // Pauli gate: phase flip 26 | gate z a { u1(pi) a; } 27 | // Clifford gate: Hadamard 28 | gate h a { u2(0,pi) a; } 29 | // Clifford gate: sqrt(Z) phase gate 30 | gate s a { u1(pi/2) a; } 31 | // Clifford gate: conjugate of sqrt(Z) 32 | gate sdg a { u1(-pi/2) a; } 33 | // C3 gate: sqrt(S) phase gate 34 | gate t a { u1(pi/4) a; } 35 | // C3 gate: conjugate of sqrt(S) 36 | gate tdg a { u1(-pi/4) a; } 37 | 38 | // --- Standard rotations --- 39 | // Rotation around X-axis 40 | gate rx(theta) a { u3(theta, -pi/2,pi/2) a; } 41 | // rotation around Y-axis 42 | gate ry(theta) a { u3(theta,0,0) a; } 43 | // rotation around Z axis 44 | gate rz(phi) a { u1(phi) a; } 45 | 46 | // --- QE Standard User-Defined Gates --- 47 | 48 | // controlled-Phase 49 | gate cz a,b { h b; cx a,b; h b; } 50 | // controlled-Y 51 | gate cy a,b { sdg b; cx a,b; s b; } 52 | // controlled-H 53 | gate ch a,b { 54 | h b; sdg b; 55 | cx a,b; 56 | h b; t b; 57 | cx a,b; 58 | t b; h b; s b; x b; s a; 59 | } 60 | // C3 gate: Toffoli 61 | gate ccx a,b,c 62 | { 63 | h c; 64 | cx b,c; tdg c; 65 | cx a,c; t c; 66 | cx b,c; tdg c; 67 | cx a,c; t b; t c; h c; 68 | cx a,b; t a; tdg b; 69 | cx a,b; 70 | } 71 | // controlled rz rotation 72 | gate crz(lambda) a,b 73 | { 74 | u1(lambda/2) b; 75 | cx a,b; 76 | u1(-lambda/2) b; 77 | cx a,b; 78 | } 79 | // controlled phase rotation 80 | gate cu1(lambda) a,b 81 | { 82 | u1(lambda/2) a; 83 | cx a,b; 84 | u1(-lambda/2) b; 85 | cx a,b; 86 | u1(lambda/2) b; 87 | } 88 | // controlled-U 89 | gate cu3(theta,phi,lambda) c, t 90 | { 91 | // implements controlled-U(theta,phi,lambda) with target t and control c 92 | u1((lambda-phi)/2) t; 93 | cx c,t; 94 | u3(-theta/2,0,-(phi+lambda)/2) t; 95 | cx c,t; 96 | u3(theta/2,phi,0) t; 97 | } 98 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/example.qasm: -------------------------------------------------------------------------------- 1 | IBMQASM 2.0; 2 | include "qelib1.inc"; 3 | qreg q[1]; 4 | creg c[1]; 5 | 6 | x q[1]; 7 | measure q -> c; 8 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const Parser = require('./lib/Parser'); 13 | const QasmError = require('./lib/QasmError'); 14 | const { version } = require('./package'); 15 | 16 | module.exports = { 17 | version, 18 | Parser, 19 | QasmError, 20 | }; 21 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/lib/Parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const jison = require('jison'); 13 | 14 | // const util = require('util'); 15 | const path = require('path'); 16 | const fs = require('fs'); 17 | const utils = require('./utils'); 18 | 19 | const dbg = utils.dbg(__filename); 20 | 21 | const QasmError = require('./QasmError'); 22 | 23 | // TODO: Do async? 24 | const bnf = fs.readFileSync(path.resolve(__dirname, 'grammar.jison'), 'utf8'); 25 | 26 | class Parser { 27 | constructor(opts = {}) { 28 | dbg('Starting', opts); 29 | this.parser = new jison.Parser(bnf); 30 | 31 | if (opts.core !== false) { 32 | // TODO: Parse all core libraries (when we have more) 33 | const qelib1 = fs.readFileSync( 34 | path.resolve(__dirname, '../core/qelib1.inc'), 35 | 'utf8', 36 | ); 37 | this.qelibParsed = this.parser.parse(qelib1); 38 | } 39 | } 40 | 41 | parse(circuit) { 42 | if (!circuit) { 43 | throw new TypeError('Required param: circuit'); 44 | } 45 | 46 | let res; 47 | 48 | try { 49 | res = this.parser.parse(circuit, this.qelibParsed); 50 | } catch (err) { 51 | if (err instanceof QasmError) { 52 | throw err; 53 | } 54 | throw new QasmError(err.message) 55 | } 56 | 57 | return res; 58 | } 59 | } 60 | 61 | module.exports = Parser; 62 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/lib/QasmError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | class QasmError extends Error { 13 | 14 | constructor(message, opts = {}) { 15 | if (!message) { 16 | throw new TypeError('Required param: message'); 17 | } 18 | super(message); 19 | this.name = 'QasmError'; 20 | 21 | // TODO: Review: error code, etc? If coming from jison X ours Y 22 | if (opts.line) { 23 | this.line = opts.line; 24 | this.message += ` (line:${this.line})`; 25 | } 26 | if (opts.column) { 27 | this.column = opts.column; 28 | } 29 | if (opts.text) { 30 | this.text = opts.text; 31 | } 32 | if (opts.token) { 33 | this.token = opts.token; 34 | } 35 | if (opts.expected) { 36 | this.expected = opts.expected; 37 | } 38 | } 39 | 40 | } 41 | 42 | module.exports = QasmError; 43 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const pkgName = require('../package.json').name; 15 | 16 | utils.dbg = fullPath => utils.debug(`${pkgName}:${utils.pathToTag(fullPath)}`); 17 | 18 | module.exports = utils; 19 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/qasm", 3 | "version": "0.9.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "JSONSelect": { 8 | "version": "0.4.0", 9 | "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", 10 | "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" 11 | }, 12 | "JSV": { 13 | "version": "4.0.2", 14 | "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", 15 | "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=" 16 | }, 17 | "amdefine": { 18 | "version": "1.0.1", 19 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 20 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", 21 | "optional": true 22 | }, 23 | "cjson": { 24 | "version": "0.3.0", 25 | "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.3.0.tgz", 26 | "integrity": "sha1-5kObkHA9MS/24iJAl76pLOPQKhQ=", 27 | "requires": { 28 | "jsonlint": "1.6.0" 29 | } 30 | }, 31 | "colors": { 32 | "version": "0.5.1", 33 | "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", 34 | "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=" 35 | }, 36 | "ebnf-parser": { 37 | "version": "0.1.10", 38 | "resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz", 39 | "integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE=" 40 | }, 41 | "escodegen": { 42 | "version": "1.3.3", 43 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", 44 | "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", 45 | "requires": { 46 | "esprima": "~1.1.1", 47 | "estraverse": "~1.5.0", 48 | "esutils": "~1.0.0", 49 | "source-map": "~0.1.33" 50 | } 51 | }, 52 | "esprima": { 53 | "version": "1.1.1", 54 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", 55 | "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" 56 | }, 57 | "estraverse": { 58 | "version": "1.5.1", 59 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", 60 | "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" 61 | }, 62 | "esutils": { 63 | "version": "1.0.0", 64 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", 65 | "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" 66 | }, 67 | "jison": { 68 | "version": "0.4.18", 69 | "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.18.tgz", 70 | "integrity": "sha512-FKkCiJvozgC7VTHhMJ00a0/IApSxhlGsFIshLW6trWJ8ONX2TQJBBz6DlcO1Gffy4w9LT+uL+PA+CVnUSJMF7w==", 71 | "requires": { 72 | "JSONSelect": "0.4.0", 73 | "cjson": "0.3.0", 74 | "ebnf-parser": "0.1.10", 75 | "escodegen": "1.3.x", 76 | "esprima": "1.1.x", 77 | "jison-lex": "0.3.x", 78 | "lex-parser": "~0.1.3", 79 | "nomnom": "1.5.2" 80 | } 81 | }, 82 | "jison-lex": { 83 | "version": "0.3.4", 84 | "resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.3.4.tgz", 85 | "integrity": "sha1-gcoo2E+ESZ36jFlNzePYo/Jux6U=", 86 | "requires": { 87 | "lex-parser": "0.1.x", 88 | "nomnom": "1.5.2" 89 | } 90 | }, 91 | "jsonlint": { 92 | "version": "1.6.0", 93 | "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.0.tgz", 94 | "integrity": "sha1-iKpGvCiaesk7tGyuLVihh6m7SUo=", 95 | "requires": { 96 | "JSV": ">= 4.0.x", 97 | "nomnom": ">= 1.5.x" 98 | } 99 | }, 100 | "lex-parser": { 101 | "version": "0.1.4", 102 | "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", 103 | "integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=" 104 | }, 105 | "nomnom": { 106 | "version": "1.5.2", 107 | "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz", 108 | "integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=", 109 | "requires": { 110 | "colors": "0.5.x", 111 | "underscore": "1.1.x" 112 | } 113 | }, 114 | "source-map": { 115 | "version": "0.1.43", 116 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", 117 | "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", 118 | "optional": true, 119 | "requires": { 120 | "amdefine": ">=0.0.4" 121 | } 122 | }, 123 | "underscore": { 124 | "version": "1.1.7", 125 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz", 126 | "integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA=" 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/qasm", 3 | "version": "0.9.0", 4 | "description": "Quantum Information Science Kit OpenQASM library", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://github.com/Qiskit/qiskit-js", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "files": [ 18 | "lib", 19 | "index.js", 20 | "core" 21 | ], 22 | "scripts": { 23 | "deps": "depcheck", 24 | "test": "mocha --recursive --timeout 8000 test --color" 25 | }, 26 | "keywords": [ 27 | "quantum", 28 | "computing", 29 | "information", 30 | "qasm", 31 | "openqasm", 32 | "parser", 33 | "compiler", 34 | "unroller", 35 | "qiskit", 36 | "IBM" 37 | ], 38 | "bugs": { 39 | "url": "https://github.com/Qiskit/qiskit-js/issues" 40 | }, 41 | "dependencies": { 42 | "@qiskit/utils": "^0.9.0", 43 | "jison": "^0.4.18" 44 | }, 45 | "engines": { 46 | "node": ">=10" 47 | }, 48 | "license": "Apache-2.0", 49 | "publishConfig": { 50 | "access": "public" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/test/functional/parser.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | // const util = require('util'); 14 | 15 | const qasm = require('../..'); 16 | const pkgInfo = require('../../package'); 17 | const Parser = require('../../lib/Parser'); 18 | const utilsTest = require('../../../../utils-test'); 19 | 20 | let parser; 21 | 22 | describe('qasm:version', () => 23 | it('should return the package version', () => 24 | assert.equal(qasm.version, pkgInfo.version))); 25 | 26 | describe('qasm:parse', () => { 27 | // TODO: Implement 28 | it('should fail without param', () => { 29 | parser = new Parser(); 30 | assert.throws(() => { 31 | parser.parse(); 32 | }, /Required param: circuit/); 33 | }); 34 | 35 | // const expected = [ 36 | // { type: 'qubit', identifier: 'q', number: '5' }, 37 | // { type: 'clbit', identifier: 'c', number: '5' }, 38 | // { type: 'x', identifiers: [{ name: 'q', index: '0' }] }, 39 | // { type: 'measure', qreg: { name: 'q' }, creg: { name: 'c' } }, 40 | // ]; 41 | // const expected = [ 42 | // { type: 'qubit', identifier: 'q', number: '1' }, 43 | // { type: 'clbit', identifier: 'c', number: '1' }, 44 | // { type: 'measure', qreg: { name: 'q' }, creg: { name: 'c' } }, 45 | // ]; 46 | const circuitSimple = 'qreg q[1];\ncreg c[1];\nmeasure q->c;\n'; 47 | 48 | // TODO: Review the spec. (v2 mandatory OPENQASM 2.0) 49 | it('should work with "IBMQASM 2.0" as version header', () => { 50 | parser = new Parser(); 51 | const circuit = `IBMQASM 2.0;\n${circuitSimple}`; 52 | 53 | utilsTest.shot(parser.parse(circuit)); 54 | }); 55 | 56 | it('should work with with "OPENQASM 2.0" as version header', () => { 57 | parser = new Parser(); 58 | const circuit = `OPENQASM 2.0;\n${circuitSimple}`; 59 | 60 | utilsTest.shot(parser.parse(circuit)); 61 | }); 62 | 63 | it('should fail with any other version header', () => { 64 | parser = new Parser(); 65 | const circuit = 'A 2.0;\n'; 66 | // TODO: More cases 67 | // const circuit = 'OPENQASM 1.0;\n'; 68 | // const circuit = 'A 1.0;\n'; 69 | // const circuit = 'A'; 70 | 71 | // TODO: Not working. 72 | // assert.throws( 73 | // () => { parse(circuit); } 74 | // /Lexical error on line 1: Unrecognized text/ 75 | // ); 76 | assert.throws(() => { 77 | parser.parse(circuit); 78 | }); 79 | }); 80 | 81 | it('should fail with no version header', () => { 82 | parser = new Parser(); 83 | const circuit = 'qreg q[5];\ncreg c[5];\nx q[0];\nmeasure q -> c;'; 84 | 85 | // TODO: Not working. 86 | // assert.throws( 87 | // () => { parse(circuit); }, 88 | // /Lexical error on line 1: Unrecognized text/ 89 | // ); 90 | assert.throws(() => { 91 | parser.parse(circuit); 92 | }); 93 | }); 94 | 95 | // TODO: Not working. 96 | it('should work with "include"', () => { 97 | parser = new Parser(); 98 | const circuit = 99 | 'OPENQASM 2.0;\n' + 100 | 'include "qelib1.inc";\n' + 101 | 'qreg q[5];\n' + 102 | 'creg c[5];\n' + 103 | 'x q[0];\n' + 104 | 'measure q -> c;'; 105 | 106 | utilsTest.shot(parser.parse(circuit)); 107 | }); 108 | 109 | it('should work with RESET', () => { 110 | parser = new Parser(); 111 | const circuit = 'IBMQASM 2.0;\nqreg q[1];\ncreg c[1];\nreset q[0];'; 112 | 113 | utilsTest.shot(parser.parse(circuit)); 114 | }); 115 | 116 | // TODO: Should fail (qreg invalid) 117 | it('should fail with "include"', () => { 118 | parser = new Parser(); 119 | const circuit = 'OPENQASM 2.0;\nqreg q[1];\ncreg c[1];\nx q[1];\n'; 120 | 121 | utilsTest.shot(parser.parse(circuit)); 122 | }); 123 | 124 | it('should work with OPAQUE gate (1)', () => { 125 | parser = new Parser(); 126 | const circuit = 127 | 'OPENQASM 2.0;\n' + 128 | 'qreg q[1];\n' + 129 | 'creg c[1];\n' + 130 | 'opaque myOpaque a,b,c;'; 131 | 132 | utilsTest.shot(parser.parse(circuit)); 133 | }); 134 | 135 | it('should work with OPAQUE gate (2)', () => { 136 | parser = new Parser(); 137 | const circuit = 138 | 'OPENQASM 2.0;\n' + 139 | 'qreg q[1];\n' + 140 | 'creg c[1];\n' + 141 | 'opaque myOpaque () a,b,c;'; 142 | 143 | utilsTest.shot(parser.parse(circuit)); 144 | }); 145 | 146 | it('should work with OPAQUE gate (3)', () => { 147 | parser = new Parser(); 148 | const circuit = 149 | 'OPENQASM 2.0;\n' + 150 | 'qreg q[1];\n' + 151 | 'creg c[1];\n' + 152 | 'opaque myOpaque (x,y) a,b,c;'; 153 | 154 | utilsTest.shot(parser.parse(circuit)); 155 | }); 156 | 157 | it('should throw QasmError if gate is not defined', () => { 158 | parser = new Parser(); 159 | const circuit = 160 | 'OPENQASM 2.0;\n' + 161 | 'qreg q[1];\n' + 162 | 'creg c[1];\n' + 163 | 'a q[0];'; 164 | 165 | assert.throws(() => { 166 | utilsTest.shot(parser.parse(circuit)); 167 | }, { 168 | name: 'QasmError', 169 | message: 'Gate a is not defined (line:4)' 170 | }); 171 | }); 172 | 173 | it('should throw wrap Jison Error as a QasmError', () => { 174 | parser = new Parser(); 175 | const circuit = 176 | 'OPENQASM 2.0;\n' + 177 | 'include "bogus";\n'; 178 | 179 | assert.throws(() => { 180 | utilsTest.shot(parser.parse(circuit)); 181 | }, { 182 | name: 'QasmError', 183 | message: 'Lexical error on line 2. ' + 184 | 'Unrecognized text.\n' + 185 | '...ENQASM 2.0;include "bogus";\n' + 186 | '----------------------^' 187 | }); 188 | }); 189 | }); 190 | -------------------------------------------------------------------------------- /packages/qiskit-qasm/test/functional/qasmError.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | // const util = require('util'); 14 | const QasmError = require('../../lib/QasmError'); 15 | 16 | describe('qasm:QasmError', () => { 17 | it('should return the error with a message and all options', () => { 18 | const msg = 'test msg'; 19 | const opts = { 20 | line: 24, 21 | column: 5, 22 | text: 'a', 23 | token: 'b', 24 | expected: 'other', 25 | }; 26 | 27 | const err = new QasmError(msg, opts); 28 | 29 | assert.equal(err.name, 'QasmError'); 30 | assert.equal(err.message, `${msg} (line:${opts.line})`); 31 | assert.equal(typeof err.stack, 'string'); 32 | assert.equal(err.line, 24); 33 | assert.equal(err.column, 5); 34 | assert.equal(err.text, 'a'); 35 | assert.equal(err.token, 'b'); 36 | assert.equal(err.expected, 'other'); 37 | }); 38 | 39 | it('should return the error with a message and without all options', () => { 40 | const msg = 'test msg'; 41 | const opts = { 42 | line: 24, 43 | }; 44 | 45 | const err = new QasmError(msg, opts); 46 | 47 | assert.equal(err.name, 'QasmError'); 48 | assert.equal(typeof err.stack, 'string'); 49 | assert.equal(err.message, `${msg} (line:${opts.line})`); 50 | assert.equal(err.line, 24); 51 | assert.equal(err.column, undefined); 52 | assert.equal(err.text, undefined); 53 | assert.equal(err.token, undefined); 54 | assert.equal(err.expected, undefined); 55 | }); 56 | 57 | it('should return the error with a message and without any option', () => { 58 | const msg = 'test msg'; 59 | 60 | const err = new QasmError(msg); 61 | 62 | assert.equal(err.name, 'QasmError'); 63 | assert.equal(typeof err.stack, 'string'); 64 | assert.equal(err.message, msg); 65 | assert.equal(err.column, undefined); 66 | assert.equal(err.text, undefined); 67 | assert.equal(err.token, undefined); 68 | assert.equal(err.expected, undefined); 69 | }); 70 | 71 | it('should fail without a message', () => { 72 | assert.throws(() => new QasmError(), /Required param: message/); 73 | }); 74 | }); 75 | -------------------------------------------------------------------------------- /packages/qiskit-sim/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js simulator 2 | 3 | :atom_symbol: [Quantum Information Science Kit](https://developer.ibm.com/open/openprojects/qiskit) simulator in pure JavaScript. As a first feature it includes an unitary one, with specific support for [OpenQASM](https://github.com/Qiskit/openqasm) circuits representation. 4 | 5 | Please visit the [main repository](https://github.com/Qiskit/qiskit-js) to know more about the rest of the project tools. 6 | 7 | ## Install 8 | 9 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 10 | 11 | ```sh 12 | npm i @qiskit/sim 13 | ``` 14 | 15 | ## Use 16 | 17 | :pencil: You can visit more complete examples [in the tests](./test). 18 | 19 | ```js 20 | const util = require('util'); 21 | 22 | const { Circuit, Gate } = require('@qiskit/sim'); 23 | 24 | function randomizeInput(nQubits) { 25 | const input = []; 26 | 27 | for (let i = 0; i < nQubits; i += 1) { 28 | const x = !!Math.round(Math.random()); 29 | input.push(x); 30 | 31 | console.log(`${i}:${x ? '|1>' : '|0>'}`); 32 | } 33 | 34 | return input; 35 | } 36 | 37 | const circuit = Circuit.createCircuit(2); 38 | 39 | circuit.add(Gate.h, 0, 0); 40 | circuit.add(Gate.cx, 1, [0, 1]); 41 | circuit.print(); 42 | 43 | console.log('\nInput randomized (as string):'); 44 | const input = randomizeInput(circuit.nQubits); 45 | 46 | console.log('\nInput randomized:'); 47 | console.log(input); 48 | 49 | console.log('\nRunning the circuit now ...'); 50 | circuit.run(input); 51 | 52 | console.log('\nDone, internal state:'); 53 | console.log(circuit.state); 54 | 55 | console.log('\nInternal state (as string):'); 56 | console.log(circuit.stateToString()); 57 | 58 | const circuitIr = circuit.save(); 59 | console.log('\nSaved IR:'); 60 | console.log(util.inspect(circuitIr, { showHidden: false, depth: null })); 61 | ``` 62 | 63 | ## API 64 | 65 | :eyes: Full specification. 66 | 67 | ### `version` 68 | 69 | The actual version of the library. 70 | 71 | * `version` (string) - Version number. 72 | 73 | ### `gates` 74 | 75 | Gates definition. 76 | 77 | * `gates` (object) - Supported gates definition. 78 | 79 | ### `Circuit(opts) -> circuit` 80 | 81 | * `opts` (object) -The constructor accepts next options: 82 | * `nQubits` (number) - Number of qubits needed to run the circuit. It will be automatically updated by the `addGate` method if needed. 83 | * `circuit` (object) - New instance. 84 | 85 | ### `circuit.state` 86 | 87 | * `state` (object, [Math.js matrix](http://mathjs.org/docs/datatypes/matrices.html)) - Internal state of the simulation. 88 | 89 | ### `circuit.stateToString() -> stateStr` 90 | 91 | * `stateStr` (string) - Human friendly representation of the internal state. 92 | 93 | ### `circuit.addGate(gate, column, wires)` 94 | 95 | Add a gate to the circuit. 96 | 97 | * `gate` (Gate|string) - Gate instance or name of the gate, from `gates` field. 98 | * `column` (number) - Qubit to connect the gate. 99 | * `wires` (number / [number]) - Gate connections. An array is used for multi-gates. 100 | 101 | ### `circuit.add(gate, column, wires)` 102 | 103 | Add a gate to the circuit. This function is identical to `addGate` but only 104 | accepts `Gate` instances. 105 | 106 | * `gate` (Gate) - Gate instance to add to the circuit. 107 | * `column` (number) - Qubit to connect the gate. 108 | * `wires` (number / [number]) - Gate connections. An array is used for multi-gates. 109 | 110 | ### `circuit.print([writable])` 111 | 112 | Prints a visual representation of the circuit to standard out (by default). 113 | 114 | * `writable` (object) - Optional [Writable](https://nodejs.org/api/stream.html#stream_writable_streams) 115 | object which will be written to. Defaults to process.stdout. 116 | 117 | ### `circuit.run(input)` 118 | 119 | Make the simulation. 120 | 121 | * `input` ([boolean]) - Initial state of each qubit. 122 | 123 | ### `circuit.save() -> circuitIr` 124 | 125 | Export the circuit setup for a future reuse. 126 | 127 | * `circuitIr` (object) - Simulator internal representation of the circuit (JSON). 128 | 129 | ### `circuit.load(circuitIr)` 130 | 131 | Import a circuit setup. 132 | 133 | * `circuitIr` 134 | -------------------------------------------------------------------------------- /packages/qiskit-sim/example/bell.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const util = require('util'); 13 | 14 | const sim = require('..'); 15 | 16 | function randomizeInput(nQubits) { 17 | const input = []; 18 | 19 | for (let i = 0; i < nQubits; i += 1) { 20 | const x = !!Math.round(Math.random()); 21 | input.push(x); 22 | 23 | /* eslint-disable no-console */ 24 | console.log(`${i}:${x ? '|1>' : '|0>'}`); 25 | } 26 | 27 | return input; 28 | } 29 | 30 | const circuit = new sim.Circuit({ nQubits: 2 }); 31 | 32 | circuit.addGate('h', 0, 0); 33 | circuit.addGate('cx', 1, [0, 1]); 34 | 35 | console.log('\nInput randomized (as string):'); 36 | const input = randomizeInput(circuit.nQubits); 37 | 38 | console.log('\nInput randomized:'); 39 | console.log(input); 40 | 41 | console.log('\nRunning the circuit now ...'); 42 | circuit.run(input); 43 | 44 | console.log('\nDone, internal state:'); 45 | console.log(circuit.state); 46 | 47 | console.log('\nInternal state (as string):'); 48 | console.log(circuit.stateToString()); 49 | 50 | const circuitIr = circuit.save(); 51 | console.log('\nSaved IR:'); 52 | console.log(util.inspect(circuitIr, { showHidden: false, depth: null })); 53 | /* eslint-enable no-console */ 54 | -------------------------------------------------------------------------------- /packages/qiskit-sim/example/deutsch-oracle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The goal of this program is to simulate the deutsch-oracle 3 | * algoritm and provide a JavaScript example for it. 4 | * 5 | * There are lots of great resources on the internet that provide 6 | * the theory. Our hope is that this can compliment those resources. 7 | * 8 | * Usage 9 | * Run as a script: 10 | * $ node ./example/deutsch-oracle.js 11 | * 12 | * Step through with debugger: 13 | * $ node --inspect-brk ./example/deutsch-oracle.js 14 | * 15 | * Run in RPEL: 16 | * $ node 17 | * Welcome to Node.js v12.4.0. 18 | * Type ".help" for more information. 19 | * > const d = require('./example/deutsch-oracle.js'); 20 | * > d.balanced0() 21 | * > d.balanced1() 22 | * > d.const0() 23 | * > d.const1() 24 | */ 25 | const { Circuit, Gate } = require('..'); 26 | 27 | /* eslint-disable */ 28 | 29 | const printTensor = (state) => { 30 | if (state[0].re === 0 && state[1].re === 0) { 31 | _printTensor([0, 1], [state[2].re, state[3].re]); 32 | } else { 33 | _printTensor([1, 0], [state[0].re, state[1].re]); 34 | } 35 | } 36 | 37 | function _printTensor(qubit0, qubit1) { 38 | const padding = 23; 39 | console.log(`${qubit0[0]} ⌈${qubit1[0]}`.padEnd(padding, ' ') + '⌉'); 40 | console.log(` ⌊${qubit1[1]}`.padEnd(padding, ' ') + '⌋'); 41 | console.log(`${qubit0[1]} ⌈${qubit1[0]}`.padEnd(padding, ' ') + '⌉'); 42 | console.log(` ⌊${qubit1[1]}`.padEnd(padding, ' ') + '⌋'); 43 | } 44 | 45 | function print(oracle) { 46 | oracle.forEach((row) => { console.log(row); } ); 47 | console.log(); 48 | } 49 | 50 | function measureQubit0(state) { 51 | return state[0].re === 0 && state[1].re === 0 ? '|1>' : '|0>'; 52 | } 53 | 54 | function run(fn) { 55 | const matrix = oracleMatrixFrom(fn); 56 | const circuit = Circuit.createCircuit(2); 57 | circuit.init(); 58 | circuit.add(Gate.x, 0, 1) 59 | .add(Gate.h, 1, 0) 60 | .add(Gate.h, 1, 1) 61 | .add(new Gate('uf', matrix), 2, [0, 1]) 62 | .add(Gate.h, 3, 0) 63 | .print(); 64 | 65 | console.log('Oracle matrix (uf):'); 66 | print(matrix); 67 | 68 | circuit.run(); 69 | 70 | console.log('Final state:'); 71 | console.log(circuit.stateToString()); 72 | console.log(); 73 | 74 | console.log('Show tensor state:'); 75 | printTensor(circuit.state); 76 | console.log(); 77 | 78 | const qubit0 = measureQubit0(circuit.state); 79 | console.log('Measure qubit 0:'); 80 | console.log(`qubit[0]: ${qubit0}, Function is ${qubit0 === '|1>' ? 81 | 'balanced' : 'constant'}!`); 82 | console.log(); 83 | } 84 | 85 | function oracleMatrixFrom(f) { 86 | const dim = 4; 87 | const input = [{x: 0, y: 0}, {x:0, y:1}, {x:1, y:0}, {x:1, y:1}]; 88 | const matrix = []; 89 | for (let i = 0; i < dim; i++) { 90 | matrix.push(new Array(dim).fill(0)); 91 | } 92 | 93 | for (let z = 0; z < input.length; z++) { 94 | const x = input[z].x; 95 | const y = input[z].y; 96 | const result = y ^ f(x); 97 | if (x === 0) { 98 | matrix[z][result] = 1; 99 | } else { 100 | matrix[z][2+result] = 1; 101 | } 102 | } 103 | return matrix; 104 | } 105 | 106 | function balanced0() { 107 | console.log(' Balanced function f(0) = 1, f(1) = 0'); 108 | run(x => (x === 0) ? 1 : 0); 109 | } 110 | 111 | function balanced1() { 112 | console.log(' Balanced function f(0) = 0, f(1) = 1'); 113 | run(x => (x === 0) ? 0 : 1); 114 | } 115 | 116 | function const0() { 117 | console.log(' Constant 0 function f(0) = 0, f(1) = 0'); 118 | run(x => 0); 119 | } 120 | 121 | function const1() { 122 | console.log(' Constant 1 function f(0) = 1, f(1) = 1'); 123 | run(x => 1); 124 | } 125 | 126 | module.exports = { 127 | balanced0, 128 | balanced1, 129 | const0, 130 | const1 131 | }; 132 | 133 | if (require.main === module) { 134 | balanced0(); 135 | balanced1(); 136 | const0(); 137 | const1(); 138 | } 139 | -------------------------------------------------------------------------------- /packages/qiskit-sim/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const { version } = require('./package'); 13 | const { Gate, gates } = require('./lib/gates'); 14 | const Circuit = require('./lib/Circuit'); 15 | 16 | module.exports = { 17 | version, 18 | gates, 19 | Gate, 20 | Circuit, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/qiskit-sim/lib/gates.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const math = require('mathjs'); 13 | 14 | const identityMatrix = n => { 15 | const matrix = []; 16 | 17 | for (let i = 0; i < n; i += 1) { 18 | matrix[i] = []; 19 | 20 | for (let j = 0; j < n; j += 1) { 21 | matrix[i][j] = j === i ? 1 : 0; 22 | } 23 | } 24 | 25 | return matrix; 26 | }; 27 | 28 | const buildControlled = Gate => { 29 | const U = Gate.matrix; 30 | const m = U.length; 31 | const C = identityMatrix(m * 2); 32 | 33 | for (let i = 0; i < m; i += 1) { 34 | for (let j = 0; j < m; j += 1) { 35 | C[i + m][j + m] = U[i][j]; 36 | } 37 | } 38 | 39 | return C; 40 | }; 41 | 42 | const phaseShift = shift => 43 | [[1, 0], [0, math.pow(math.e, math.multiply(math.i, math.PI / shift))]]; 44 | 45 | const gates = new Map(); 46 | let builtinGateNames; 47 | 48 | class Gate { 49 | constructor(name, matrix) { 50 | this.name = name; 51 | this.matrix = matrix; 52 | if (!builtinGateNames || !builtinGateNames.has(name)) { 53 | gates.set(name, this); 54 | } 55 | } 56 | 57 | prettyMatrix() { 58 | let str = ''; 59 | this.matrix.forEach( (m) => { str += `[${m.join(', ')}]\n`; } ); 60 | return str; 61 | } 62 | } 63 | 64 | Gate.x = new Gate('x', [[0, 1], [1, 0]]); 65 | Gate.y = new Gate('y', [[0, math.multiply(-1, math.i)], [math.i, 0]]); 66 | Gate.z = new Gate('z', [[1, 0], [0, -1]]); 67 | Gate.id = new Gate('id', [[1, 0], [0, 1]]); 68 | Gate.h = new Gate('h', 69 | [[1 / math.sqrt(2), 1 / math.sqrt(2)], 70 | [1 / math.sqrt(2), 0 - 1 / math.sqrt(2)]]); 71 | Gate.srn = new Gate('srn', 72 | [[1 / math.sqrt(2), 0 - 1 / math.sqrt(2)], 73 | [1 / math.sqrt(2), 1 / math.sqrt(2)]]); 74 | Gate.s = new Gate('s', phaseShift(2)); 75 | Gate.r2 = new Gate('r2', Gate.s.matrix); 76 | Gate.r4 = new Gate('r4', phaseShift(4)); 77 | Gate.r8 = new Gate('r8', phaseShift(8)); 78 | Gate.t = new Gate('t', Gate.r4.matrix); 79 | Gate.swap = new Gate('swap', 80 | [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]); 81 | Gate.srswap = new Gate('srswap', 82 | [ 83 | [1, 0, 0, 0], 84 | [ 85 | 0, 86 | math.multiply(0.5, math.add(1, math.i)), 87 | math.multiply(0.5, math.subtract(1, math.i)), 88 | 0, 89 | ], 90 | [ 91 | 0, 92 | math.multiply(0.5, math.subtract(1, math.i)), 93 | math.multiply(0.5, math.add(1, math.i)), 94 | 0, 95 | ], 96 | [0, 0, 0, 1], 97 | ]); 98 | Gate.cx = new Gate('cx', buildControlled(Gate.x)); 99 | Gate.cy = new Gate('cy', buildControlled(Gate.y)); 100 | Gate.cz = new Gate('cz', buildControlled(Gate.z)); 101 | Gate.ch = new Gate('ch', buildControlled(Gate.h)); 102 | Gate.csrn = new Gate('csrn', buildControlled(Gate.srn)); 103 | Gate.cs = new Gate('cs', buildControlled(Gate.s)); 104 | Gate.cr2 = new Gate('cr2', buildControlled(Gate.r2)); 105 | Gate.cr4 = new Gate('cr4', buildControlled(Gate.r4)); 106 | Gate.cr8 = new Gate('cr8', buildControlled(Gate.r8)); 107 | builtinGateNames = new Set(gates.keys()); 108 | 109 | module.exports = { 110 | Gate, 111 | gates 112 | }; 113 | -------------------------------------------------------------------------------- /packages/qiskit-sim/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | const math = require('mathjs'); 14 | 15 | const pkgName = require('../package.json').name; 16 | 17 | utils.dbg = fullPath => utils.debug(`${pkgName}:${utils.pathToTag(fullPath)}`); 18 | 19 | utils.randomString = length => { 20 | const len = length || 17; 21 | let text = ''; 22 | // var first char to be letter 23 | let charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 24 | 25 | text += charset.charAt(Math.floor(Math.random() * charset.length)); 26 | // other chars can be numbers 27 | charset += '0123456789'; 28 | 29 | for (let i = 0; i < len; i += 1) { 30 | text += charset.charAt(Math.floor(Math.random() * charset.length)); 31 | } 32 | 33 | return text; 34 | }; 35 | 36 | utils.formatComplex = complex => { 37 | const re = math.round(complex.re, 8); 38 | const im = math.round(complex.im, 8); 39 | 40 | return `${re}${im >= 0 ? '+' : '-'}${math.abs(im)}i`; 41 | }; 42 | 43 | module.exports = utils; 44 | -------------------------------------------------------------------------------- /packages/qiskit-sim/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/sim", 3 | "version": "0.9.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "complex.js": { 8 | "version": "2.0.11", 9 | "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.11.tgz", 10 | "integrity": "sha512-6IArJLApNtdg1P1dFtn3dnyzoZBEF0MwMnrfF1exSBRpZYoy4yieMkpZhQDC0uwctw48vii0CFVyHfpgZ/DfGw==" 11 | }, 12 | "decimal.js": { 13 | "version": "10.2.0", 14 | "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.0.tgz", 15 | "integrity": "sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==" 16 | }, 17 | "escape-latex": { 18 | "version": "1.2.0", 19 | "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", 20 | "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" 21 | }, 22 | "fraction.js": { 23 | "version": "4.0.12", 24 | "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.0.12.tgz", 25 | "integrity": "sha512-8Z1K0VTG4hzYY7kA/1sj4/r1/RWLBD3xwReT/RCrUCbzPszjNQCCsy3ktkU/eaEqX3MYa4pY37a52eiBlPMlhA==" 26 | }, 27 | "javascript-natural-sort": { 28 | "version": "0.7.1", 29 | "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", 30 | "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=" 31 | }, 32 | "mathjs": { 33 | "version": "5.10.3", 34 | "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-5.10.3.tgz", 35 | "integrity": "sha512-ySjg30BC3dYjQm73ILZtwcWzFJde0VU6otkXW/57IjjuYRa3Qaf0Kb8pydEuBZYtqW2OxreAtsricrAmOj3jIw==", 36 | "requires": { 37 | "complex.js": "2.0.11", 38 | "decimal.js": "10.2.0", 39 | "escape-latex": "1.2.0", 40 | "fraction.js": "4.0.12", 41 | "javascript-natural-sort": "0.7.1", 42 | "seed-random": "2.2.0", 43 | "tiny-emitter": "2.1.0", 44 | "typed-function": "1.1.0" 45 | } 46 | }, 47 | "seed-random": { 48 | "version": "2.2.0", 49 | "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", 50 | "integrity": "sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ=" 51 | }, 52 | "tiny-emitter": { 53 | "version": "2.1.0", 54 | "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", 55 | "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" 56 | }, 57 | "typed-function": { 58 | "version": "1.1.0", 59 | "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-1.1.0.tgz", 60 | "integrity": "sha512-TuQzwiT4DDg19beHam3E66oRXhyqlyfgjHB/5fcvsRXbfmWPJfto9B4a0TBdTrQAPGlGmXh/k7iUI+WsObgORA==" 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/qiskit-sim/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/sim", 3 | "version": "0.9.0", 4 | "description": "Quantum Information Science Kit simulator", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://github.com/Qiskit/qiskit-js", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "files": [ 18 | "lib", 19 | "index.js" 20 | ], 21 | "scripts": { 22 | "deps": "depcheck", 23 | "test": "mocha --recursive test --color" 24 | }, 25 | "keywords": [ 26 | "quantum", 27 | "computing", 28 | "information", 29 | "qasm", 30 | "openqasm", 31 | "simulator", 32 | "emulator", 33 | "compiler", 34 | "unroller", 35 | "qiskit", 36 | "IBM" 37 | ], 38 | "bugs": { 39 | "url": "https://github.com/Qiskit/qiskit-js/issues" 40 | }, 41 | "dependencies": { 42 | "@qiskit/qasm": "^0.9.0", 43 | "@qiskit/utils": "^0.9.0", 44 | "mathjs": "^5.10.0" 45 | }, 46 | "engines": { 47 | "node": ">=10" 48 | }, 49 | "license": "Apache-2.0", 50 | "publishConfig": { 51 | "access": "public" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/qiskit-sim/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit-sim/test/functional/gates.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const { gates, Gate } = require('../..'); 15 | 16 | describe('sim:gates', () => { 17 | it('should include all supported ones', () => 18 | assert.deepEqual([...gates.keys()], [ 19 | 'x', 20 | 'y', 21 | 'z', 22 | 'id', 23 | 'h', 24 | 'srn', 25 | 's', 26 | 'r2', 27 | 'r4', 28 | 'r8', 29 | 't', 30 | 'swap', 31 | 'srswap', 32 | 'cx', 33 | 'cy', 34 | 'cz', 35 | 'ch', 36 | 'csrn', 37 | 'cs', 38 | 'cr2', 39 | 'cr4', 40 | 'cr8', 41 | ])); 42 | it('t gate should have the same unitary matrix as the r4 gate', () => { 43 | assert.deepEqual(Gate.t.matrix, Gate.r4.matrix); 44 | }); 45 | 46 | it('prettyMatrix should return a pretty matrix', () => { 47 | const expected = '[1, 0, 0, 0]\n' + 48 | '[0, 1, 0, 0]\n' + 49 | '[0, 0, 0, 1]\n' + 50 | '[0, 0, 1, 0]\n'; 51 | assert.strictEqual(Gate.cx.prettyMatrix(), expected); 52 | }); 53 | 54 | it('custom gate should be added to gates map', () => { 55 | const custom = new Gate('custom', [[1, 0], [0, 1]]); 56 | assert.ok(gates.has(custom.name)); 57 | }); 58 | 59 | it('custom gate should be allowed to be overwritten', () => { 60 | const custom = new Gate('custom', [[1, 0], [0, 1]]); 61 | const newMatrix = [[1, 0], 62 | [1, 1]]; 63 | const overwrite = new Gate(custom.name, newMatrix); 64 | assert.ok(gates.has(overwrite.name)); 65 | assert.strictEqual(gates.get(custom.name).matrix, newMatrix); 66 | }); 67 | 68 | }); 69 | -------------------------------------------------------------------------------- /packages/qiskit-sim/test/functional/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const sim = require('../..'); 15 | const pkgInfo = require('../../package'); 16 | 17 | describe('sim:index', () => { 18 | it('should include all documented root elements', () => { 19 | assert.deepEqual(Object.keys(sim), ['version', 'gates', 'Gate', 'Circuit']); 20 | }); 21 | }); 22 | 23 | describe('sim:version', () => { 24 | it('should return the package version', () => { 25 | assert.equal(sim.version, pkgInfo.version); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/qiskit-utils/.npmignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.png 3 | *.csv 4 | *.dat 5 | *.iml 6 | *.log 7 | *.out 8 | *.pid 9 | *.seed 10 | *.sublime-* 11 | *.swo 12 | *.swp 13 | *.tgz 14 | *.xml 15 | .DS_Store 16 | .idea 17 | .project 18 | .strong-pm 19 | coverage 20 | *.lock 21 | .vscode 22 | 23 | # Node.js 24 | node_modules 25 | npm-debug.log 26 | .jshintrc 27 | .jslintrc 28 | .editorconfig 29 | 30 | # Project stuff 31 | test 32 | -------------------------------------------------------------------------------- /packages/qiskit-utils/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js utils 2 | 3 | :atom_symbol: Quantum Information Science Kit utils library, shared among the rest of the qiskit-\* packages. 4 | 5 | Please visit the [main repository](https://github.com/Qiskit/qiskit-js) of the project to know about the rest of the tools. 6 | 7 | ## Install 8 | 9 | :coffee: Install lastest [Node.js](https://nodejs.org/download) stable version (or LTS) and then: 10 | 11 | ```sh 12 | npm i @qiskit/utils 13 | ``` 14 | 15 | ## Use 16 | 17 | :pencil: You can visit the complete example [in this test](./test/functional.js). 18 | 19 | ```js 20 | const utils = require('@qiskit/utils'); 21 | 22 | console.log('Version'); 23 | console.log(utils.version); 24 | ``` 25 | 26 | ## API 27 | 28 | :eyes: Full specification. 29 | 30 | ### `version` 31 | 32 | The actual version of the library. 33 | 34 | * `version` (string) - Version number. 35 | 36 | ### `debug` 37 | 38 | Our debugger. A wrapper for [debug](https://github.com/visionmedia/debug). 39 | 40 | * `debug` (object) - The same object provided in the original library. 41 | 42 | ### `pathToTag(fullPath) -> tag` 43 | 44 | To get a consistent tag among all the project debugging. So we use with the `debug` method. 45 | 46 | * `fullPath` (string) - The full path of the file we're debugging. 47 | * `tag` (string) - The name of the file. 48 | 49 | ### `ayb` 50 | 51 | A wrapper for [ayb](https://github.com/nerddiffer/all-your-base). 52 | 53 | * `ayb` (object) - The same object provided in the original library. 54 | -------------------------------------------------------------------------------- /packages/qiskit-utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const path = require('path'); 13 | 14 | const utils = require('lodash'); 15 | const debug = require('debug'); 16 | const ayb = require('all-your-base'); 17 | 18 | const { version } = require('./package.json'); 19 | const genRandom = require('./lib/genRandom'); 20 | 21 | function pathToTag(fullPath) { 22 | const res = path.basename(fullPath, '.js'); 23 | 24 | if (!res || res === fullPath) { 25 | throw new Error('Not valid path'); 26 | } else { 27 | return res; 28 | } 29 | } 30 | 31 | // Exposed stuff. 32 | utils.version = version; 33 | utils.pathToTag = pathToTag; 34 | utils.debug = debug; 35 | utils.ayb = ayb; 36 | utils.genRandom = genRandom; 37 | 38 | module.exports = utils; 39 | -------------------------------------------------------------------------------- /packages/qiskit-utils/lib/genRandom.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | // We can't use "utils.*" here to avoid a circular dep. 13 | const debug = require('debug'); 14 | const lodash = require('lodash'); 15 | const ayb = require('all-your-base'); 16 | 17 | const { name } = require('../package'); 18 | 19 | const formats = ['hex']; 20 | const dbg = debug(name); 21 | 22 | // TODO: Document this. 23 | module.exports = async (genHex, opts = {}) => { 24 | let len = 16; 25 | 26 | dbg('Passed opts:', opts); 27 | 28 | if (!genHex) { 29 | throw new Error('Required "genHex" param'); 30 | } 31 | 32 | if (opts.length) { 33 | if (typeof opts.length !== 'number') { 34 | throw new TypeError('A number expected for "length"'); 35 | } 36 | 37 | len = opts.length; 38 | } 39 | dbg('Parsed opts:', { len }); 40 | 41 | const hexadecimal = await genHex(len); 42 | 43 | dbg('Generated number (hexadecimal):', { 44 | hexadecimal, 45 | len: hexadecimal.length, 46 | }); 47 | 48 | if (opts.format) { 49 | if (!lodash.includes(formats, opts.format)) { 50 | throw new Error(`Not supported "format", allowed: ${formats}`); 51 | } 52 | 53 | // We make this check here to return in advance and avoit to 54 | // convert it to decimal in this cases. 55 | if (opts.format === 'hex') { 56 | return hexadecimal; 57 | } 58 | } 59 | 60 | // ie (after "ayb"): 1.1914622019661597e+24, 5.591825073748114e+23 61 | const decimal = ayb.parseInt(hexadecimal, 16, 10); 62 | 63 | dbg('Generated number (decimal):', { decimal }); 64 | 65 | // To return a value between 0 and 1 (similar to "Math.floor"). 66 | return decimal / 10 ** decimal.toString().length; 67 | }; 68 | -------------------------------------------------------------------------------- /packages/qiskit-utils/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/utils", 3 | "version": "0.9.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "all-your-base": { 8 | "version": "0.3.0", 9 | "resolved": "https://registry.npmjs.org/all-your-base/-/all-your-base-0.3.0.tgz", 10 | "integrity": "sha1-61apxC2l0XNeradF6S0FaLaFDTQ=" 11 | }, 12 | "debug": { 13 | "version": "4.1.1", 14 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 15 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 16 | "requires": { 17 | "ms": "^2.1.1" 18 | } 19 | }, 20 | "lodash": { 21 | "version": "4.17.11", 22 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", 23 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" 24 | }, 25 | "ms": { 26 | "version": "2.1.1", 27 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 28 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/qiskit-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@qiskit/utils", 3 | "version": "0.9.0", 4 | "description": "Quantum Information Science Kit utils library", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://github.com/Qiskit/qiskit-js", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "scripts": { 18 | "deps": "depcheck", 19 | "test": "mocha --recursive test --color" 20 | }, 21 | "keywords": [ 22 | "quantum", 23 | "experience", 24 | "computing", 25 | "information", 26 | "utils", 27 | "helpers", 28 | "qiskit", 29 | "IBM" 30 | ], 31 | "bugs": { 32 | "url": "https://github.com/Qiskit/qiskit-js/issues" 33 | }, 34 | "dependencies": { 35 | "all-your-base": "^0.3.0", 36 | "debug": "^4.1.1", 37 | "lodash": "^4.17.11" 38 | }, 39 | "engines": { 40 | "node": ">=10" 41 | }, 42 | "license": "Apache-2.0", 43 | "publishConfig": { 44 | "access": "public" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/qiskit-utils/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit-utils/test/functional.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const utils = require('..'); 15 | const { version } = require('../package'); 16 | 17 | function multiIncludes(text, values) { 18 | return values.every(val => text.includes(val)); 19 | } 20 | 21 | describe('utils:api', () => { 22 | it('should include all documented items', () => { 23 | assert.ok( 24 | multiIncludes(Object.keys(utils), ['version', 'debug', 'pathToTag']), 25 | ); 26 | }); 27 | 28 | it('should return the the correct result for its methods', () => 29 | assert.equal(utils.version, version)); 30 | }); 31 | 32 | describe('sim:utils:pathToTag', () => { 33 | // We can use this function here to get the name of this file 34 | // because we're testing it. 35 | it('should work with a valid file name', () => 36 | assert.equal('index', utils.pathToTag('./a/b/c/index.js'))); 37 | 38 | it('should fail with an invalid file name', () => 39 | assert.throws(() => { 40 | utils.pathToTag('a'); 41 | }, /Not valid path/)); 42 | }); 43 | -------------------------------------------------------------------------------- /packages/qiskit/README.md: -------------------------------------------------------------------------------- 1 | # Qiskit.js 2 | 3 | Please visit the documentation in the [main repository](https://github.com/Qiskit/qiskit-js). 4 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/backend.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'backend [name]'; 16 | 17 | exports.aliases = ['b']; 18 | 19 | exports.desc = 'Get latest calibration stats for a backend'; 20 | 21 | exports.builder = { 22 | name: { 23 | desc: 'Name of the backend to inspect', 24 | type: 'string', 25 | default: 'ibmqx4', 26 | }, 27 | }; 28 | 29 | exports.handler = argv => { 30 | logger.title(qiskit.version); 31 | 32 | global.qiskit.cloud 33 | .backend(argv.name) 34 | .then(res => { 35 | logger.resultHead(); 36 | logger.json(res); 37 | }) 38 | .catch(err => { 39 | logger.error('Making the request', err); 40 | process.exit(1); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/backends.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | const utils = require('../lib/utils'); 15 | 16 | exports.command = 'backends [onlySims]'; 17 | 18 | exports.aliases = ['bs']; 19 | 20 | exports.desc = 'Get latest calibration stats for a backend'; 21 | 22 | exports.builder = { 23 | onlySims: { 24 | desc: ' To get only info of the simulators', 25 | type: 'boolean', 26 | default: false, 27 | }, 28 | }; 29 | 30 | exports.handler = argv => { 31 | logger.title(qiskit.version); 32 | 33 | global.qiskit.cloud 34 | .backends(argv.onlySims) 35 | .then(res => { 36 | logger.resultHead(); 37 | 38 | utils.forEach(res, data => { 39 | let header = `${data.name}`; 40 | if (data.chipName) { 41 | header = `${header} (${data.chipName}, v${data.version})`; 42 | } 43 | logger.bold(`\n${header}`); 44 | logger.regular( 45 | `simulator: ${data.simulator} nQubits: ${data.nQubits} status: ${ 46 | data.status 47 | }`, 48 | ); 49 | }); 50 | }) 51 | .catch(err => { 52 | logger.error('Making the request', err); 53 | process.exit(1); 54 | }); 55 | }; 56 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/calibration.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'calibration [backend]'; 16 | 17 | exports.aliases = ['c']; 18 | 19 | exports.desc = 'Get latest calibration stats for a backend'; 20 | 21 | exports.builder = { 22 | backend: { 23 | desc: 'Name of the backend to inspect', 24 | type: 'string', 25 | default: 'ibmqx4', 26 | }, 27 | }; 28 | 29 | exports.handler = argv => { 30 | logger.title(qiskit.version); 31 | 32 | global.qiskit.cloud 33 | .calibration(argv.backend) 34 | .then(res => { 35 | logger.resultHead(); 36 | logger.json(res); 37 | }) 38 | .catch(err => { 39 | logger.error('Making the request', err); 40 | process.exit(1); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/circuit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const fs = require('fs'); 13 | const path = require('path'); 14 | const util = require('util'); 15 | 16 | const qiskit = require('../..'); 17 | const logger = require('../lib/logger'); 18 | 19 | const readFile = util.promisify(fs.readFile); 20 | 21 | exports.command = 22 | 'circuit [backend] [shots] [name] [seed] [maxCredits]'; 23 | 24 | exports.aliases = ['ci']; 25 | 26 | exports.desc = 27 | 'Send the circuit to be run in the Quantum Experience' + 28 | ' (https://quantumexperience.ng.bluemix.net)'; 29 | 30 | exports.builder = { 31 | circuit: { 32 | desc: 'Path to the file with the code of the circuit (OpenQASM)', 33 | type: 'string', 34 | normalize: true, 35 | }, 36 | backend: { 37 | desc: 'Name of the backend to use', 38 | type: 'string', 39 | default: 'simulator', 40 | }, 41 | shots: { 42 | desc: 'Number of times to run the circuit', 43 | type: 'string', 44 | default: 1, 45 | }, 46 | name: { 47 | desc: 'Human friendly indetifier', 48 | type: 'string', 49 | }, 50 | seed: { 51 | desc: 'Noise entropy, only allowed if using the simulator', 52 | type: 'string', 53 | }, 54 | maxCredits: { 55 | desc: 'Number of times to run the circuit', 56 | type: 'number', 57 | }, 58 | }; 59 | 60 | exports.handler = argv => { 61 | logger.title(qiskit.version); 62 | 63 | const extension = path.extname(argv.circuit); 64 | 65 | if (!extension || extension !== '.qasm') { 66 | logger.error('Format not supported'); 67 | process.exit(1); 68 | } 69 | 70 | const pathCode = path.resolve(process.cwd(), argv.circuit); 71 | 72 | logger.info(`${logger.emoji('mag')} Reading the circuit file: ${pathCode}`); 73 | readFile(pathCode, 'utf8') 74 | .then(code => { 75 | global.qiskit.cloud 76 | .run( 77 | code, 78 | argv.backend, 79 | argv.shots, 80 | argv.name, 81 | argv.seed, 82 | argv.maxCredits, 83 | ) 84 | .then(res => { 85 | logger.resultHead(); 86 | logger.json(res); 87 | }) 88 | .catch(err => { 89 | logger.error('Making the request', err); 90 | process.exit(1); 91 | }); 92 | }) 93 | .catch(err => { 94 | logger.error('Reading the circuit file', err); 95 | process.exit(1); 96 | }); 97 | }; 98 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/credits.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'credits'; 16 | 17 | exports.aliases = ['cr']; 18 | 19 | exports.desc = 'Information about your credits'; 20 | 21 | exports.builder = {}; 22 | 23 | exports.handler = () => { 24 | logger.title(qiskit.version); 25 | 26 | global.qiskit.cloud 27 | .credits() 28 | .then(res => { 29 | logger.resultHead(); 30 | logger.json(res); 31 | }) 32 | .catch(err => { 33 | logger.error('Making the request', err); 34 | process.exit(1); 35 | }); 36 | }; 37 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/factor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'factor '; 16 | 17 | exports.aliases = ['f']; 18 | 19 | exports.desc = 'Calculate a factor of a number'; 20 | 21 | exports.builder = { 22 | number: { 23 | desc: 'Number to factorize', 24 | type: 'number', 25 | }, 26 | }; 27 | 28 | exports.handler = argv => { 29 | logger.title(qiskit.version); 30 | 31 | qiskit.algo 32 | .factor(argv.number) 33 | .then(res => { 34 | logger.resultHead(); 35 | logger.json(res); 36 | }) 37 | .catch(err => { 38 | logger.error('Making the request', err); 39 | process.exit(1); 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/job.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'job '; 16 | 17 | exports.aliases = ['j']; 18 | 19 | exports.desc = 'Get the info of a specific job'; 20 | 21 | exports.builder = { 22 | id: { 23 | desc: 'Job identifier', 24 | type: 'string', 25 | }, 26 | }; 27 | 28 | exports.handler = argv => { 29 | logger.title(qiskit.version); 30 | 31 | global.qiskit.cloud 32 | .job(argv.id) 33 | .then(res => { 34 | logger.resultHead(); 35 | logger.json(res); 36 | }) 37 | .catch(err => { 38 | logger.error('Making the request', err); 39 | process.exit(1); 40 | }); 41 | }; 42 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/jobs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | const utils = require('../lib/utils'); 15 | 16 | exports.command = 'jobs [limit] [offset]'; 17 | 18 | exports.aliases = ['js']; 19 | 20 | exports.desc = 'Get all your jobs. Ordered by creation date'; 21 | 22 | exports.builder = { 23 | limit: { 24 | desc: ' To get only info of the simulators', 25 | type: 'number', 26 | default: 50, 27 | }, 28 | offset: { 29 | desc: ' To get only info of the simulators', 30 | type: 'number', 31 | }, 32 | }; 33 | 34 | exports.handler = argv => { 35 | logger.title(qiskit.version); 36 | 37 | global.qiskit.cloud 38 | .jobs(argv.limit, argv.offset) 39 | .then(res => { 40 | logger.resultHead(); 41 | 42 | utils.forEach(res, data => { 43 | let header = `${data.id}`; 44 | if (data.name) { 45 | header = `${header} (${data.name})`; 46 | } 47 | 48 | /* eslint-disable no-param-reassign */ 49 | delete data.id; 50 | delete data.name; 51 | data.circuits = data.circuits.length; 52 | /* eslint-enable no-param-reassign */ 53 | 54 | logger.bold(`\n${header}`); 55 | logger.json(data); 56 | }); 57 | }) 58 | .catch(err => { 59 | logger.error('Making the request', err); 60 | process.exit(1); 61 | }); 62 | }; 63 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/login.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const util = require('util'); 13 | 14 | const prompt = require('prompt'); 15 | 16 | const qiskit = require('../..'); 17 | const logger = require('../lib/logger'); 18 | const storage = require('../lib/storage'); 19 | 20 | const getToken = util.promisify(prompt.get); 21 | const promptSchema = { 22 | properties: { 23 | apiKey: { 24 | type: 'string', 25 | hidden: true, 26 | message: 27 | 'Quantum Experience API key, you can get' + 28 | ' it here: https://quantumexperience.ng.bluemix.net/qx/account/advanced', 29 | required: true, 30 | }, 31 | }, 32 | }; 33 | 34 | exports.command = 'login [printToken]'; 35 | 36 | exports.aliases = ['l']; 37 | 38 | exports.desc = 'Use an API key to get a token to make requests'; 39 | 40 | exports.builder = { 41 | printToken: { 42 | desc: 'To show the returned API auth token in the console', 43 | type: 'boolean', 44 | default: false, 45 | }, 46 | }; 47 | 48 | exports.handler = argv => { 49 | logger.title(qiskit.version); 50 | 51 | prompt.start(); 52 | getToken(promptSchema) 53 | .then(entered => { 54 | global.qiskit.cloud 55 | .login(entered.apiKey) 56 | .then(res => { 57 | logger.resultHead(); 58 | 59 | Promise.all([ 60 | storage.setItem('token', res.token), 61 | storage.setItem('userId', res.userId), 62 | ]) 63 | .then(() => { 64 | if (!argv.printToken) { 65 | delete res.token; 66 | } 67 | 68 | logger.json(res); 69 | logger.regular( 70 | '\nHTTP API auth token and user ID correctly stored for future use', 71 | ); 72 | }) 73 | .catch(err => { 74 | logger.error('Storing the new long term token', err); 75 | process.exit(1); 76 | }); 77 | }) 78 | .catch(err => { 79 | logger.error('Making the request', err); 80 | process.exit(1); 81 | }); 82 | }) 83 | .catch(err => { 84 | logger.error('Prompting for the personal token', err); 85 | process.exit(1); 86 | }); 87 | }; 88 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/params.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'params [backend]'; 16 | 17 | exports.aliases = ['p']; 18 | 19 | exports.desc = 'Get latest parameter stats for a backend'; 20 | 21 | exports.builder = { 22 | backend: { 23 | desc: 'Name of the backend to inspect', 24 | type: 'string', 25 | default: 'ibmqx4', 26 | }, 27 | }; 28 | 29 | exports.handler = argv => { 30 | logger.title(qiskit.version); 31 | 32 | global.qiskit.cloud 33 | .parameters(argv.backend) 34 | .then(res => { 35 | logger.resultHead(); 36 | logger.json(res); 37 | }) 38 | .catch(err => { 39 | logger.error('Making the request', err); 40 | process.exit(1); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/parse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const fs = require('fs'); 13 | const path = require('path'); 14 | const util = require('util'); 15 | 16 | const qiskit = require('../..'); 17 | const utils = require('../lib/utils'); 18 | const logger = require('../lib/logger'); 19 | 20 | const readFile = util.promisify(fs.readFile); 21 | const dbg = utils.dbg(__filename); 22 | 23 | exports.command = 'parse '; 24 | 25 | exports.aliases = ['p']; 26 | 27 | // TODO: Put a name to our IR. 28 | exports.desc = 29 | 'Parse the circuit to our IR (intermediate representation - JSON format).'; 30 | 31 | exports.builder = { 32 | circuit: { 33 | desc: 'Path to the file with the code of the circuit (OpenQASM)', 34 | type: 'string', 35 | normalize: true, 36 | }, 37 | }; 38 | 39 | exports.handler = argv => { 40 | logger.title(qiskit.version); 41 | logger.bold('\n\nWARNING: Partial implementation for now\n\n'); 42 | 43 | dbg('Starting, args', argv); 44 | 45 | const pathCode = path.resolve(process.cwd(), argv.circuit); 46 | const parser = new qiskit.qasm.Parser(); 47 | 48 | // TODO: "async" still not suported by yargs: 49 | // https://github.com/yargs/yargs/issues/510 50 | readFile(pathCode, 'utf8') 51 | .then(code => { 52 | try { 53 | logger.resultHead(); 54 | logger.json(parser.parse(code)); 55 | } catch (err) { 56 | logger.error('Parsing the circuit', err); 57 | process.exit(1); 58 | } 59 | }) 60 | .catch(err => { 61 | logger.error('Reading the circuit file', err); 62 | process.exit(1); 63 | }); 64 | }; 65 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/queue.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'queue [backend]'; 16 | 17 | exports.aliases = ['q']; 18 | 19 | exports.desc = 'Get the status of a backend queue'; 20 | 21 | exports.builder = { 22 | backend: { 23 | desc: 'Name of the backend to inspect', 24 | type: 'string', 25 | default: 'ibmqx4', 26 | }, 27 | }; 28 | 29 | exports.handler = argv => { 30 | logger.title(qiskit.version); 31 | 32 | global.qiskit.cloud 33 | .queues(argv.backend) 34 | .then(res => { 35 | logger.resultHead(); 36 | logger.json(res); 37 | }) 38 | .catch(err => { 39 | logger.error('Making the request', err); 40 | process.exit(1); 41 | }); 42 | }; 43 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/random.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'random [engine] [length] [format] [backend]'; 16 | 17 | exports.aliases = ['r']; 18 | 19 | exports.desc = 'Generate a true random number among 0 and 1'; 20 | 21 | exports.builder = { 22 | engine: { 23 | desc: 'Where to run the operation. Supported: "js", "ibm"', 24 | type: 'string', 25 | default: 'js', 26 | }, 27 | length: { 28 | desc: 29 | 'Number of random hex characters to ask for to the engine. ' + 30 | "As you can see in the doc referenced before each engine has different limit, they will throw in it's overpassed", 31 | type: 'number', 32 | default: 16, 33 | }, 34 | format: { 35 | desc: 'To ask for the result in a different format, supported ("hex")', 36 | type: 'string', 37 | default: null, 38 | }, 39 | backend: { 40 | desc: 'Name of the IBM backend to use (if any)', 41 | type: 'string', 42 | default: 'simulator', 43 | }, 44 | }; 45 | 46 | exports.handler = argv => { 47 | logger.title(qiskit.version); 48 | 49 | const opts = { 50 | engine: argv.engine || 'js', 51 | length: argv.length, 52 | format: argv.format, 53 | backend: argv.backend, 54 | }; 55 | 56 | if (argv.engine && argv.engine === 'ibm') { 57 | opts.custom = global.qiskit.cloud; 58 | } 59 | 60 | qiskit.algo 61 | .random(opts) 62 | .then(res => { 63 | logger.resultHead(); 64 | logger.json(res); 65 | }) 66 | .catch(err => { 67 | logger.error('Making the request', err); 68 | process.exit(1); 69 | }); 70 | }; 71 | -------------------------------------------------------------------------------- /packages/qiskit/bin/cmds/result.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qiskit = require('../..'); 13 | const logger = require('../lib/logger'); 14 | 15 | exports.command = 'result '; 16 | 17 | exports.aliases = ['re']; 18 | 19 | exports.desc = 20 | 'Get the result of a background job generated by an algorithm method. ' + 21 | 'The engine is ommited because IBM Q is the unique which uses background jobs for now.'; 22 | 23 | exports.builder = { 24 | jobId: { 25 | desc: 'Identifier of the job to get the result', 26 | type: 'string', 27 | }, 28 | }; 29 | 30 | exports.handler = argv => { 31 | logger.title(qiskit.version); 32 | 33 | qiskit.algo 34 | .result(argv.jobId, { custom: global.qiskit.cloud }) 35 | .then(res => { 36 | logger.resultHead(); 37 | logger.json(res); 38 | }) 39 | .catch(err => { 40 | logger.error('Making the request', err); 41 | process.exit(1); 42 | }); 43 | }; 44 | -------------------------------------------------------------------------------- /packages/qiskit/bin/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * @license 5 | * 6 | * Copyright (c) 2017, IBM. 7 | * 8 | * This source code is licensed under the Apache License, Version 2.0 found in 9 | * the LICENSE.txt file in the root directory of this source tree. 10 | */ 11 | 12 | 'use strict'; 13 | 14 | const yargs = require('yargs'); 15 | 16 | const qiskit = require('..'); 17 | const logger = require('./lib/logger'); 18 | const storage = require('./lib/storage'); 19 | 20 | // To share it among the different QE related commands. 21 | global.qiskit = { cloud: new qiskit.Cloud() }; 22 | 23 | Promise.all([storage.getItem('token'), storage.getItem('userId')]) 24 | .then(creds => { 25 | if (creds) { 26 | [global.qiskit.cloud.token, global.qiskit.cloud.userId] = creds; 27 | } 28 | 29 | // Starting the console cli. 30 | // eslint-disable-next-line no-unused-expressions 31 | yargs.commandDir('./cmds').demandCommand().argv; 32 | }) 33 | .catch(err => { 34 | logger.error('Looking for a long term token', err); 35 | process.exit(1); 36 | }); 37 | -------------------------------------------------------------------------------- /packages/qiskit/bin/lib/logger.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const clc = require('cli-color'); 13 | const prettyjson = require('prettyjson'); 14 | const emoji = require('node-emoji'); 15 | 16 | /* eslint-disable no-console */ 17 | 18 | module.exports.info = str => console.log(clc.xterm(63)(str)); 19 | 20 | module.exports.json = json => console.log(prettyjson.render(json)); 21 | 22 | module.exports.error = (str, err) => { 23 | console.error(clc.red(str)); 24 | if (err && err.stack) { 25 | console.error(clc.red(err.stack)); 26 | } 27 | }; 28 | 29 | module.exports.regular = str => console.log(str); 30 | 31 | module.exports.bold = str => console.log(clc.bold(str)); 32 | 33 | module.exports.title = version => { 34 | console.log(clc.bold.xterm(202)(`\n\tqiskit.js ${emoji.get('atom_symbol')}`)); 35 | console.log(clc.xterm(63)(`\t(v${version})\n`)); 36 | }; 37 | 38 | module.exports.time = label => console.time(clc.xterm(63)(label)); 39 | 40 | module.exports.timeEnd = label => console.timeEnd(clc.xterm(63)(label)); 41 | /* eslint-enable no-console */ 42 | 43 | module.exports.emoji = label => emoji.get(label); 44 | 45 | module.exports.resultHead = () => 46 | this.info(`\n${emoji.get('ok_hand')} Finised, result:`); 47 | -------------------------------------------------------------------------------- /packages/qiskit/bin/lib/storage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const path = require('path'); 13 | 14 | const storage = require('node-persist'); 15 | const homeOrTmp = require('home-or-tmp'); 16 | 17 | const logger = require('./logger'); 18 | const utils = require('./utils'); 19 | 20 | const dbg = utils.dbg(__filename); 21 | 22 | storage 23 | .init({ dir: path.resolve(homeOrTmp, '.qiskit') }) 24 | .then(() => dbg('Local storage init done')) 25 | .catch(err => { 26 | logger.error('Starting the persistent storage', err); 27 | process.exit(1); 28 | }); 29 | 30 | module.exports = storage; 31 | -------------------------------------------------------------------------------- /packages/qiskit/bin/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const utils = require('@qiskit/utils'); 13 | 14 | const pkgName = require('../../package.json').name; 15 | 16 | utils.dbg = fullPath => utils.debug(`${pkgName}:${utils.pathToTag(fullPath)}`); 17 | 18 | module.exports = utils; 19 | -------------------------------------------------------------------------------- /packages/qiskit/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const qasm = require('@qiskit/qasm'); 13 | const sim = require('@qiskit/sim'); 14 | const Cloud = require('@qiskit/cloud'); 15 | const utils = require('@qiskit/utils'); 16 | const algo = require('@qiskit/algo'); 17 | 18 | const { version } = require('./package'); 19 | 20 | module.exports = { 21 | version, 22 | qasm, 23 | sim, 24 | Cloud, 25 | utils, 26 | algo, 27 | }; 28 | -------------------------------------------------------------------------------- /packages/qiskit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qiskit", 3 | "version": "0.9.0", 4 | "description": "Quantum Information Science Kit meta-package", 5 | "author": { 6 | "name": "IBM RESEARCH", 7 | "url": "http://research.ibm.com" 8 | }, 9 | "homepage": "https://www.qiskit.org", 10 | "contributors": [ 11 | "https://github.com/Qiskit/qiskit-js/graphs/contributors" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/Qiskit/qiskit-js" 16 | }, 17 | "files": [ 18 | "bin", 19 | "index.js" 20 | ], 21 | "bin": { 22 | "qiskitjs": "./bin/index.js" 23 | }, 24 | "scripts": { 25 | "deps": "depcheck", 26 | "test": "mocha --recursive test --color" 27 | }, 28 | "keywords": [ 29 | "quantum", 30 | "computing", 31 | "experience", 32 | "information", 33 | "qasm", 34 | "openqasm", 35 | "simulator", 36 | "emulator", 37 | "compiler", 38 | "unroller", 39 | "algorithms", 40 | "qiskit", 41 | "command", 42 | "client", 43 | "shell", 44 | "IBM" 45 | ], 46 | "bugs": { 47 | "url": "https://github.com/Qiskit/qiskit-js/issues" 48 | }, 49 | "dependencies": { 50 | "@qiskit/algo": "^0.9.0", 51 | "@qiskit/cloud": "^0.9.0", 52 | "@qiskit/qasm": "^0.9.0", 53 | "@qiskit/sim": "^0.9.0", 54 | "@qiskit/utils": "^0.9.0", 55 | "cli-color": "^1.4.0", 56 | "home-or-tmp": "^3.0.0", 57 | "node-emoji": "^1.10.0", 58 | "node-persist": "^3.0.4", 59 | "prettyjson": "^1.2.1", 60 | "prompt": "^1.0.0", 61 | "yargs": "^13.2.4" 62 | }, 63 | "engines": { 64 | "node": ">=10" 65 | }, 66 | "license": "Apache-2.0", 67 | "publishConfig": { 68 | "access": "public" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/qiskit/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/qiskit/test/functional/bin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const path = require('path'); 13 | const assert = require('assert'); 14 | const exec = require('child_process').execSync; 15 | 16 | const binPath = path.resolve(__dirname, '../../bin/index.js'); 17 | const comm = `node ${binPath}`; 18 | const pkgInfo = require('../../package'); 19 | const utilsTest = require('../../../../utils-test'); 20 | 21 | const reGot0 = /Not enough non-option arguments: got 0/; 22 | const reNotSup = /Format not supported/; 23 | 24 | function assertComm(re, result) { 25 | assert.ok(re.test(utilsTest.strip(result.toString()).replace(/ /g, ''))); 26 | } 27 | 28 | describe('qiskit:bin', () => { 29 | it('should fail if no params', () => assert.throws(() => exec(comm), reGot0)); 30 | 31 | it('should work for "--version"', () => 32 | assertComm(new RegExp(pkgInfo.version), exec(`${comm} --version`))); 33 | 34 | it('should work for "--help"', () => 35 | assertComm(/parseParsethecircuittoourIR/, exec(`${comm} --help`))); 36 | 37 | it('should work for "parse" command', () => 38 | assertComm( 39 | /-\ntype:qubit\nidentifier:q\nnumber:3/, 40 | exec(`${comm} parse ../../circuits/example.qasm`), 41 | )); 42 | 43 | it('should fail for "parse" command without arguments', () => 44 | assert.throws(() => exec(`${comm} parse`), reGot0)); 45 | 46 | // TODO: Waiting to finish the new simulator implementation. 47 | it.skip('should work for "sim" command with unrolled circuits', () => { 48 | assertComm( 49 | /State\|psi>=U|0>:\[0.35355339059327384,0/, 50 | exec(`${comm} sim ../../circuits/unrolled/example.json`), 51 | ); 52 | }).timeout(5000); 53 | 54 | it.skip('should fail for "sim" command without arguments', () => 55 | assert.throws(() => exec(`${comm} sim`), reGot0)); 56 | 57 | it.skip('should fail for "sim" command with any other format', () => { 58 | assert.throws(() => exec(`${comm} sim whatever.png`), reNotSup); 59 | }); 60 | 61 | it('should fail for "job" command without arguments', () => 62 | assert.throws(() => exec(`${comm} job`), reGot0)); 63 | 64 | it('should fail for "circuit" command without arguments', () => 65 | assert.throws(() => exec(`${comm} circuit`), reGot0)); 66 | }); 67 | -------------------------------------------------------------------------------- /packages/qiskit/test/functional/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const assert = require('assert'); 13 | 14 | const qiskit = require('../..'); 15 | 16 | const pkgInfo = require('../../package'); 17 | const pkgInfoSim = require('../../../qiskit-sim/package'); 18 | 19 | describe('qiskit:api', () => { 20 | it('should include all documented items', () => 21 | assert.deepEqual(Object.keys(qiskit), [ 22 | 'version', 23 | 'qasm', 24 | 'sim', 25 | 'Cloud', 26 | 'utils', 27 | 'algo', 28 | ])); 29 | 30 | it('should return the the correct result for its methods', () => 31 | assert.equal(qiskit.version, pkgInfo.version)); 32 | 33 | // We only check one for convenience. 34 | it('should return the correct result for any item', () => 35 | assert.equal(qiskit.sim.version, pkgInfoSim.version)); 36 | }); 37 | -------------------------------------------------------------------------------- /utils-test/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * 4 | * Copyright (c) 2017, IBM. 5 | * 6 | * This source code is licensed under the Apache License, Version 2.0 found in 7 | * the LICENSE.txt file in the root directory of this source tree. 8 | */ 9 | 10 | 'use strict'; 11 | 12 | // TODO: Repeated code in qiskit bin, qiskit-utils package needed? 13 | const assert = require('assert'); 14 | 15 | /* eslint-disable import/no-extraneous-dependencies */ 16 | const shot = require('snap-shot-it'); 17 | const strip = require('strip-color'); 18 | /* eslint-enable import/no-extraneous-dependencies */ 19 | 20 | // A custom version of [assert.throws](https://nodejs.org/api/assert.html# 21 | // assert_assert_throws_block_error_message) with async (through promises) support. 22 | // 23 | // - `block` (function) - Piece of code (returning a promise) to be checked. 24 | // - `errRegex` (object) - Regular expresion to confirm the expected error. 25 | // 26 | // Ref: https://wietse.loves.engineering/testing-promises-with-mocha-90df8b7d2e35 27 | async function throwsAsync(block, errorRexp) { 28 | try { 29 | await block(); 30 | } catch (e) { 31 | // To be consistent with the Node.js "assert.throws" behavior we reuse it. 32 | if (errorRexp) { 33 | assert.throws(() => { 34 | throw e; 35 | }, errorRexp); 36 | } 37 | // We need this return because we're catching the thrown error, 38 | // if not, the next assert.fail would be reached when the regexp matches. 39 | return; 40 | } 41 | 42 | assert.fail('Missing expected exception'); 43 | } 44 | 45 | module.exports = { throwsAsync, shot, strip }; 46 | --------------------------------------------------------------------------------