-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Eric Peterson <[email protected]> Co-authored-by: Peter Karalekas <[email protected]>
- Loading branch information
0 parents
commit 7823b02
Showing
33 changed files
with
6,540 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
name: main | ||
|
||
on: | ||
push: | ||
branches: [ master ] | ||
pull_request: | ||
branches: [ master ] | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Check out anatevka | ||
uses: actions/checkout@v2 | ||
with: | ||
path: anatevka | ||
- name: Initialize Lisp | ||
run: | | ||
sudo apt install sbcl | ||
curl -o /tmp/quicklisp.lisp "http://beta.quicklisp.org/quicklisp.lisp" | ||
sbcl --noinform --non-interactive \ | ||
--load /tmp/quicklisp.lisp \ | ||
--eval '(quicklisp-quickstart:install)' | ||
WD=$(pwd | xargs dirname) | ||
echo >> ~/.sbclrc | ||
echo '#-quicklisp(let ((i(merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname))))(when(probe-file i)(load i)))' >> ~/.sbclrc | ||
echo "#+quicklisp(push \"${WD}/\" ql:*local-project-directories*)" >> ~/.sbclrc | ||
rm -f /tmp/quicklisp.lisp | ||
- name: Run the test suite | ||
run: | | ||
# run the tests via the Makefile | ||
cd anatevka | ||
sbcl --version | ||
sbcl --noinform --non-interactive --eval '(ql:quickload "anatevka-tests")' | ||
make test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.fasl | ||
.DS_Store | ||
*~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Copyright © 2022 Eric Peterson, Peter Karalekas, and contributors | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
SBCL_BIN=sbcl | ||
SBCL_WORKSPACE?=2048 | ||
SBCL_OPTIONS=--noinform --no-userinit --no-sysinit --non-interactive | ||
SBCL=$(SBCL_BIN) --dynamic-space-size $(SBCL_WORKSPACE) $(SBCL_OPTIONS) | ||
|
||
# tell me where Quicklisp is | ||
ifeq ($(HOME), /github/home) | ||
# when running on GitHub Actions, use Docker filesystem location | ||
QUICKLISP_HOME=/root/quicklisp | ||
else | ||
QUICKLISP_HOME=$(HOME)/quicklisp | ||
endif | ||
QUICKLISP_SETUP=$(QUICKLISP_HOME)/setup.lisp | ||
|
||
# tell me where local projects are | ||
ifeq ($(HOME), /github/home) | ||
# when running on GitHub Actions, use Docker filesystem location | ||
QUICKLISP_PROJECTS=/src | ||
else | ||
QUICKLISP_PROJECTS=../ | ||
endif | ||
|
||
QUICKLISP=$(SBCL) --load $(QUICKLISP_SETUP) \ | ||
--eval '(push (truename ".") asdf:*central-registry*)' \ | ||
--eval "(push (truename \"$(QUICKLISP_PROJECTS)\") ql:*local-project-directories*)" | ||
|
||
.PHONY: test | ||
test: | ||
$(QUICKLISP) \ | ||
--eval "(ql:quickload :anatevka-tests)" \ | ||
--eval "(asdf:test-system :anatevka)" | ||
|
||
### | ||
### clean targets, borrowed from QVM | ||
### | ||
|
||
# Clean the executables | ||
clean: | ||
rm -f qvm qvm-ng build-output.log system-index.txt | ||
|
||
# Clean the Lisp cache, reindex local projects. | ||
clean-cache: | ||
@echo "Deleting $(LISP_CACHE)" | ||
$(QUICKLISP) \ | ||
--eval "(ql:register-local-projects)" | ||
rm -rf "$(LISP_CACHE)" | ||
|
||
clean-qvm-cache: | ||
@echo "Deleting $(QVM_LISP_CACHE)" | ||
$(QUICKLISP) \ | ||
--eval "(ql:register-local-projects)" | ||
rm -rf $(QVM_LISP_CACHE) | ||
|
||
clean-quicklisp: | ||
@echo "Cleaning up old projects in Quicklisp" | ||
$(QUICKLISP) \ | ||
--eval '(ql-dist:clean (ql-dist:dist "quicklisp"))' | ||
|
||
cleanall: clean clean-cache clean-quicklisp | ||
@echo "All cleaned and reindexed." | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# `anatevka` | ||
|
||
`anatevka` is a Common Lisp package which houses [a distributed variant of Edmonds's blossom algorithm](https://arxiv.org/abs/2210.14277) for producing minimum-weight perfect matchings, written in [`aether`](https://github.com/dtqec/aether)'s application layer. | ||
|
||
## Overview | ||
|
||
`anatevka` contains an executable description of a distributed solver for minimum-weight perfect matchings on graphs. | ||
The solver is written on top of [`aether`](https://github.com/dtqec/aether), so that one can simulate the algorithm running on large networks and infer the performance characteristics of such scenarios. | ||
The package is also implemented _extensibly_, so as to allow application-specific behaviors to be written into packages derived from this one. | ||
|
||
The original motivation for the development of this package was [Fowler's program](https://arxiv.org/abs/1307.1740) for using a distributed solver for minimum-weight perfect matching to perform quantum error correction. | ||
This package provides the first implementation of the core distributed solver, incompletely described by Fowler. | ||
|
||
## Installation | ||
|
||
`anatevka` is a Lisp package which relies on other Lisp packages. You'll need to: | ||
|
||
1. Install a Lisp environment. | ||
[Some convenient instructions](https://github.com/quil-lang/qvm/blob/master/doc/lisp-setup.md) for this can be found as part of the QVM Lisp package. | ||
2. This also depends on [`aether`](https://github.com/dtqec/aether), another Eigenware package. | ||
Install this software somewhere locally, where ASDF can find it, perhaps using [QuickLisp](http://quicklisp.org/). | ||
|
||
## Example | ||
|
||
In this section we consider an example instantiation of the solver inside of an `aether` simulation. | ||
To abbreviate the code examples, we assume we have imported the `anatevka` package. | ||
|
||
The behavior of the solver is guided by three classes: | ||
|
||
1. A `dryad` class which implements the interface in `dryad-api.lisp`. | ||
The `dryad` is responsible for creating the worker nodes which embody graph vertices and managing edge discovery. | ||
We provide an example implementation in `dryad.lisp` for a centralized `dryad` managing a fully-connected, weighted graph. | ||
2. A `blossom-node` class which enacts the individual steps in the blossom algorithm. | ||
We provide a stock implementation in `node.lisp`; users need only provide a subclass if they want to deviate from the standard behavior of the algorithm. | ||
3. An `id` class which is used to uniquely tag the vertices in the graph and from which the edge weight between any two vertices can be computed via `anatevka::vertex-vertex-distance`. | ||
The repository provides no such stock class; we will implement a version below with static edge weights. | ||
|
||
In our example, we will use the stock `dryad` and `blossom-node` implementations, which leaves only the `id` class to define. | ||
The following definition provides eight valid `demo-id` instances and a function which computes the edge weights between them: | ||
|
||
```lisp | ||
(defstruct demo-id | ||
"A wrapper for a vertex ID used in the Mathematica blossom demo." | ||
(value nil :type (integer 1 8))) | ||
(defmethod anatevka::vertex-vertex-distance ((id-v demo-id) (id-w demo-id)) | ||
(let ((v (demo-id-value id-v)) | ||
(w (demo-id-value id-w))) | ||
;; index into the following weighted adjacency matrix | ||
(aref #2A(( 0 40 52 50 46 70 36 46) | ||
(40 0 34 54 28 64 20 6) | ||
(52 34 0 28 34 24 2 30) | ||
(50 54 28 0 42 18 36 8) | ||
(46 28 34 42 0 14 80 22) | ||
(70 64 24 18 14 0 22 64) | ||
(36 20 2 36 80 22 0 80) | ||
(46 6 30 8 22 64 80 0)) | ||
(1- v) (1- w)))) | ||
``` | ||
|
||
**Note:** Given the example adjacency matrix provided, one possible minumum-weight perfect matching consists of the pairs (1, 2), (3, 7), (4, 8), and (5, 6), which altogether has weight 64. | ||
|
||
Having established the class which carries the graph definition, we wrap a solver in a simulation and invoke the simulation to extract a minimum-weight perfect matching: | ||
|
||
```lisp | ||
(let* ((simulation (make-simulation)) | ||
;; aether requires us to bind `*local-courier*' before spawning processes. | ||
(*local-courier* (make-courier :processing-clock-rate 300)) | ||
;; The edges discovered by the algorithm will be announced on this address. | ||
(match-address (register)) | ||
;; This process manages graph discovery. | ||
(dryad (spawn-process 'dryad | ||
:process-clock-rate 20 | ||
:debug? t | ||
:match-address match-address))) | ||
;; Set up the core simulation components: the network host and the dryad. | ||
(simulation-add-event simulation | ||
(make-event :callback *local-courier* :time 0)) | ||
(simulation-add-event simulation (make-event :callback dryad :time 0)) | ||
;; Prime the dryad with messages to spawn workers for the eight vertices. | ||
(loop :for j :from 1 :to 8 | ||
:for id := (make-demo-id :value j) | ||
:do (send-message (process-public-address dryad) | ||
(anatevka::make-message-sow :id id))) | ||
;; Run simulation until maximally matched (i.e., until the dryad terminates). | ||
(simulation-run simulation :canary (canary-process dryad)) | ||
;; Read out the match edges from the `match-address' mailbox. | ||
(labels ((drain-match-address (&optional acc) | ||
(receive-message (match-address message) | ||
(message-reap | ||
(drain-match-address (list* (message-reap-ids message) acc))) | ||
(otherwise | ||
acc)))) | ||
;; Calculate the weight of the matching. | ||
(loop :for (left right) :in (drain-match-address) | ||
:do (format t "~d --~02d-- ~d~%" | ||
(demo-id-value left) | ||
(vertex-vertex-distance left right) | ||
(demo-id-value right)) | ||
:sum (anatevka::vertex-vertex-distance left right)))) | ||
``` | ||
|
||
which prints | ||
|
||
``` | ||
8 -- 8-- 4 | ||
7 -- 2-- 3 | ||
6 --14-- 5 | ||
2 --40-- 1 | ||
``` | ||
|
||
and emits the return value `64`. | ||
|
||
## License | ||
|
||
`anatevka` is made available under the MIT license. | ||
See `LICENSE.md` in the source tree for more information. | ||
|
||
## See also | ||
|
||
+ [ArXiv preprint](https://arxiv.org/abs/2210.14277) | ||
+ [GitHub repository](https://github.com/dtqec/anatevka) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"1.0.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
;;;; anatevka-tests.asd | ||
|
||
(asdf:defsystem #:anatevka-tests | ||
:description "Regression tests for Anatevka." | ||
:author "Eric Peterson <[email protected]>, Peter Karalekas <[email protected]>" | ||
:depends-on (#:anatevka | ||
#:fiasco | ||
#:uiop | ||
#:closer-mop | ||
) | ||
:perform (asdf:test-op (o s) | ||
(uiop:symbol-call ':anatevka-tests | ||
'#:run-anatevka-tests)) | ||
:pathname "tests/" | ||
:serial t | ||
:components ((:file "package") | ||
(:file "suite") | ||
(:file "node") | ||
(:module "operations" | ||
:serial t | ||
:components ((:file "graft") | ||
(:file "augment") | ||
(:file "expand") | ||
(:file "contract") | ||
(:file "multireweight") | ||
(:file "reweight"))) | ||
(:file "blossom"))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
;;;; anatevka.asd | ||
;;;; | ||
;;;; Author: Eric Peterson, Peter Karalekas | ||
|
||
(asdf:defsystem #:anatevka | ||
:description "A distributed blossom algorithm for minimum-weight perfect matching." | ||
:author "Eric Peterson <[email protected]>, Peter Karalekas <[email protected]>" | ||
:version (:read-file-form "VERSION.txt") | ||
:pathname "src/" | ||
:depends-on (#:alexandria | ||
(:version #:aether "1.1.0") | ||
) | ||
:in-order-to ((asdf:test-op (asdf:test-op #:anatevka-tests))) | ||
:around-compile (lambda (compile) | ||
(let (#+sbcl(sb-ext:*derive-function-types* t)) | ||
(funcall compile))) | ||
:serial t | ||
:components ((:file "package") | ||
(:file "utilities") | ||
(:file "logger") | ||
(:file "dryad-api") | ||
(:file "node") | ||
(:file "supervisor") | ||
(:file "lock") | ||
(:module "operations" | ||
:serial t | ||
:components ((:file "scan") | ||
(:file "graft") | ||
(:file "augment") | ||
(:file "expand") | ||
(:file "contract") | ||
(:file "multireweight") | ||
(:file "reweight"))) | ||
(:file "dryad"))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
;;;; dryad-api.lisp | ||
;;;; | ||
;;;; Specifies the message types used to communicate with the DRYAD. | ||
;;;; See dryad.lisp and matchmaker.lisp for information on the participants. | ||
|
||
(in-package #:anatevka) | ||
|
||
;;; messages between the dryad and the external world | ||
|
||
(defstruct (message-sow (:include message)) | ||
"Instructs a `DRYAD' to inject a new vertex with the indicated id." | ||
(id nil :type t)) | ||
|
||
(defstruct (message-reap (:include message)) | ||
"Reported by a `DRYAD' to its `MATCH-ADDRESS' with a pair of IDs that participate in the calculated matching." | ||
(ids nil :type list)) | ||
|
||
;;; messages between the dryad and its managed blossoms | ||
|
||
(defstruct (message-discover (:include message)) | ||
"Sent from a blossom process to a `DRYAD' to query for a list of other blossom processes to which it should send PINGs." | ||
(address nil :type address) | ||
(id nil :type t) | ||
(internal-weight nil :type real) ; NOTE: a little surprised that this isn't (REAL 0) | ||
(repeat? nil :type boolean)) | ||
|
||
(defstruct (message-discovery (:include message)) | ||
"The response to a DISCOVER message. | ||
CHANNELS-TO-TRY: The addresses to send PINGs to." | ||
(channels-to-try nil :type list)) | ||
|
||
(defstruct (message-wilt (:include message)) | ||
"An instruction to a `BLOSSOM-NODE' to cease operation as a process.") | ||
|
||
(defstruct (message-sprout (:include message)) | ||
"Whenever a vertex participates in an augmentation, we are guaranteed that it has been assigned a match (possibly after any parent blossom undergoes expansion). Upon augmentation, it sends this message to the DRYAD to indicate that it no longer need consider this vertex to be \"live\"." | ||
(address nil :type address)) | ||
|
||
;; NOTE: This message is essentially unused in the reference implementation, but it can be useful when implementing an online solver. | ||
(defstruct (message-wilting (:include message)) | ||
"When a `BLOSSOM-NODE' wilts, it notifies its parent `DRYAD' to remove it from consideration." | ||
(address nil :type address)) |
Oops, something went wrong.