...which sounds a LOT more complex than it is.  I don't care about 
simulation--there are great Python-based packages for that.  I don't even 
care about verification or optimization yet; I just want to generate a data 
structure that's exportable in, say, EDN that I can write a parser for in 
Python.

So... I'm dabbling in quantum computing, and the way these things work, 
loosely, is that you have a fairly small address space (Google's 
Bristlecone has 72 bits, and that's HUGE), and you basically apply "gates" 
(atomic operations) to one, two, or occasionally three bits at a time.  
That's basically it--you can have larger operations, but at the end of they 
day they get broken down into 1/2/3-qubit gates.

Right now the available kits use python to create these, and it just feels 
clunky... not even like writing assembler, but like writing Python code to 
write assembler, and there's no separation of data structure from execution 
environment.  I figure at the end of the day you're just making lists of 
operations; if only there was a language suited for list processing!  :)

Example: here's Python code for a "bell pair" (when measured, both bits are 
either 0 or 1), from ProjectQ, one of the Python libraries:

# The H operator is defined as an object elsewhere
# because ProjectQ mixes the construction of the quantum
# code with its execution:
# create a main compiler engine
eng = MainEngine()

# allocate one qubit
b1 = eng.allocate_qubit()
b2 = eng.allocate_qubit()

# put it in superposition
H | b1
CNOT | (b1, b2)

# measure
Measure | q1
Measure | q2

eng.flush()
# print the result:
print("Measured: {}{}".format(int(q1),int(q2)))


What I'd like to see is something more like

;; declare H to be a 1-bit gate and CNOT to be a 2-bit gate
;; note these don't have to DO anything here as long as they can
;; be interpreted in the Python backends
(defgate H 1)
(defgate CNOT 2)

(defq-fn bell-pair [b1 b2]
  (H b1)
  (CNOT b1 b2))

(defq-pgm run-bell-pair []
  (let [b1 (allocate-bit 1)   ;; variable of one qubit
         b2 (allocate-bit 1)]  ;; same
  (bell-pair b1 b2)
  (measure b1 b2))

...where gates behave like functions (so you can use partial, map, etc, 
like (map (partial CNOT 1) [b1 b2 b3])

And doing say (bell-pair 1 2) would spit out EDN

((:H 1)
 (:CNOT 1 2))

and (run-bell-pair) might parse everything, include extra data about the 
necessary machine, and reassign variables to allocated bits

{:machine {:bitsize 2} ; calculated because only two bits were allocated in 
all the subsidiary code
 :code ((:block {:name bell-pair 
                         :code (:H 0) (:CNOT 0 1) (:measure 0 1)}))}

That sort of thing (the ":block" idea is mostly to delineate "where you 
are" in the output program, and to group operations for display).  Then I 
could write a parser in Python for the simulators and such (or rewrite the 
Clojure code for Hylang, which is its own exercise, but I could use the 
Python libs directly then).  There are other things I'd like (allocate 
multi-bit variables, and apply gates to individual bits of those, like to 
have the idea of reusing bits once they're measured and done with, that 
sort of thing) but this is a start.

On the surface, this looks really easy--you're just generating and 
traversing data structures--but it's funny how hard I'm finding it because 
it's key that you can execute proper computational code within (to do 
things like determine angles for parameterized gates, apply gates in 
complex ways to sequences, etc).  

I created a defgate macro that generated function stubs for gates that 
created EDN for gates; that was easy.  But properly doing the "defq-fn" 
macro is eluding me.  I want it to return a list of the gates' data 
structures, but if I just eval the given form, I'll only get the last 
result and (do...) to get a sequence is tricky because we're mixing gates 
and clojure code.  I tried a solution where the generated "gate" functions 
would call an "emit" function which appended to a module-level variable, 
and that soooorta worked, but it's not elegant (and not threadsafe).

Ideally the defq-fn macro would create a function that returns a sequence 
of gates, one for every "gate function" executed in the execution of the 
function, but no other output (I may be making a specious distinction 
between defq-fn and defq-pgm, since I'd like to be able to allocate and 
"free" bits within qfns).

Aaaanyway, long story.  But what's the best/correct approach here?  I'm new 
to macros, but game to flail wildly.  Ideally any solution would be 
sorta-portable to Hylang (I'm doing the same exercise there and running 
into even stranger problems as for example "map" just returns a "map 
object" rather than simply being lazily evaluated, but I'm trying).

And yeah, for "real" QC applications there's a lot missing here, but one 
has to start somewhere :)
Vic

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/60cec71a-87fd-449d-934f-46460db72e9e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to