Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uploaded files expected to make Qiskit software configured to be published through Open Horizon Services. #3

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
64 changes: 64 additions & 0 deletions Dockerfile.amd64
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
FROM python:3.7-buster
RUN apt update
RUN apt install -y cmake libatlas-base-dev git build-essential p7zip-full curl
RUN pip3 install --upgrade pip

# check
RUN python --version
RUN pip --version
RUN curl --version

WORKDIR /

# retworkx
RUN pip install setuptools-rust
RUN curl -o /get_rustup.sh -s https://sh.rustup.rs
RUN sh /get_rustup.sh -y
RUN . ~/.cargo/env && pip install --prefer-binary retworkx

# libcint
RUN git clone https://github.com/sunqm/libcint.git
RUN mkdir -p /libcint/build
RUN cd /libcint/build && cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/ ..
RUN cd /libcint/build && make install

# cython
RUN pip install --upgrade setuptools wheel cython

# pyscf
#RUN pip install --upgrade pyscf
RUN git clone https://github.com/sunqm/pyscf
RUN mkdir /pyscf/pyscf/lib/build
RUN cd /pyscf/pyscf/lib/build && cmake ..
RUN cd /pyscf/pyscf/lib/build && make

# scipy prereq
RUN apt install -y gfortran

#qiskit
RUN pip install --prefer-binary qiskit-terra==0.16.*
RUN pip install --prefer-binary qiskit-ignis==0.5.*
RUN . ~/.cargo/env && pip install --prefer-binary qiskit-ibmq-provider==0.11.*
RUN apt install -y libhdf5-dev
RUN pip install --prefer-binary qiskit-aqua==0.8.*
RUN pip install --prefer-binary qiskit-aer==0.7.*
RUN pip install --prefer-binary 'qiskit[visualization]==0.23.*'

# check
RUN pip list | grep qiskit

# jupyter
RUN pip install jupyter

# jupyter (run as non-root user under tini)
RUN mkdir /.local
RUN chmod 777 /.local
RUN mkdir /.mpl
RUN chmod 777 /.mpl
RUN mkdir /jupyter
RUN chmod 777 /jupyter
RUN chown 10001:10001 /jupyter
USER 10001
WORKDIR /jupyter
RUN curl -sSL https://raw.githubusercontent.com/JavaFXpert/qiskit4devs-workshop-notebooks/master/quantum_not_gate_qiskit.ipynb -o /jupyter/example.ipynb
CMD cd /jupyter && MPLCONFIGDIR=/.mpl /usr/local/bin/jupyter notebook --no-browser --ip=* --port 8888
64 changes: 64 additions & 0 deletions Dockerfile.arm32
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
FROM arm32v7/python:3.7-buster
RUN apt update
RUN apt install -y cmake libatlas-base-dev git build-essential p7zip-full curl
RUN pip3 install --upgrade pip

# check
RUN python --version
RUN pip --version
RUN curl --version

WORKDIR /

# retworkx
RUN pip install setuptools-rust
RUN curl -o /get_rustup.sh -s https://sh.rustup.rs
RUN sh /get_rustup.sh -y
RUN . ~/.cargo/env && pip install --prefer-binary retworkx

# libcint
RUN git clone https://github.com/sunqm/libcint.git
RUN mkdir -p /libcint/build
RUN cd /libcint/build && cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/ ..
RUN cd /libcint/build && make install

# cython
RUN pip install --upgrade setuptools wheel cython

# pyscf
#RUN pip install --upgrade pyscf
RUN git clone https://github.com/sunqm/pyscf
RUN mkdir /pyscf/pyscf/lib/build
RUN cd /pyscf/pyscf/lib/build && cmake ..
RUN cd /pyscf/pyscf/lib/build && make

# scipy prereq
RUN apt install -y gfortran

#qiskit
RUN pip install --prefer-binary qiskit-terra==0.16.*
RUN pip install --prefer-binary qiskit-ignis==0.5.*
RUN . ~/.cargo/env && pip install --prefer-binary qiskit-ibmq-provider==0.11.*
RUN apt install -y libhdf5-dev
RUN pip install --prefer-binary qiskit-aqua==0.8.*
RUN pip install --prefer-binary qiskit-aer==0.7.*
RUN pip install --prefer-binary 'qiskit[visualization]==0.23.*'

# check
RUN pip list | grep qiskit

# jupyter
RUN pip install jupyter

# jupyter (run as non-root user under tini)
RUN mkdir /.local
RUN chmod 777 /.local
RUN mkdir /.mpl
RUN chmod 777 /.mpl
RUN mkdir /jupyter
RUN chmod 777 /jupyter
RUN chown 10001:10001 /jupyter
USER 10001
WORKDIR /jupyter
RUN curl -sSL https://raw.githubusercontent.com/JavaFXpert/qiskit4devs-workshop-notebooks/master/quantum_not_gate_qiskit.ipynb -o /jupyter/example.ipynb
CMD cd /jupyter && MPLCONFIGDIR=/.mpl /usr/local/bin/jupyter notebook --no-browser --ip=* --port 8888
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 Mega Mosquito

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
71 changes: 71 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
all: run

