Example #1
0
    def testFeedback(self):
        A, B, C, D, A1, A2 = get_symbols(3, 2, 1, 1, 1, 1)
        circuit_identity(1)

#        self.assertRaises(Exception, Feedback, ())
#        self.assertRaises(Exception, Feedback, (C,))
#        self.assertRaises(Exception, Feedback, (C + D,))
#        self.assertRaises(Exception, Feedback, (C << D,))
#        self.assertRaises(Exception, Feedback, (circuit_identity(n),))
#        self.assertRaises(Exception, Feedback.create, (circuit_identity(0)))
#        self.assertEquals(Feedback.create(circuit_identity(n)), circuit_identity(n-1))
        self.assertEquals(FB(A+B), A + FB(B))
        smq = map_signals_circuit({2:1}, 3) # == 'cid(1) + X'
        self.assertEquals(smq, smq.series_inverse())
        # import metapost as mp
        # mp.display_circuit(Feedback.apply_with_rules(smq.series_inverse() << (B + C) << smq))
        # mp.display_circuit(B.feedback() + C)

        self.assertEquals(( smq << (B + C)).feedback(out_index = 2, in_index = 1), B.feedback() + C)
        print((smq << (B + C) << smq).feedback())

        self.assertEquals(( smq << (B + C) << smq).feedback(), B.feedback() + C)

        self.assertEquals((B + C).feedback(1,1), B.feedback() + C)

        #check that feedback is resolved into series when possible
        self.assertEquals(B.feedback(1,0).substitute({B:(C+D)}), C << D)
        self.assertEquals((A << (B + cid(1))).feedback(),  A.feedback() << B)
        self.assertEquals((A << (B + cid(1)) << (cid(1) + P_sigma(1,0))).feedback(2,1),  A.feedback() << B)
        self.assertEquals((A << (cid(1) + P_sigma(1,0)) << (B + cid(1)) << (cid(1) + P_sigma(1,0))).feedback(1,1),  A.feedback(1,1) << B)
        self.assertEquals((B << (cid(1)  + C)).feedback(0,1).substitute({B: (A1 + A2)}), A2 << C << A1)
        self.assertEquals(((cid(1)  + C)<< P_sigma(1,0) << B).feedback(1,1).substitute({B: (A1 + A2)}), A2 << C << A1)
        self.assertEquals(((cid(1)  + C)<< P_sigma(1,0) << B << (cid(1) + D)).feedback(1,1).substitute({B: (A1 + A2)}), A2 << D<< C << A1)
Example #2
0
    def testFeedback(self):
        A, B, C, D, A1, A2 = get_symbols(3, 2, 1, 1, 1, 1)
        circuit_identity(1)

        #        self.assertRaises(Exception, Feedback, ())
        #        self.assertRaises(Exception, Feedback, (C,))
        #        self.assertRaises(Exception, Feedback, (C + D,))
        #        self.assertRaises(Exception, Feedback, (C << D,))
        #        self.assertRaises(Exception, Feedback, (circuit_identity(n),))
        #        self.assertRaises(Exception, Feedback.create, (circuit_identity(0)))
        #        self.assertEquals(Feedback.create(circuit_identity(n)), circuit_identity(n-1))
        self.assertEquals(FB(A + B), A + FB(B))
        smq = map_signals_circuit({2: 1}, 3)  # == 'cid(1) + X'
        self.assertEquals(smq, smq.series_inverse())
        # import metapost as mp
        # mp.display_circuit(Feedback.apply_with_rules(smq.series_inverse() << (B + C) << smq))
        # mp.display_circuit(B.feedback() + C)

        self.assertEquals((smq << (B + C)).feedback(out_index=2, in_index=1),
                          B.feedback() + C)
        print((smq << (B + C) << smq).feedback())

        self.assertEquals((smq << (B + C) << smq).feedback(), B.feedback() + C)

        self.assertEquals((B + C).feedback(1, 1), B.feedback() + C)

        #check that feedback is resolved into series when possible
        self.assertEquals(B.feedback(1, 0).substitute({B: (C + D)}), C << D)
        self.assertEquals((A << (B + cid(1))).feedback(), A.feedback() << B)
        self.assertEquals((A << (B + cid(1)) <<
                           (cid(1) + P_sigma(1, 0))).feedback(2, 1),
                          A.feedback() << B)
        self.assertEquals((A << (cid(1) + P_sigma(1, 0)) << (B + cid(1)) <<
                           (cid(1) + P_sigma(1, 0))).feedback(1, 1),
                          A.feedback(1, 1) << B)
        self.assertEquals(
            (B << (cid(1) + C)).feedback(0, 1).substitute({B: (A1 + A2)}),
            A2 << C << A1)
        self.assertEquals(((cid(1) + C) << P_sigma(1, 0) << B).feedback(
            1, 1).substitute({B: (A1 + A2)}), A2 << C << A1)
        self.assertEquals(
            ((cid(1) + C) << P_sigma(1, 0) << B <<
             (cid(1) + D)).feedback(1, 1).substitute({B: (A1 + A2)}),
            A2 << D << C << A1)
