diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 09fb0c371ec331db74fb0194bd182594d91b9a30..0000000000000000000000000000000000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,20 +0,0 @@ -stages: - - build - - test - - deploy - -build: - stage: build - script: - - docker build -t myproject . - -test: - stage: test - script: - - docker run myproject pytest - - script: - - echo "Deploying the application..." - # Add deployment scripts here - - scp docker-compose.yml $DEPLOY_USER@$DEPLOY_SERVER:/path/to/deployment - - ssh $DEPLOY_USER@$DEPLOY_SERVER 'docker-compose down && docker-compose up -d' diff --git a/README.md b/README.md index 534cb06053e7fc7b8725455d42045a02a2d5f5ad..2c713280234490c3e1d3d5b5bc79a122b771aeaf 100644 --- a/README.md +++ b/README.md @@ -15,18 +15,17 @@ All folders are isolated projects. `cd` into the folder to run/build them. 1. Install [python](https://www.python.org/downloads/) (version 3.11.5) 2. Install [poetry](https://python-poetry.org/docs/#installation) (version 1.7.1) 3. Install [docker](https://docs.docker.com/engine/install/). If you want to run docker as non-root user then you need to add it to the docker group (see [documentation](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)). -4. We are storing Docker images at GitLab's integrated container registry by running: - - docker login git.imp.fu-berlin.de:5000 -u <GITLAB_USERNAME> -p <TOKEN> -*Some Project Access Tokens are available and will be provided to members.* - -5. From the root directory of this repo, run +4. From the root directory of this repo, run make init #### Do this happily ever after - +1. Start a (new) shell and activate the virtual environment poetry shell +2. We are storing Docker images at GitLab's integrated container registry by running: + + docker login git.imp.fu-berlin.de:5000 -u <GITLAB_USERNAME> -p <TOKEN> +*Some Project Access Tokens are available and will be provided to members.* ## Local development ### jobs @@ -46,8 +45,13 @@ For live experience (meaning you enter the container), run: If you change code in `src`, you need to rebuild the image with `bash build/build_image.sh`. The `src` folder can also be mounted in the image, but the assumption is that life is already difficult as it is... -### tasks +### tasks (! Under construction !) Tasks are python scripts that can spawn jobs which run in docker containers. Before calling a task, make sure you have built the related job-image. - python -B src/a-task.py local --config=docker.yaml --IN0 demo-inputs/system.json --OUT /tmp/test-a-task \ No newline at end of file + python -B src/a_task.py local --config=docker.yaml --IN0 demo-inputs/system.json --OUT /tmp/test-a-task + +##### TODO for jung +- [] Figure out `docker-compose` and `MinIO` to transfer docker images from `jobs` to `tasks` +- [] Setup CI/CD pipeline with `.gitlab-ci.yml` (File removed for the time being) +- [] Deploy where? (pypi or docker hub or GitLab package registry) \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5d6a5422810efdeeaa55244f6b1f1c1800c0d9ab 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -0,0 +1,18 @@ +version: '3.4' +services: + minio: + image: minio/minio + container_name: minio-s3 + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + ports: + - '9000:9000' + - '9001:9001' + command: server /data --console-address ":9001" + volumes: + - minio_data:/data + +# let docker handle persistence of the data directory +volumes: + minio_data: {} \ No newline at end of file diff --git a/jobs/src/a_job.py b/jobs/src/a_job.py index 6445a2c91007c1d48e90c71dcf46f370631aad27..e07abb83f00f815e0323f342eee2edad63c0be52 100644 --- a/jobs/src/a_job.py +++ b/jobs/src/a_job.py @@ -4,5 +4,25 @@ Just some toy code for demonstration import numpy as np -def id_func(x: np.ndarray) -> np.ndarray: - return x * np.ones(x.shape) +def sigma_x() -> np.ndarray: + """ + Pauli gate X (or NOT gate) + """ + + return np.array([[0, 1], [1, 0]]) + + +def sigma_y() -> np.ndarray: + """ + Pauli gate Y + """ + + return np.array([[0, -1j], [1j, 0]]) + + +def sigma_z() -> np.ndarray: + """ + Pauli gate Z + """ + + return np.array([[1, 0], [0, -1]]) diff --git a/jobs/unittests/test_a_job.py b/jobs/unittests/test_a_job.py index 519f3c2fe80d0960dff38769c731b08aa5ff2768..83b0b3b721a5dab962750c50b44fe82a86275cf6 100644 --- a/jobs/unittests/test_a_job.py +++ b/jobs/unittests/test_a_job.py @@ -3,14 +3,39 @@ import unittest import numpy as np -from src.a_job import id_func +from src.a_job import sigma_x, sigma_y, sigma_z logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) class AJobTest(unittest.TestCase): def test_a_job(self): - a_vector = np.ndarray([1, 2, 3]) - self.assertEqual(id_func(a_vector), a_vector) - logger.info("Test passes") + """ + Test functionalities of Pauli gates on single qubits + """ + qubit_0 = np.array([1, 0]) + qubit_1 = np.array([0, 1]) + + # ensure input is a single qubit + self.assertTrue(qubit_0.shape[0] == 2) + self.assertTrue(qubit_1.shape[0] == 2) + + # test Pauli gate X + self.assertTrue(np.array_equal(np.dot(sigma_x(), qubit_0), qubit_1)) + self.assertTrue(np.array_equal(np.dot(sigma_x(), qubit_1), qubit_0)) + + # test Pauli gate Y + self.assertTrue(np.array_equal(np.dot(sigma_y(), qubit_0), 1j * qubit_1)) + self.assertTrue(np.array_equal(np.dot(sigma_y(), qubit_1), -1j * qubit_0)) + + # test Pauli gate Z + self.assertTrue(np.array_equal(np.dot(sigma_z(), qubit_0), qubit_0)) + self.assertTrue(np.array_equal(np.dot(sigma_z(), qubit_1), -qubit_1)) + + logger.info("Logging for fun!") + + +if __name__ == '__main__': + unittest.main() diff --git a/tasks/docker.yaml b/tasks/docker.yaml index b8d7412984e8f23c93d9d8c9891c56d1f4a0a7db..63076dceffda35fd549e8dae323130184db0e57e 100644 --- a/tasks/docker.yaml +++ b/tasks/docker.yaml @@ -1,5 +1,5 @@ backend: - name: docker + name: docker-dev kind: docker release: local transport: @@ -7,10 +7,25 @@ backend: kind: s3 url: s3+http://minioadmin:minioadmin@127.0.0.1:9000/test remoteUrl: s3+http://minioadmin:minioadmin@127.0.0.1:9000/test + imageSpecs: + "git.imp.fu-berlin.de:5000/comp-sci-project:local": + network_mode: host + volumes: + ../jobs/src: + bind: /usr/src/app/src + mode: ro defaultSpecs: network_mode: host maxCpu: 4 - environment: - NUMPROCS: 3 # no cpu+1 + +plugins: + - kind: logging + - kind: resources + - kind: metrics + name: honeycomb + host: https://api.honeycomb.io + apiKey: 1X7YfLO8iH3zevALRjxL5F + dataset: honeycomb-python-example + - kind: storage numJobs: 3 diff --git a/tasks/integration-tests/test_a_task.py b/tasks/integration-tests/test_a_task.py index bb56fc0f19fe12154b54a43152dd30a7ec102f8e..93c36b9915a1fb8a3d677b4c80101c326753adcf 100644 --- a/tasks/integration-tests/test_a_task.py +++ b/tasks/integration-tests/test_a_task.py @@ -1,2 +1,43 @@ -class TestATask: - pass +import logging +import unittest + +import numpy as np + +from src.a_task import swap_gate + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) + + +class ATaskTest(unittest.TestCase): + + def test_a_task(self): + """ + Test functionalities of swap gate on 2-qubits + """ + + qubit_0 = np.array([1, 0]) + qubit_1 = np.array([0, 1]) + + qubit_00 = np.kron(qubit_0, qubit_0) + qubit_11 = np.kron(qubit_1, qubit_1) + qubit_01 = np.kron(qubit_0, qubit_1) + qubit_10 = np.kron(qubit_1, qubit_0) + + # ensure input is a 2-qubit + self.assertTrue(qubit_00.shape[0] == 4) + self.assertTrue(qubit_01.shape[0] == 4) + self.assertTrue(qubit_10.shape[0] == 4) + self.assertTrue(qubit_11.shape[0] == 4) + + self.assertTrue(np.array_equal(np.dot(swap_gate(), qubit_00), qubit_00)) + self.assertTrue(np.array_equal(np.dot(swap_gate(), qubit_11), qubit_11)) + + self.assertTrue(np.array_equal(np.dot(swap_gate(), qubit_01), qubit_10)) + self.assertTrue(np.array_equal(np.dot(swap_gate(), qubit_10), qubit_01)) + + logger.info("Logging for fun!") + + +if __name__ == '__main__': + unittest.main() diff --git a/tasks/src/a-task.py b/tasks/src/a-task.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/tasks/src/a_task.py b/tasks/src/a_task.py new file mode 100644 index 0000000000000000000000000000000000000000..7a53867f8638f139220c922834d9baa02a370b0f --- /dev/null +++ b/tasks/src/a_task.py @@ -0,0 +1,16 @@ +""" +This module implements the SWAP gate using the Pauli gates +Example: + python -B src/a_task.py local --config=docker-dev.yaml --IN0 demo-inputs/a_2_qubit.txt --OUT /tmp/test-a-task +""" + +import numpy as np + +from jobs.src.a_job import sigma_x, sigma_y, sigma_z + + +def swap_gate() -> np.ndarray: + + swap_matrix = (np.kron(np.identity(2), np.identity(2)) + np.kron(sigma_x(), sigma_x()) + + np.kron(sigma_y(), sigma_y()) + np.kron(sigma_z(), sigma_z())) + return swap_matrix