For certain circuits that are instances of the SeriesProduct class, applying feedback spawns an infinite loop. Here's sort of a minimum non-working example:
Before feedback, the circuit looks like this:
Applying feedback should thus be as simple as moving the phase shift over to the right. Instead, the program loops indefinitely.
The offending cycle looks something like this: SeriesProduct.feedback calls SeriesProduct._feedback calls Feedback.create calls super().create (which dispatches via Operation to Expression.create, but with cls bound to Feedback) calls match_replace (as one of the simplifications on line 214 in abstract_algebra.py) calls a lambda defined in Feedback._rules calls SeriesProduct.feedback, and the game is on...
The bug only appears in somewhat special circumstances. In the example above, the call to toSLH is essential; if left out, such that the beamsplitter and cavity remain separate components in the definition of the circuit, no infinite loop appears. It also seems like internal degrees of freedom are required; for example, if the single-port cavity is replaced by a phase shift, everything works as expected. Finally, if toSLH is called on the full circuit before applying feedback, i.e., circuit.toSLH().feedback(), the infinite loop is avoided (not too surprising, since now feedback is called on an SLH object instead of a SeriesProduct object).
For certain circuits that are instances of the
SeriesProduct
class, applying feedback spawns an infinite loop. Here's sort of a minimum non-working example:Before feedback, the circuit looks like this: Applying feedback should thus be as simple as moving the phase shift over to the right. Instead, the program loops indefinitely.
The offending cycle looks something like this:
SeriesProduct.feedback
callsSeriesProduct._feedback
callsFeedback.create
callssuper().create
(which dispatches viaOperation
toExpression.create
, but withcls
bound toFeedback
) callsmatch_replace
(as one of thesimplifications
on line 214 inabstract_algebra.py
) calls alambda
defined inFeedback._rules
callsSeriesProduct.feedback
, and the game is on...The bug only appears in somewhat special circumstances. In the example above, the call to
toSLH
is essential; if left out, such that the beamsplitter and cavity remain separate components in the definition of the circuit, no infinite loop appears. It also seems like internal degrees of freedom are required; for example, if the single-port cavity is replaced by a phase shift, everything works as expected. Finally, iftoSLH
is called on the full circuit before applying feedback, i.e.,circuit.toSLH().feedback()
, the infinite loop is avoided (not too surprising, since nowfeedback
is called on anSLH
object instead of aSeriesProduct
object).