Example #3
0
    def to_circuit(self, identifier_postfix = ''):
        """
        Compute a circuit algebra expression from the QHDL code and return the
        circuit expression, the all_symbols appearing in it and the component instance assignments
        """
        
        if self._circuit_data:
            return self._circuit_data
        from qnet.algebra import circuit_algebra as ca


        # initialize trivial circuit
        circuit = ca.cid(0)

        II = []
        OO = []

        if len(self.lossy_signals):
            if not self.components.get('Beamsplitter', False):
                self.components['Beamsplitter'] = Component('Beamsplitter', [('theta','real')],[(['In1','In2'],'in','fieldmode'),(['Out1','Out2'],'out','fieldmode')])
                self.components['Beamsplitter'].cdim = 2
        
        
        OPEN = object()
        #create all_symbols for all instances
        circuit_symbols = {}
        for (instance_name, (component, _, _)) in self.instance_assignments.items():
            QQ = ca.CircuitSymbol(instance_name + identifier_postfix, component.cdim)
            circuit_symbols[instance_name] = QQ
            
            assert component.inout_port_identifiers == []
            
            circuit  = circuit + QQ
#            II = II + [(instance_name, port_name + "_i" ) for port_name in component.inout_port_identifiers]
            II = II + [(instance_name, port_name) for port_name in component.in_port_identifiers]
            
#            OO = OO + [(instance_name, port_name + "_o") for port_name in component.inout_port_identifiers]
            OO = OO + [(instance_name, port_name) for port_name in component.out_port_identifiers]
            
            if len(component.in_port_identifiers) + len(component.inout_port_identifiers) < component.cdim:
                II = II + [(OPEN,OPEN)] * ( component.cdim - len(component.in_port_identifiers) - len(component.inout_port_identifiers))
            
            if len(component.out_port_identifiers) < component.cdim:
                OO = OO + [(OPEN,OPEN)] * ( component.cdim - len(component.out_port_identifiers) - len(component.inout_port_identifiers))
        
        
        # Add loss-beamsplitters
        for k, s in enumerate(self.lossy_signals):
        
