The flows in Racket Qi can be viewed as stream functions if inputs and outputs are streams. We call them stream circuits; in some literature, they are also referred to as signal flow graphs. Qi-circuit is a domain specific language to allow convenient creating such circuits.
A large circuit can be constructed by combining small circuits. Qi-circuit currently provides 6 basic circuits:
-
(c-add op)
Adder circuit. The
op
is a binary or multiple operator that can be+
or*
. -
(c-mul x)
Multiplier circuit scales the input stream by x times.
-
(c-convo s1 s2)
Convolution circuit.
-
(c-reg init)
Register circuit can be viewed as consisting of a one-place memory cell that initially contains the value
init
. -
c-->
Read as "followed by". Let
e
andf
are streams, the(c--> e f)
is a stream whose sequence is(e0 f1 f2 ...)
. -
(c-loop sf)
Feedback loop circuit
-
(c-loop-gen sf)
Feedback loop circuit (no need input)
-
(c-switch args)
The syntax is the same as switch, but based on stream.
Although any Qi flow can be viewed a circuit as long as the inputs and outputs are streams, it's better to think of the inputs and outputs as signals, at time moments 0, 1, 2, ... For example:
The
Moreover, even though Qi-circuit is a purely functional programming language (i.e. no side effect), it's better to pretend that the circuits have memory. For example:
The register starts its activity, at time moment 0, by outputting its value 0 at its output end, while it simultaneously inputs the value
To effectively utilize Qi-circuit, there are two considerations:
- Most known circuits are not written in Qi-circuit syntax. Typically, for ease of writing, they incorporate shorthands or "sugars" to streamline circuits. As a result, when constructing circuits with Qi-circuit, it is necessary to translate those circuits into Qi-circuit compatible equivalent circuits.
- Handling circuits with feedback loops, especially in a strict programming language such as Racket, is a challenge. The solution is still translating those circuits into equivalent circuits.
Note that equivalent circuits might look very different from the original circuits! The following will illustrate the two considerations through some concrete examples.
- Sum
- Integral
- Factorial
- Fibonacci, Rabbit Farming
- Solving ODE 1
- Solving ODE 2
- Catalan numbers
- Raising edge, MinMax Bistable, Counter
- Add Clock
- Can work with multiple recursive variables in
c-loop
at the moment?- Try another version of Flip-flop in Arrow SF
- Multiple streams vs One stream of values (with zip, unzip)
- The former is Qi-circuit
- The latter is Arrow SF (need lazy pattern matching for
values
?) - Multiplex in one stream?
- The current circuit is not conducive to modularization because Qi is strict in Racket.
- Try
#lang lazy
(need lazy pattern matching forvalues
?) - Try rewriting diagram in a macro expansion pass.
- Try
- Asynchronous Qi-circuit
- Synchronous Qi-circuit with delta time.
- More examples (e.g. FRP)