# Set these to your own values first
JUPYTER_TOKEN=secr3t
DOCKERHUB_ID=ibmosquito
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tahira-tariq just for the sake of consistence could you change this to DOCKER_HUB_ID=ibmosquito? I might have let some of these slip by accidentally but we more broadly use DOCKER_HUB_ID in the other services

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tahira-tariq I actually just realized the way that's written DOCKER_HUB_ID can't be overwritten at all ... can you change it to DOCKER_HUB_ID ?= ibmosquito similar to how it is in web-helloworld-python

https://github.com/open-horizon-services/web-helloworld-python/blob/main/Makefile#L3

SERVICE_NAME ?= service-qiskit
SERVICE_VERSION ?= 1.0.0
PATTERN_NAME ?= pattern-service-qiskit

ARCH=$(shell uname -m)
ifeq ($(ARCH), armv7l)
ARCH=arm32
else ifeq($(ARCH), x86_64)
ARCH=amd64
else
ARCH=unknown
endif

# Leave blank for open DockerHub containers
# CONTAINER_CREDS:=-r "registry.wherever.com:myid:mypw"
CONTAINER_CREDS ?=

default: build run

build:
docker build -t $(DOCKERHUB_ID)/qiskit_$(ARCH):1.0.0 -f Dockerfile.$(ARCH) .

dev: build
-docker rm -f qiskit 2>/dev/null
docker run -it -e JUPYTER_TOKEN=$(JUPYTER_TOKEN) -p 8888:8888 --name qiskit $(DOCKERHUB_ID)/qiskit_$(ARCH):1.0.0 /bin/bash

run:
-docker rm -f qiskit 2>/dev/null
docker run -d -e JUPYTER_TOKEN=$(JUPYTER_TOKEN) -p 8888:8888 --restart unless-stopped --name qiskit $(DOCKERHUB_ID)/qiskit_$(ARCH):1.0.0

test:
@curl -sS http://127.0.0.1:8888

push:
docker push $(DOCKERHUB_ID)/qiskit_$(ARCH):1.0.0

check:
@echo "Point your browser to: \"http://localhost:8888/\""

publish-service:
@ARCH=$(ARCH) \
SERVICE_NAME="$(SERVICE_NAME)" \
SERVICE_VERSION="$(SERVICE_VERSION)"\
SERVICE_CONTAINER="$(DOCKER_HUB_ID)/$(SERVICE_NAME):$(SERVICE_VERSION)" \
hzn exchange service publish -O $(CONTAINER_CREDS) -f service.json --pull-image

publish-pattern:
@ARCH=$(ARCH) \
SERVICE_NAME="$(SERVICE_NAME)" \
SERVICE_VERSION="$(SERVICE_VERSION)"\
PATTERN_NAME="$(PATTERN_NAME)" \
hzn exchange pattern publish -f pattern.json

stop:
@docker rm -f ${SERVICE_NAME} >/dev/null 2>&1 || :

clean:
@docker rmi -f $(DOCKER_HUB_ID)/$(SERVICE_NAME):$(SERVICE_VERSION) >/dev/null 2>&1 || :

agent-run: agent-stop
@hzn register --pattern "${HZN_ORG_ID}/$(PATTERN_NAME)"

agent-stop:
@hzn unregister -f

.PHONY: build dev run push publish-service publish-pattern test stop clean agent-run agent-stop
Binary file added Mini-Q.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
98 changes: 97 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,97 @@
# service-qiskit
# service-qiskit

This is an Open Horizon services configuration to deploy a docker container with QISKIT and Jupyter for Raspberry Pi.

QISKIT is both a quantum simulator and a tool that simplifies interfacing with IBM's quantum computing services in the IBM cloud. The Quantum Experience link below will guide you through the latter if you are interested in using the real thing!