#            while "LSS%s_%d%s" % (s, j, identifier_postfix) in circuit_symbols:
#                j += 1
            LBS = ca.CircuitSymbol("LSS_%s%s" % (s,identifier_postfix), 2)
            circuit = circuit + LBS
            
            
            II = II + [('LSS_%s' % s, 'In1'),(OPEN, OPEN)]
            OO = OO + [('LSS_%s' % s, 'Out1'),(OPEN, OPEN)]
            
            self.signals.append(s+"__from_loss")
            self.signals.append(s)
            
            
            # modify assignment of original component that leads into signal
            try:
                # exploit enforced order of dictionaries
                jj = list(self.in_to_signal.values()).index(s)
                ipnames = list(self.in_to_signal.keys())[jj]
                assert self.in_to_signal[ipnames] == s
                self.in_to_signal[ipnames] = s + "__from_loss"
            except ValueError:
                jj = list(self.global_out.values()).index(s)
                ipnames = list(self.global_out.keys())[jj]
                assert self.global_out[ipnames] == s
                self.global_out[ipnames] = s + "__from_loss"
            # Update lookup tables
            self.in_to_signal[('LSS_%s' % s, 'In1')] = s
            self.out_to_signal[('LSS_%s' % s, 'Out1')] = s + "__from_loss"
            
            # Create artificial instance assignment
            self.instance_assignments['LSS_%s' % s] = self.components['Beamsplitter'], {'theta': 'theta_LS%d' % k},{"In1": s, "Out1": s + "__from_loss"}
            circuit_symbols['LSS_%s' % s] = LBS
            self.entity.generics['theta_LS%d' % k] = "real", None
            
        
        assert circuit.cdim == len(OO) == len(II)
        SS = list(self.signals)
        
        
        # Add signals as passthru lines below rest
        circuit = circuit + ca.cid(len(SS))
#        print(circuit)
        
        # Do feedback from instance output to signals
        SSp = list(SS)
        OOp = list(OO)
        M = len(OO)
        for iname, pname in OO:
            if iname is OPEN:
                continue
            sname = self.out_to_signal.get((iname, pname), False)
            if sname:
                k = OOp.index((iname, pname))
                l = SSp.index(sname) + M
                
                circuit = circuit.feedback(k,l)
                SSp.remove(sname)
                OOp.remove((iname, pname))
#        print(circuit)
        # Do feedback from signal output to instance inputs
        IIp = list(II)
        SSpp = list(SS)
        Mf = len(OOp)
        
        for iname, pname in II:
            if iname is OPEN:
                continue
            sname = self.in_to_signal.get((iname, pname), False)
            if sname:
                k = SSpp.index(sname) + Mf
                l = IIp.index((iname, pname))
                
                circuit = circuit.feedback(k,l)
                SSpp.remove(sname)
                IIp.remove((iname, pname))
        
        SIGNAL = object()
        OO_effective = OOp + [(SIGNAL, s) for s in SSpp]
        II_effective = IIp + [(SIGNAL, s) for s in SSp]
        
        
        omapping = {}
        # construct output permutation
        for i, (iname, pname) in enumerate(OO_effective):
            if iname is not SIGNAL:
                eport = self.global_out.get((iname, pname), False)
            else:
                eport = self.signal_to_global_out.get(pname, False)
            if eport:
                omapping[i] = list(self.entity.out_port_identifiers).index(eport)
        
        imapping = {}
        # construct output permutation
        
        for i, (iname, pname) in enumerate(II_effective):
            if not (iname is SIGNAL):
                eport = self.global_in.get((iname, pname), False)
            else:
                eport = self.signal_to_global_in.get(pname, False)
            if eport:
                k = list(self.entity.in_port_identifiers).index(eport)
                imapping[k] = i
#        print(imapping, II_effective,self.signal_to_global_in)
        
        circuit = ca.map_signals_circuit(omapping, circuit.cdim) << circuit << ca.map_signals_circuit(imapping, circuit.cdim)

        self._circuit_data = circuit, circuit_symbols, self.instance_assignments
        self.entity.cdim = circuit.cdim
        return self._circuit_data
Example #4
0
    def testFactorizePermutation(self):
        self.assertEqual(full_block_perm((0,1,2), (1,1,1)), (0,1,2))
        self.assertEqual(full_block_perm((0,2,1), (1,1,1)), (0,2,1))
        self.assertEqual(full_block_perm((0,2,1), (1,1,2)), (0,3,1,2))
        self.assertEqual(full_block_perm((0,2,1), (1,2,3)), (0,4,5,1,2,3))
        self.assertEqual(full_block_perm((1,2,0), (1,2,3)), (3,4,5,0,1,2))
        self.assertEqual(full_block_perm((3,1,2,0), (1,2,3,4)), (9, 4, 5, 6, 7, 8, 0, 1, 2, 3 ))
        self.assertEqual(block_perm_and_perms_within_blocks((9, 4, 5, 6, 7, 8, 0, 1, 2, 3 ), (1,2,3,4)), \
                                                                        ((3,1,2,0), [(0,),(0,1),(0,1,2),(0,1,2,3)]))

        A1,A2,A3,A4 = get_symbols(1,2,3,4)

        new_lhs, permuted_rhs, new_rhs = P_sigma(9, 4, 5, 6, 7, 8, 0, 1, 2, 3 )._factorize_for_rhs(A1+A2+A3+A4)
        self.assertEqual(new_lhs, cid(10))
        self.assertEqual(permuted_rhs, (A4+A2+A3+A1))
        self.assertEqual(new_rhs, P_sigma(9, 4, 5, 6, 7, 8, 0, 1, 2, 3 ))

        p = P_sigma(0,1,4,2,3,5)
        expr = A2 + A3 + A1
        new_lhs, permuted_rhs, new_rhs = p._factorize_for_rhs(expr)
        self.assertEqual(new_lhs, cid(6))
        self.assertEqual(permuted_rhs, A2 + (P_sigma(2,0,1) << A3) + A1)
        self.assertEqual(new_rhs, cid(6))


        p = P_sigma(0, 3, 1, 2)

        p_r = P_sigma(2, 0, 1)
        assert p == cid(1) + p_r
        A = get_symbol(2)



        new_lhs, permuted_rhs, new_rhs = p._factorize_for_rhs(cid(1) + A+ cid(1))

        self.assertEqual(new_lhs, P_sigma(0,1,3,2))
        self.assertEqual(permuted_rhs, (cid(1) + (P_sigma(1,0) << A)  + cid(1)))
        self.assertEqual(new_rhs, cid(4))


        new_lhs, permuted_rhs, new_rhs = p._factorize_for_rhs(cid(2) + A)

        self.assertEqual(new_lhs, cid(4))
        self.assertEqual(permuted_rhs, (cid(1) + A  + cid(1)))
        self.assertEqual(new_rhs, p)

        self.assertEqual(p.series_inverse() << (cid(2) + A), cid(1) + SeriesProduct(P_sigma(0,2,1), Concatenation(SeriesProduct(P_sigma(1,0), A), cid(1)),P_sigma(2,0,1)))

        self.assertEqual(p.series_inverse() << (cid(2) + A) << p, cid(1) + (p_r.series_inverse() << (cid(1) + A) << p_r))

        new_lhs, permuted_rhs, new_rhs = P_sigma(4,2,1,3,0)._factorize_for_rhs((A4 + cid(1)))
        self.assertEqual(new_lhs, cid(5))
        self.assertEqual(permuted_rhs, (cid(1) + (P_sigma(3,1,0,2) << A4)))
        self.assertEqual(new_rhs, map_signals_circuit({4:0}, 5))


        ## special test case that helped find the major permutation block structure factorization bug
        p = P_sigma(3, 4, 5, 0, 1, 6, 2)
        q = cid(3) + CircuitSymbol('NAND1', 4)

        new_lhs, permuted_rhs, new_rhs = p._factorize_for_rhs(q)
        self.assertEqual(new_lhs, P_sigma(0,1,2,6,3,4,5))
        self.assertEqual(permuted_rhs, (P_sigma(0,1,3,2) << CircuitSymbol('NAND1', 4)) + cid(3))
        self.assertEqual(new_rhs, P_sigma(4,5,6, 0,1,2,3))