There's a blog article to go along with this repo, here:
[https://darlingevil.com/your-own-quantum-computer/](https://darlingevil.com/your-own-quantum-computer/)

This container was built to run on a Raspberry Pi 4B with 2GB RAM (with Raspberry Pi OS 10, buster). It should work on any Raspberry Pi model 2, 3, or 4, although you may need to expland swap space on the smaller machines as described below. It should also work on any 64-bit x86 host with Docker installed.

## Prerequisites

You need to install to use this container is docker. You can install docker on a Raspberry Pi with this one command:

```
curl -sSL https://get.docker.com | sh
```

When done, I recommend running this command so the pi user can use docker withut sudo:

```
sudo usermod -aG docker pi
```

After executing that command, exit your shell and open a new shell. In that new shell and all subsequent shells you will be able to run `docker` commands without `sudo`. E.g., try this:

```
docker ps
```

## To build this container

NOTE: You need a little more than 2GB of RAM to build the docker container (about 3.4GB I think). Note also that this extra memory is not needed to **run** the container, only to **build** it. A 4GB or 8GB Pi therefore won't need this step so don't bother with it. However, since I am using a 2GB Raspberry Pi 4B, I increased the swap space with these commands:

```
sudo sed -i 's/CONF_SWAPSIZE=100/CONF_SWAPSIZE=1024/' /etc/dphys-swapfile
sudo /etc/init.d/dphys-swapfile stop
sudo /etc/init.d/dphys-swapfile start
```

Once you have that sorted out, these are the build steps:

1. Edit the Makefile to set your DockerHub ID in `DOCKERHUB_ID`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is the only other mention of DOCKERHUB_ID outside of the Makefile


2. Edit the Makefile to set the `JUPYTER_TOKEN`. This is the token you will use to login to the Jupyter Notebook created by this container. So keep it secret. Keep it safe. :-)

3. Run `make build`. You should expect this to take a very long time. On my little Pi4B/2GB it took me more than 6.5 hours to run `make build`. Notably, the file, `lda_c_pk09.c.o` alone takes something like 30 minutes to build (and it also happens to be the first one, perhaps the only one, that causes memory to run out with just 2GB of RAM and the default 100MB of swap). It builds much faster on an Intel i7 CPU.

4. Optionally you can push your container image to DockerHub so you don't ever have to build it again:

```
make push
```

## To run the resulting container

Once it is built, it starts up very quickly from then onward.

```
make run
```

## To use the container

Point your favorite browser at `<raspberry-pi-address>:8888/`. Enter the `JUPYTER_TOKEN` value you set in the Makefile, and you will see the familiar Jupyter Notebooks interface. I installed just one example notebook, `quantum_not_gate_qiskit.ipynb`. You can select it and run through it to verify everything is working. To create your own notebook, pull down the "New" menu at the top right, and select "Python 3".

## To learn more

This YouTube video gives a brief QISKIT primer:
[https://www.youtube.com/watch?v=V3hXSftZuoc](https://www.youtube.com/watch?v=V3hXSftZuoc)

The quantum NOT gate example from this set of guided exercises:
[https://github.com/JavaFXpert/qiskit4devs-workshop-notebooks](https://github.com/JavaFXpert/qiskit4devs-workshop-notebooks)

The IBM Quantum Experience getting started guide:
[https://quantum-computing.ibm.com/docs/](https://quantum-computing.ibm.com/docs/)

The official QISKIT documentation:
[https://qiskit.org/documentation/](https://qiskit.org/documentation/)

## Advanced details

### All Makefile targets

- `init` - mostly used for operator services to create the scaffolding of a new operator, or any form of code generation required to build
- `build` - build the container
- `dev` - open a shell in the container for development, with source dir mounted
- `run` - run container locally
- `stop` - stop and remove the container
- `agent-run` - deploy the container to your edge node using the agent
- `agent-stop` - stop the container running from `agent-run`
- `test` - assumes container is running
- `push` - to docker compliant registry
- `publish-service` - verify and publish the service
- `publish-pattern` - publish the pattern using the properties defined in the `pattern.json` file
- `clean` - calls stop and also removes the container image
2 changes: 2 additions & 0 deletions horizon/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode
**/.vscode
26 changes: 26 additions & 0 deletions horizon/deployment.policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"label": "$SERVICE_NAME Deployment Policy", /* Deployment policy label. */
"description": "Policy to auto deploy $SERVICE_NAME", /* Deployment policy description. */
"service": {
"name": "$SERVICE_NAME", /* The name of the service. */
"org": "$SERVICE_ORG_ID", /* The org of the service. */
"arch": "*", /* Set to '*' to use services of any hardware architecture. */
"serviceVersions": [ /* A list of service versions. */
{
"version": "$SERVICE_VERSION",
"priority":{}
}
]
},
"properties": [ /* A list of policy properties that describe the service being deployed. */
{
"name": "prop1",
"value": "value1"
}
],
"constraints": [
"purpose == SmartAg"
],
"userInput": [],
"secretBinding": []
}
26 changes: 26 additions & 0 deletions horizon/node.policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"properties": [ /* A list of policy properties that describe the object. */
/* It applies to both deployment and node management.*/
/* It usually containts the built-in node properties.*/
{
"name": "purpose",
"value": "SmartAg"
}
],
"constraints": [],
"deployment": { /* Policies that are used for deployment only. */
"properties": [ /* A list of policy properties for deployment. */
/* It overwrites the properties with the same name on the top level.*/
{
"name": "purpose",
"value": "SmartAg"
}
],
"constraints": []
},
"management": { /* Policies that are used for node management only. */
"properties": [],
"constraints": []
}
}

Loading