Example #5
0
    def testFactorizePermutation(self):
        self.assertEqual(full_block_perm((0, 1, 2), (1, 1, 1)), (0, 1, 2))
        self.assertEqual(full_block_perm((0, 2, 1), (1, 1, 1)), (0, 2, 1))
        self.assertEqual(full_block_perm((0, 2, 1), (1, 1, 2)), (0, 3, 1, 2))
        self.assertEqual(full_block_perm((0, 2, 1), (1, 2, 3)),
                         (0, 4, 5, 1, 2, 3))
        self.assertEqual(full_block_perm((1, 2, 0), (1, 2, 3)),
                         (3, 4, 5, 0, 1, 2))
        self.assertEqual(full_block_perm((3, 1, 2, 0), (1, 2, 3, 4)),
                         (9, 4, 5, 6, 7, 8, 0, 1, 2, 3))
        self.assertEqual(block_perm_and_perms_within_blocks((9, 4, 5, 6, 7, 8, 0, 1, 2, 3 ), (1,2,3,4)), \
                                                                        ((3,1,2,0), [(0,),(0,1),(0,1,2),(0,1,2,3)]))

        A1, A2, A3, A4 = get_symbols(1, 2, 3, 4)

        new_lhs, permuted_rhs, new_rhs = P_sigma(
            9, 4, 5, 6, 7, 8, 0, 1, 2, 3)._factorize_for_rhs(A1 + A2 + A3 + A4)
        self.assertEqual(new_lhs, cid(10))
        self.assertEqual(permuted_rhs, (A4 + A2 + A3 + A1))
        self.assertEqual(new_rhs, P_sigma(9, 4, 5, 6, 7, 8, 0, 1, 2, 3))

        p = P_sigma(0, 1, 4, 2, 3, 5)
        expr = A2 + A3 + A1
        new_lhs, permuted_rhs, new_rhs = p._factorize_for_rhs(expr)
        self.assertEqual(new_lhs, cid(6))
        self.assertEqual(permuted_rhs, A2 + (P_sigma(2, 0, 1) << A3) + A1)
        self.assertEqual(new_rhs, cid(6))

        p = P_sigma(0, 3, 1, 2)

        p_r = P_sigma(2, 0, 1)
        assert p == cid(1) + p_r
        A = get_symbol(2)

        new_lhs, permuted_rhs, new_rhs = p._factorize_for_rhs(
            cid(1) + A + cid(1))

        self.assertEqual(new_lhs, P_sigma(0, 1, 3, 2))
        self.assertEqual(permuted_rhs,
                         (cid(1) + (P_sigma(1, 0) << A) + cid(1)))
        self.assertEqual(new_rhs, cid(4))

        new_lhs, permuted_rhs, new_rhs = p._factorize_for_rhs(cid(2) + A)

        self.assertEqual(new_lhs, cid(4))
        self.assertEqual(permuted_rhs, (cid(1) + A + cid(1)))
        self.assertEqual(new_rhs, p)

        self.assertEqual(
            p.series_inverse() << (cid(2) + A),
            cid(1) + SeriesProduct(
                P_sigma(0, 2, 1),
                Concatenation(SeriesProduct(P_sigma(1, 0), A), cid(1)),
                P_sigma(2, 0, 1)))

        self.assertEqual(
            p.series_inverse() << (cid(2) + A) << p,
            cid(1) + (p_r.series_inverse() << (cid(1) + A) << p_r))

        new_lhs, permuted_rhs, new_rhs = P_sigma(4, 2, 1, 3,
                                                 0)._factorize_for_rhs(
                                                     (A4 + cid(1)))
        self.assertEqual(new_lhs, cid(5))
        self.assertEqual(permuted_rhs, (cid(1) + (P_sigma(3, 1, 0, 2) << A4)))
        self.assertEqual(new_rhs, map_signals_circuit({4: 0}, 5))

        ## special test case that helped find the major permutation block structure factorization bug
        p = P_sigma(3, 4, 5, 0, 1, 6, 2)
        q = cid(3) + CircuitSymbol('NAND1', 4)

        new_lhs, permuted_rhs, new_rhs = p._factorize_for_rhs(q)
        self.assertEqual(new_lhs, P_sigma(0, 1, 2, 6, 3, 4, 5))
        self.assertEqual(permuted_rhs,
                         (P_sigma(0, 1, 3, 2) << CircuitSymbol('NAND1', 4)) +
                         cid(3))
        self.assertEqual(new_rhs, P_sigma(4, 5, 6, 0, 1, 2, 3))