def test_qsd_codegen_parameters(): k = symbols(r'kappa', positive=True) x = symbols(r'chi', real=True) c = symbols("c") a = Destroy(1) H = x * (a * a + a.dag() * a.dag()) + (c * a.dag() + c.conjugate() * a) L = sqrt(k) * a slh = SLH(identity_matrix(1), [L], H) codegen = QSDCodeGen(circuit=slh, num_vals={x: 2., c: 1 + 2j, k: 2}) scode = codegen._parameters_lines(indent=0) assert dedent(scode).strip() == dedent(""" Complex I(0.0,1.0); Complex c(1,2); double chi = 2; double kappa = 2;""").strip() codegen.num_vals.update({c: 1}) scode = codegen._parameters_lines(indent=0) assert dedent(scode).strip() == dedent(""" Complex I(0.0,1.0); Complex c(1,0); double chi = 2; double kappa = 2;""").strip() del codegen.num_vals[c] with pytest.raises(KeyError) as excinfo: scode = codegen._parameters_lines(indent=0) assert "There is no value for symbol c" in str(excinfo.value)
def test_latex_symbols(slh_Sec6): """Test that if any of the symbols contain "special" characters such as backslashes (LaTeX code), we still get valid C++ code (basic ASCII words only).""" k = symbols("\kappa", positive=True) x = symbols(r"\chi^{(1)}_{\text{main}}", real=True) c = symbols("c") a = Destroy(1) H = x * (a * a + a.dag() * a.dag()) + (c * a.dag() + c.conjugate() * a) L = sqrt(k) * a slh = SLH(identity_matrix(1), [L], H) codegen = QSDCodeGen(circuit=slh, num_vals={x: 2.0, c: 1 + 2j, k: 2}) scode = codegen._parameters_lines(indent=0) assert ( dedent(scode).strip() == dedent( """ Complex I(0.0,1.0); Complex c(1,2); double chi_1_textmain = 2; double kappa = 2;""" ).strip() )
def test_ordered_tensor_operands(slh_Sec6): codegen = QSDCodeGen(circuit=slh_Sec6) psi = BasisKet(0, 0) * BasisKet(1, 0) assert (list(psi.operands) == list(codegen._ordered_tensor_operands(psi))) psi = TensorKet(BasisKet(1, 0), BasisKet(0, 0)) assert (list(reversed(psi.operands)) == list( codegen._ordered_tensor_operands(psi)))
def test_operator_hilbert_space_check(): circuit = SLH(identity_matrix(0), [], 1) s = LocalSigma("sys", "g", "e") codegen = QSDCodeGen(circuit) with pytest.raises(ValueError) as exc_info: codegen._update_qsd_ops([s]) assert "not in the circuit's Hilbert space" in str(exc_info.value)
def test_operator_hilbert_space_check(): circuit = SLH(identity_matrix(0), [], 1) s = LocalSigma("sys", 'g', 'e') codegen = QSDCodeGen(circuit) with pytest.raises(ValueError) as exc_info: codegen._update_qsd_ops([ s, ]) assert "not in the circuit's Hilbert space" in str(exc_info.value)
def test_qsd_codegen_lindblads(slh_Sec6): codegen = QSDCodeGen(circuit=slh_Sec6) scode = codegen._lindblads_lines(indent=0) assert dedent(scode).strip() == dedent(r''' const int nL = 3; Operator L[nL]={ (sqrt(2)*sqrt(gamma_1)) * (A0), (sqrt(2)*sqrt(gamma_2)) * (A1), (sqrt(2)*sqrt(kappa)) * (S2_0_1) }; ''').strip()
def test_labeled_basis_op(): """Check that in QSD code generation labeled basis states are translated into numbered basis states""" hs = local_space("tls", namespace="sys", basis=("g", "e")) a = Destroy(hs) ad = a.dag() s = LocalSigma(hs, "g", "e") circuit = SLH(identity_matrix(0), [], a * ad) codegen = QSDCodeGen(circuit) codegen._update_qsd_ops([s]) assert codegen._qsd_ops[s].instantiator == "(0,1,0)" != "(g,e,0)"
def test_labeled_basis_op(): """Check that in QSD code generation labeled basis states are translated into numbered basis states""" hs = local_space('tls', namespace='sys', basis=('g', 'e')) a = Destroy(hs) ad = a.dag() s = LocalSigma(hs, 'g', 'e') circuit = SLH(identity_matrix(0), [], a * ad) codegen = QSDCodeGen(circuit) codegen._update_qsd_ops([ s, ]) assert codegen._qsd_ops[s].instantiator == '(0,1,0)' != '(g,e,0)'
def test_qsd_codegen_hamiltonian(): k = symbols(r"\kappa", positive=True) x = symbols(r"\chi", real=True) c = symbols("c", real=True) a = Destroy(1) H = x * (a * a + a.dag() * a.dag()) + (c * a.dag() + c.conjugate() * a) L = sqrt(k) * a slh = SLH(identity_matrix(1), [L], H) codegen = QSDCodeGen(circuit=slh, num_vals={x: 2.0, c: 1, k: 2}) codegen._operator_basis_lines(indent=0) scode = codegen._hamiltonian_lines(indent=0) assert scode.strip() == (r"Operator H = ((c) * (Ad0) + (c) * (A0) + (chi) " r"* (((Ad0 * Ad0) + (A0 * A0))));")
def test_driven_tls(datadir): hs = local_space('tls', namespace='sys', basis=('g', 'e')) w = symbols(r'\omega', real=True) pi = sympy.pi cos = sympy.cos t, T, E0 = symbols('t, T, E_0', real=True) a = 0.16 blackman = 0.5 * (1 - a - cos(2 * pi * t / T) + a * cos(4 * pi * t / T)) H0 = Destroy(hs).dag() * Destroy(hs) H1 = LocalSigma(hs, 'g', 'e') + LocalSigma(hs, 'e', 'g') H = w * H0 + 0.5 * E0 * blackman * H1 circuit = SLH(identity_matrix(0), [], H) num_vals = {w: 1.0, T: 10.0, E0: 1.0 * 2 * np.pi} # test qutip conversion H_qutip, Ls = circuit.substitute(num_vals).HL_to_qutip(time_symbol=t) assert len(Ls) == 0 assert len(H_qutip) == 3 times = np.linspace(0, num_vals[T], 201) psi0 = qutip.basis(2, 1) states = qutip.mesolve(H_qutip, psi0, times, [], []).states pop0 = np.array(qutip_population(states, state=0)) pop1 = np.array(qutip_population(states, state=1)) datfile = os.path.join(datadir, 'pops.dat') #print("DATFILE: %s" % datfile) #np.savetxt(datfile, np.c_[times, pop0, pop1, pop0+pop1]) pop0_expect, pop1_expect = np.genfromtxt(datfile, unpack=True, usecols=(1, 2)) assert np.max(np.abs(pop0 - pop0_expect)) < 1e-12 assert np.max(np.abs(pop1 - pop1_expect)) < 1e-12 # Test QSD conversion codegen = QSDCodeGen(circuit, num_vals=num_vals, time_symbol=t) codegen.add_observable(LocalSigma(hs, 'e', 'e'), name='P_e') psi0 = BasisKet(hs, 'e') codegen.set_trajectories(psi_initial=psi0, stepper='AdaptiveStep', dt=0.01, nt_plot_step=5, n_plot_steps=200, n_trajectories=1) scode = codegen.generate_code() compile_cmd = _cmd_list_to_str( codegen._build_compile_cmd(qsd_lib='$HOME/local/lib/libqsd.a', qsd_headers='$HOME/local/include/qsd/', executable='test_driven_tls', path='$HOME/bin', compiler='mpiCC', compile_options='-g -O0')) print(compile_cmd) codefile = os.path.join(datadir, "test_driven_tls.cc") #print("CODEFILE: %s" % codefile) #with(open(codefile, 'w')) as out_fh: #out_fh.write(scode) #out_fh.write("\n") with open(codefile) as in_fh: scode_expected = in_fh.read() assert scode.strip() == scode_expected.strip()
def test_qsd_codegen_hamiltonian(): k = symbols(r'\kappa', positive=True) x = symbols(r'\chi', real=True) c = symbols("c", real=True) a = Destroy(1) H = x * (a * a + a.dag() * a.dag()) + (c * a.dag() + c.conjugate() * a) L = sqrt(k) * a slh = SLH(identity_matrix(1), [L], H) codegen = QSDCodeGen(circuit=slh, num_vals={x: 2., c: 1, k: 2}) codegen._operator_basis_lines(indent=0) scode = codegen._hamiltonian_lines(indent=0) assert scode.strip() == (r'Operator H = ((c) * (Ad0) + (c) * (A0) + (chi) ' r'* (((Ad0 * Ad0) + (A0 * A0))));')
def test_qsd_codegen_lindblads(slh_Sec6): codegen = QSDCodeGen(circuit=slh_Sec6) scode = codegen._lindblads_lines(indent=0) assert ( dedent(scode).strip() == dedent( r""" const int nL = 3; Operator L[nL]={ (sqrt(2)*sqrt(gamma_1)) * (A0), (sqrt(2)*sqrt(gamma_2)) * (A1), (sqrt(2)*sqrt(kappa)) * (S2_0_1) }; """ ).strip() )
def test_latex_symbols(slh_Sec6): """Test that if any of the symbols contain "special" characters such as backslashes (LaTeX code), we still get valid C++ code (basic ASCII words only).""" k = symbols("\kappa", positive=True) x = symbols(r'\chi^{(1)}_{\text{main}}', real=True) c = symbols("c") a = Destroy(1) H = x * (a * a + a.dag() * a.dag()) + (c * a.dag() + c.conjugate() * a) L = sqrt(k) * a slh = SLH(identity_matrix(1), [L], H) codegen = QSDCodeGen(circuit=slh, num_vals={x: 2., c: 1 + 2j, k: 2}) scode = codegen._parameters_lines(indent=0) assert dedent(scode).strip() == dedent(""" Complex I(0.0,1.0); Complex c(1,2); double chi_1_textmain = 2; double kappa = 2;""").strip()
def test_qsd_codegen_operator_basis(): a = Destroy(1) a.space.dimension = 10 ad = a.dag() s = LocalSigma(2, 1, 0) s.space.dimension = 2 sd = s.dag() circuit = SLH(identity_matrix(0), [], a * ad + s + sd) codegen = QSDCodeGen(circuit) ob = codegen._operator_basis_lines(indent=0) assert dedent(ob).strip() == dedent(""" IdentityOperator Id0(0); IdentityOperator Id1(1); AnnihilationOperator A0(0); FieldTransitionOperator S1_0_1(0,1,1); FieldTransitionOperator S1_1_0(1,0,1); Operator Id = Id0*Id1; Operator Ad0 = A0.hc(); """).strip() circuit = SLH(identity_matrix(0), [], ad) codegen = QSDCodeGen(circuit) ob = codegen._operator_basis_lines(indent=0) assert dedent(ob).strip() == dedent(""" IdentityOperator Id0(0); AnnihilationOperator A0(0); Operator Id = Id0; Operator Ad0 = A0.hc(); """).strip()
def test_qsd_codegen_parameters(): k = symbols(r"kappa", positive=True) x = symbols(r"chi", real=True) c = symbols("c") a = Destroy(1) H = x * (a * a + a.dag() * a.dag()) + (c * a.dag() + c.conjugate() * a) L = sqrt(k) * a slh = SLH(identity_matrix(1), [L], H) codegen = QSDCodeGen(circuit=slh, num_vals={x: 2.0, c: 1 + 2j, k: 2}) scode = codegen._parameters_lines(indent=0) assert ( dedent(scode).strip() == dedent( """ Complex I(0.0,1.0); Complex c(1,2); double chi = 2; double kappa = 2;""" ).strip() ) codegen.num_vals.update({c: 1}) scode = codegen._parameters_lines(indent=0) assert ( dedent(scode).strip() == dedent( """ Complex I(0.0,1.0); Complex c(1,0); double chi = 2; double kappa = 2;""" ).strip() ) del codegen.num_vals[c] with pytest.raises(KeyError) as excinfo: scode = codegen._parameters_lines(indent=0) assert "There is no value for symbol c" in str(excinfo.value)
def test_qsd_codegen_operator_basis(): a = Destroy(1) a.space.dimension = 10 ad = a.dag() s = LocalSigma(2, 1, 0) s.space.dimension = 2 sd = s.dag() circuit = SLH(identity_matrix(0), [], a * ad + s + sd) codegen = QSDCodeGen(circuit) ob = codegen._operator_basis_lines(indent=0) assert ( dedent(ob).strip() == dedent( """ IdentityOperator Id0(0); IdentityOperator Id1(1); AnnihilationOperator A0(0); FieldTransitionOperator S1_0_1(0,1,1); FieldTransitionOperator S1_1_0(1,0,1); Operator Id = Id0*Id1; Operator Ad0 = A0.hc(); """ ).strip() ) circuit = SLH(identity_matrix(0), [], ad) codegen = QSDCodeGen(circuit) ob = codegen._operator_basis_lines(indent=0) assert ( dedent(ob).strip() == dedent( """ IdentityOperator Id0(0); AnnihilationOperator A0(0); Operator Id = Id0; Operator Ad0 = A0.hc(); """ ).strip() )
def test_driven_tls(datadir): hs = local_space('tls', namespace='sys', basis=('g', 'e')) w = symbols(r'\omega', real=True) pi = sympy.pi cos = sympy.cos t, T, E0 = symbols('t, T, E_0', real=True) a = 0.16 blackman = 0.5 * (1 - a - cos(2*pi * t/T) + a*cos(4*pi*t/T)) H0 = Destroy(hs).dag() * Destroy(hs) H1 = LocalSigma(hs, 'g', 'e') + LocalSigma(hs, 'e', 'g') H = w*H0 + 0.5 * E0 * blackman * H1 circuit = SLH(identity_matrix(0), [], H) num_vals = {w: 1.0, T:10.0, E0:1.0*2*np.pi} # test qutip conversion H_qutip, Ls = circuit.substitute(num_vals).HL_to_qutip(time_symbol=t) assert len(Ls) == 0 assert len(H_qutip) == 3 times = np.linspace(0, num_vals[T], 201) psi0 = qutip.basis(2, 1) states = qutip.mesolve(H_qutip, psi0, times, [], []).states pop0 = np.array(qutip_population(states, state=0)) pop1 = np.array(qutip_population(states, state=1)) datfile = os.path.join(datadir, 'pops.dat') #print("DATFILE: %s" % datfile) #np.savetxt(datfile, np.c_[times, pop0, pop1, pop0+pop1]) pop0_expect, pop1_expect = np.genfromtxt(datfile, unpack=True, usecols=(1,2)) assert np.max(np.abs(pop0 - pop0_expect)) < 1e-12 assert np.max(np.abs(pop1 - pop1_expect)) < 1e-12 # Test QSD conversion codegen = QSDCodeGen(circuit, num_vals=num_vals, time_symbol=t) codegen.add_observable(LocalSigma(hs, 'e', 'e'), name='P_e') psi0 = BasisKet(hs, 'e') codegen.set_trajectories(psi_initial=psi0, stepper='AdaptiveStep', dt=0.01, nt_plot_step=5, n_plot_steps=200, n_trajectories=1) scode = codegen.generate_code() compile_cmd = _cmd_list_to_str(codegen._build_compile_cmd( qsd_lib='$HOME/local/lib/libqsd.a', qsd_headers='$HOME/local/include/qsd/', executable='test_driven_tls', path='$HOME/bin', compiler='mpiCC', compile_options='-g -O0')) print(compile_cmd) codefile = os.path.join(datadir, "test_driven_tls.cc") #print("CODEFILE: %s" % codefile) #with(open(codefile, 'w')) as out_fh: #out_fh.write(scode) #out_fh.write("\n") with open(codefile) as in_fh: scode_expected = in_fh.read() assert scode.strip() == scode_expected.strip()
def Sec6_codegen(slh_Sec6, slh_Sec6_vals): codegen = QSDCodeGen(circuit=slh_Sec6, num_vals=slh_Sec6_vals) A2 = Destroy(1) Sp = LocalSigma(2, 1, 0) Sm = Sp.dag() codegen.add_observable(Sp * A2 * Sm * Sp, name="X1") codegen.add_observable(Sm * Sp * A2 * Sm, name="X2") codegen.add_observable(A2, name="A2") psi0 = BasisKet(0, 0) psi1 = BasisKet(1, 0) psi2 = BasisKet(2, 0) codegen.set_trajectories(psi_initial=psi0 * psi1 * psi2, stepper='AdaptiveStep', dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10) return codegen
def Sec6_codegen(slh_Sec6, slh_Sec6_vals): codegen = QSDCodeGen(circuit=slh_Sec6, num_vals=slh_Sec6_vals) A2 = Destroy(1) Sp = LocalSigma(2, 1, 0) Sm = Sp.dag() codegen.add_observable(Sp * A2 * Sm * Sp, name="X1") codegen.add_observable(Sm * Sp * A2 * Sm, name="X2") codegen.add_observable(A2, name="A2") psi0 = BasisKet(0, 0) psi1 = BasisKet(1, 0) psi2 = BasisKet(2, 0) codegen.set_trajectories( psi_initial=psi0 * psi1 * psi2, stepper="AdaptiveStep", dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10, ) return codegen
def test_qsd_codegen_traj(slh_Sec6): A2 = Destroy(1) Sp = LocalSigma(2, 1, 0) Sm = Sp.dag() codegen = QSDCodeGen(circuit=slh_Sec6) codegen.add_observable(Sp * A2 * Sm * Sp, name="X1") codegen.add_observable(Sm * Sp * A2 * Sm, name="X2") codegen.add_observable(A2, name="A2") with pytest.raises(QSDCodeGenError) as excinfo: scode = codegen._trajectory_lines(indent=0) assert "No trajectories set up" in str(excinfo.value) codegen.set_trajectories(psi_initial=None, stepper='AdaptiveStep', dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10) scode = codegen._trajectory_lines(indent=0) assert dedent(scode).strip() == dedent(r''' ACG gen(rndSeed); // random number generator ComplexNormal rndm(&gen); // Complex Gaussian random numbers double dt = 0.01; int dtsperStep = 100; int nOfSteps = 5; int nTrajSave = 10; int nTrajectory = 1; int ReadFile = 0; AdaptiveStep stepper(psiIni, H, nL, L); Trajectory traj(psiIni, dt, stepper, &rndm); traj.sumExp(nOfOut, outlist, flist , dtsperStep, nOfSteps, nTrajectory, nTrajSave, ReadFile); ''').strip() with pytest.raises(ValueError) as excinfo: codegen.set_moving_basis(move_dofs=0, delta=0.01, width=2, move_eps=0.01) assert "move_dofs must be an integer >0" in str(excinfo.value) with pytest.raises(ValueError) as excinfo: codegen.set_moving_basis(move_dofs=4, delta=0.01, width=2, move_eps=0.01) assert "move_dofs must not be larger" in str(excinfo.value) with pytest.raises(QSDCodeGenError) as excinfo: codegen.set_moving_basis(move_dofs=3, delta=0.01, width=2, move_eps=0.01) assert "A moving basis cannot be used" in str(excinfo.value) codegen.set_moving_basis(move_dofs=2, delta=0.01, width=2, move_eps=0.01) scode = codegen._trajectory_lines(indent=0) assert dedent(scode).strip() == dedent(r''' ACG gen(rndSeed); // random number generator ComplexNormal rndm(&gen); // Complex Gaussian random numbers double dt = 0.01; int dtsperStep = 100; int nOfSteps = 5; int nTrajSave = 10; int nTrajectory = 1; int ReadFile = 0; AdaptiveStep stepper(psiIni, H, nL, L); Trajectory traj(psiIni, dt, stepper, &rndm); int move = 2; double delta = 0.01; int width = 2; double moveEps = 0.01; traj.sumExp(nOfOut, outlist, flist , dtsperStep, nOfSteps, nTrajectory, nTrajSave, ReadFile, move, delta, width, moveEps); ''').strip()
def test_qsd_codegen_initial_state(slh_Sec6): A2 = Destroy(1) Sp = LocalSigma(2, 1, 0) Sm = Sp.dag() psi_cav1 = lambda n: BasisKet(0, n) psi_cav2 = lambda n: BasisKet(1, n) psi_spin = lambda n: BasisKet(2, n) psi_tot = lambda n, m, l: psi_cav1(n) * psi_cav2(m) * psi_spin(l) BasisRegistry.registry = {} # reset psi_cav1(0).space.dimension = 10 psi_cav2(0).space.dimension = 10 psi_spin(0).space.dimension = 2 codegen = QSDCodeGen(circuit=slh_Sec6) codegen.add_observable(Sp * A2 * Sm * Sp, "X1.out") codegen.add_observable(Sm * Sp * A2 * Sm, "X2.out") codegen.add_observable(A2, "A2.out") psi = (((psi_cav1(0) + psi_cav1(1)) / sympy.sqrt(2)) * ((psi_cav2(0) + psi_cav2(1)) / sympy.sqrt(2)) * psi_spin(0)) codegen.set_trajectories(psi_initial=psi, stepper='AdaptiveStep', dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10) scode = codegen._initial_state_lines(indent=0) assert scode == dedent(r''' State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiL3(10,1,FIELD); // HS 0 State phiL4(10,1,FIELD); // HS 1 State phiT0List[3] = {(phiL0 + phiL3), (phiL1 + phiL4), phiL2}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 State psiIni = (1.0L/2.0L) * (phiT0); psiIni.normalize(); ''').strip() alpha = symbols('alpha') psi = CoherentStateKet(0, alpha) * psi_cav2(0) * psi_spin(0) codegen.set_trajectories(psi_initial=psi, stepper='AdaptiveStep', dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10) scode = codegen._initial_state_lines(indent=0) assert scode == dedent(r''' State phiL0(10,0,FIELD); // HS 1 State phiL1(2,0,FIELD); // HS 2 State phiL2(10,alpha,FIELD); // HS 0 State phiT0List[3] = {phiL2, phiL0, phiL1}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 State psiIni = phiT0; psiIni.normalize(); ''').strip() psi = (psi_tot(1, 0, 0) + psi_tot(0, 1, 0)) / sympy.sqrt(2) codegen.set_trajectories(psi_initial=psi, stepper='AdaptiveStep', dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10) scode = codegen._initial_state_lines(indent=0) assert scode == dedent(r''' State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiL3(10,1,FIELD); // HS 0 State phiL4(10,1,FIELD); // HS 1 State phiT0List[3] = {phiL0, phiL4, phiL2}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 State phiT1List[3] = {phiL3, phiL1, phiL2}; State phiT1(3, phiT1List); // HS 0 * HS 1 * HS 2 State psiIni = ((1.0L/2.0L)*sqrt(2)) * ((phiT0 + phiT1)); psiIni.normalize(); ''').strip()
def test_define_atomic_kets(slh_Sec6): codegen = QSDCodeGen(circuit=slh_Sec6) psi_cav1 = lambda n: BasisKet(0, n) psi_cav2 = lambda n: BasisKet(1, n) psi_spin = lambda n: BasisKet(2, n) psi_tot = lambda n, m, l: psi_cav1(n) * psi_cav2(m) * psi_spin(l) with pytest.raises(QSDCodeGenError) as excinfo: lines = codegen._define_atomic_kets(psi_cav1(0)) assert "not in the Hilbert space of the Hamiltonian" in str(excinfo.value) BasisRegistry.registry = {} # reset with pytest.raises(QSDCodeGenError) as excinfo: lines = codegen._define_atomic_kets(psi_tot(0, 0, 0)) assert "Unknown dimension for Hilbert space" in str(excinfo.value) psi_cav1(0).space.dimension = 10 psi_cav2(0).space.dimension = 10 psi_spin(0).space.dimension = 2 lines = codegen._define_atomic_kets(psi_tot(0, 0, 0)) scode = "\n".join(lines) assert scode == dedent(r''' State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiT0List[3] = {phiL0, phiL1, phiL2}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 ''').strip() psi = (((psi_cav1(0) + psi_cav1(1)) / sympy.sqrt(2)) * ((psi_cav2(0) + psi_cav2(1)) / sympy.sqrt(2)) * psi_spin(0)) lines = codegen._define_atomic_kets(psi) scode = "\n".join(lines) assert scode == dedent(r''' State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiL3(10,1,FIELD); // HS 0 State phiL4(10,1,FIELD); // HS 1 State phiT0List[3] = {(phiL0 + phiL3), (phiL1 + phiL4), phiL2}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 ''').strip() for phi in (list(find_kets(psi, cls=LocalKet)) + list(find_kets(psi, cls=TensorKet))): assert phi in codegen._qsd_states alpha = symbols('alpha') psi = CoherentStateKet(0, alpha) * psi_cav2(0) * psi_spin(0) with pytest.raises(TypeError) as excinfo: lines = codegen._define_atomic_kets(psi) assert "neither a known symbol nor a complex number" in str(excinfo.value) codegen.syms.add(alpha) codegen._update_var_names() lines = codegen._define_atomic_kets(psi) scode = "\n".join(lines) assert scode == dedent(r''' State phiL0(10,0,FIELD); // HS 1 State phiL1(2,0,FIELD); // HS 2 State phiL2(10,alpha,FIELD); // HS 0 State phiT0List[3] = {phiL2, phiL0, phiL1}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 ''').strip() for phi in (list(find_kets(psi, cls=LocalKet)) + list(find_kets(psi, cls=TensorKet))): assert phi in codegen._qsd_states psi = CoherentStateKet(0, 1j) * psi_cav2(0) * psi_spin(0) lines = codegen._define_atomic_kets(psi) scode = "\n".join(lines) assert scode == dedent(r''' State phiL0(10,0,FIELD); // HS 1 State phiL1(2,0,FIELD); // HS 2 Complex phiL2_alpha(0,1); State phiL2(10,phiL2_alpha,FIELD); // HS 0 State phiT0List[3] = {phiL2, phiL0, phiL1}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 ''').strip() for phi in (list(find_kets(psi, cls=LocalKet)) + list(find_kets(psi, cls=TensorKet))): assert phi in codegen._qsd_states psi = psi_tot(1, 0, 0) + psi_tot(0, 1, 0) + psi_tot(0, 0, 1) lines = codegen._define_atomic_kets(psi) scode = "\n".join(lines) assert scode == dedent(r''' State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiL3(10,1,FIELD); // HS 0 State phiL4(10,1,FIELD); // HS 1 State phiL5(2,1,FIELD); // HS 2 State phiT0List[3] = {phiL0, phiL1, phiL5}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 State phiT1List[3] = {phiL0, phiL4, phiL2}; State phiT1(3, phiT1List); // HS 0 * HS 1 * HS 2 State phiT2List[3] = {phiL3, phiL1, phiL2}; State phiT2(3, phiT2List); // HS 0 * HS 1 * HS 2 ''').strip() for phi in (list(find_kets(psi, cls=LocalKet)) + list(find_kets(psi, cls=TensorKet))): assert phi in codegen._qsd_states
def test_qsd_codegen_observables(caplog, slh_Sec6, slh_Sec6_vals): A2 = Destroy(1) Sp = LocalSigma(2, 1, 0) Sm = Sp.dag() codegen = QSDCodeGen(circuit=slh_Sec6, num_vals=slh_Sec6_vals) with pytest.raises(QSDCodeGenError) as excinfo: scode = codegen._observables_lines(indent=0) assert "Must register at least one observable" in str(excinfo.value) codegen.add_observable(Sp * A2 * Sm * Sp) name = 'a_1 sigma_10^[2]' filename = codegen._observables[name][1] assert filename == 'a_1_sigma_10_2.out' codegen.add_observable(Sp * A2 * Sm * Sp) assert 'Overwriting existing operator' in caplog.text() with pytest.raises(ValueError) as exc_info: codegen.add_observable(Sp * A2 * A2 * Sm * Sp) assert "longer than limit" in str(exc_info.value) name = 'A2^2' codegen.add_observable(Sp * A2 * A2 * Sm * Sp, name=name) assert name in codegen._observables filename = codegen._observables[name][1] assert filename == 'A2_2.out' with pytest.raises(ValueError) as exc_info: codegen.add_observable(A2, name='A2_2') assert "Cannot generate unique filename" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: codegen.add_observable(A2, name="A2\t2") assert "invalid characters" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: codegen.add_observable(A2, name="A" * 100) assert "longer than limit" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: codegen.add_observable(A2, name="()") assert "Cannot generate filename" in str(exc_info.value) codegen = QSDCodeGen(circuit=slh_Sec6, num_vals=slh_Sec6_vals) codegen.add_observable(Sp * A2 * Sm * Sp, name="X1") codegen.add_observable(Sm * Sp * A2 * Sm, name="X2") assert codegen._observables["X2"] == (Sm * Sp * A2 * Sm, 'X2.out') codegen.add_observable(A2, name="A2") assert codegen._observables["A2"] == (A2, 'A2.out') scode = codegen._observables_lines(indent=0) assert dedent(scode).strip() == dedent(r''' const int nOfOut = 3; Operator outlist[nOfOut] = { (A1 * S2_1_0), (A1 * S2_0_1), A1 }; char *flist[nOfOut] = {"X1.out", "X2.out", "A2.out"}; int pipe[4] = {1,2,3,4}; ''').strip() # Note how the observables have been simplified assert Sp * A2 * Sm * Sp == Sp * A2 assert codegen._operator_str(Sp * A2) == '(A1 * S2_1_0)' assert Sm * Sp * A2 * Sm == Sm * A2 assert codegen._operator_str(Sm * A2) == '(A1 * S2_0_1)' # If the oberservables introduce new operators or symbols, these should # extend the existing ones P1 = LocalSigma(2, 1, 1) zeta = symbols("zeta", real=True) codegen.add_observable(zeta * P1, name="P1") assert P1 in codegen._local_ops assert str(codegen._qsd_ops[P1]) == 'S2_1_1' assert zeta in codegen.syms codegen.num_vals.update({zeta: 1.0}) assert 'zeta' in codegen._parameters_lines(indent=0) assert str(codegen._qsd_ops[P1]) in codegen._operator_basis_lines(indent=0) assert Sp * A2 in set(codegen.observables) assert Sm * A2 in set(codegen.observables) assert zeta * P1 in set(codegen.observables) assert list(codegen.observable_names) == ['X1', 'X2', 'A2', 'P1'] assert codegen.get_observable('X1') == Sp * A2 * Sm * Sp
def test_qsd_codegen_observables(caplog, slh_Sec6, slh_Sec6_vals): A2 = Destroy(1) Sp = LocalSigma(2, 1, 0) Sm = Sp.dag() codegen = QSDCodeGen(circuit=slh_Sec6, num_vals=slh_Sec6_vals) with pytest.raises(QSDCodeGenError) as excinfo: scode = codegen._observables_lines(indent=0) assert "Must register at least one observable" in str(excinfo.value) codegen.add_observable(Sp * A2 * Sm * Sp) name = "a_1 sigma_10^[2]" filename = codegen._observables[name][1] assert filename == "a_1_sigma_10_2.out" codegen.add_observable(Sp * A2 * Sm * Sp) assert "Overwriting existing operator" in caplog.text() with pytest.raises(ValueError) as exc_info: codegen.add_observable(Sp * A2 * A2 * Sm * Sp) assert "longer than limit" in str(exc_info.value) name = "A2^2" codegen.add_observable(Sp * A2 * A2 * Sm * Sp, name=name) assert name in codegen._observables filename = codegen._observables[name][1] assert filename == "A2_2.out" with pytest.raises(ValueError) as exc_info: codegen.add_observable(A2, name="A2_2") assert "Cannot generate unique filename" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: codegen.add_observable(A2, name="A2\t2") assert "invalid characters" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: codegen.add_observable(A2, name="A" * 100) assert "longer than limit" in str(exc_info.value) with pytest.raises(ValueError) as exc_info: codegen.add_observable(A2, name="()") assert "Cannot generate filename" in str(exc_info.value) codegen = QSDCodeGen(circuit=slh_Sec6, num_vals=slh_Sec6_vals) codegen.add_observable(Sp * A2 * Sm * Sp, name="X1") codegen.add_observable(Sm * Sp * A2 * Sm, name="X2") assert codegen._observables["X2"] == (Sm * Sp * A2 * Sm, "X2.out") codegen.add_observable(A2, name="A2") assert codegen._observables["A2"] == (A2, "A2.out") scode = codegen._observables_lines(indent=0) assert ( dedent(scode).strip() == dedent( r""" const int nOfOut = 3; Operator outlist[nOfOut] = { (A1 * S2_1_0), (A1 * S2_0_1), A1 }; char *flist[nOfOut] = {"X1.out", "X2.out", "A2.out"}; int pipe[4] = {1,2,3,4}; """ ).strip() ) # Note how the observables have been simplified assert Sp * A2 * Sm * Sp == Sp * A2 assert codegen._operator_str(Sp * A2) == "(A1 * S2_1_0)" assert Sm * Sp * A2 * Sm == Sm * A2 assert codegen._operator_str(Sm * A2) == "(A1 * S2_0_1)" # If the oberservables introduce new operators or symbols, these should # extend the existing ones P1 = LocalSigma(2, 1, 1) zeta = symbols("zeta", real=True) codegen.add_observable(zeta * P1, name="P1") assert P1 in codegen._local_ops assert str(codegen._qsd_ops[P1]) == "S2_1_1" assert zeta in codegen.syms codegen.num_vals.update({zeta: 1.0}) assert "zeta" in codegen._parameters_lines(indent=0) assert str(codegen._qsd_ops[P1]) in codegen._operator_basis_lines(indent=0) assert Sp * A2 in set(codegen.observables) assert Sm * A2 in set(codegen.observables) assert zeta * P1 in set(codegen.observables) assert list(codegen.observable_names) == ["X1", "X2", "A2", "P1"] assert codegen.get_observable("X1") == Sp * A2 * Sm * Sp
def test_ordered_tensor_operands(slh_Sec6): codegen = QSDCodeGen(circuit=slh_Sec6) psi = BasisKet(0, 0) * BasisKet(1, 0) assert list(psi.operands) == list(codegen._ordered_tensor_operands(psi)) psi = TensorKet(BasisKet(1, 0), BasisKet(0, 0)) assert list(reversed(psi.operands)) == list(codegen._ordered_tensor_operands(psi))
def test_define_atomic_kets(slh_Sec6): codegen = QSDCodeGen(circuit=slh_Sec6) psi_cav1 = lambda n: BasisKet(0, n) psi_cav2 = lambda n: BasisKet(1, n) psi_spin = lambda n: BasisKet(2, n) psi_tot = lambda n, m, l: psi_cav1(n) * psi_cav2(m) * psi_spin(l) with pytest.raises(QSDCodeGenError) as excinfo: lines = codegen._define_atomic_kets(psi_cav1(0)) assert "not in the Hilbert space of the Hamiltonian" in str(excinfo.value) BasisRegistry.registry = {} # reset with pytest.raises(QSDCodeGenError) as excinfo: lines = codegen._define_atomic_kets(psi_tot(0, 0, 0)) assert "Unknown dimension for Hilbert space" in str(excinfo.value) psi_cav1(0).space.dimension = 10 psi_cav2(0).space.dimension = 10 psi_spin(0).space.dimension = 2 lines = codegen._define_atomic_kets(psi_tot(0, 0, 0)) scode = "\n".join(lines) assert ( scode == dedent( r""" State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiT0List[3] = {phiL0, phiL1, phiL2}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 """ ).strip() ) psi = ((psi_cav1(0) + psi_cav1(1)) / sympy.sqrt(2)) * ((psi_cav2(0) + psi_cav2(1)) / sympy.sqrt(2)) * psi_spin(0) lines = codegen._define_atomic_kets(psi) scode = "\n".join(lines) assert ( scode == dedent( r""" State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiL3(10,1,FIELD); // HS 0 State phiL4(10,1,FIELD); // HS 1 State phiT0List[3] = {(phiL0 + phiL3), (phiL1 + phiL4), phiL2}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 """ ).strip() ) for phi in list(find_kets(psi, cls=LocalKet)) + list(find_kets(psi, cls=TensorKet)): assert phi in codegen._qsd_states alpha = symbols("alpha") psi = CoherentStateKet(0, alpha) * psi_cav2(0) * psi_spin(0) with pytest.raises(TypeError) as excinfo: lines = codegen._define_atomic_kets(psi) assert "neither a known symbol nor a complex number" in str(excinfo.value) codegen.syms.add(alpha) codegen._update_var_names() lines = codegen._define_atomic_kets(psi) scode = "\n".join(lines) assert ( scode == dedent( r""" State phiL0(10,0,FIELD); // HS 1 State phiL1(2,0,FIELD); // HS 2 State phiL2(10,alpha,FIELD); // HS 0 State phiT0List[3] = {phiL2, phiL0, phiL1}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 """ ).strip() ) for phi in list(find_kets(psi, cls=LocalKet)) + list(find_kets(psi, cls=TensorKet)): assert phi in codegen._qsd_states psi = CoherentStateKet(0, 1j) * psi_cav2(0) * psi_spin(0) lines = codegen._define_atomic_kets(psi) scode = "\n".join(lines) assert ( scode == dedent( r""" State phiL0(10,0,FIELD); // HS 1 State phiL1(2,0,FIELD); // HS 2 Complex phiL2_alpha(0,1); State phiL2(10,phiL2_alpha,FIELD); // HS 0 State phiT0List[3] = {phiL2, phiL0, phiL1}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 """ ).strip() ) for phi in list(find_kets(psi, cls=LocalKet)) + list(find_kets(psi, cls=TensorKet)): assert phi in codegen._qsd_states psi = psi_tot(1, 0, 0) + psi_tot(0, 1, 0) + psi_tot(0, 0, 1) lines = codegen._define_atomic_kets(psi) scode = "\n".join(lines) assert ( scode == dedent( r""" State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiL3(10,1,FIELD); // HS 0 State phiL4(10,1,FIELD); // HS 1 State phiL5(2,1,FIELD); // HS 2 State phiT0List[3] = {phiL0, phiL1, phiL5}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 State phiT1List[3] = {phiL0, phiL4, phiL2}; State phiT1(3, phiT1List); // HS 0 * HS 1 * HS 2 State phiT2List[3] = {phiL3, phiL1, phiL2}; State phiT2(3, phiT2List); // HS 0 * HS 1 * HS 2 """ ).strip() ) for phi in list(find_kets(psi, cls=LocalKet)) + list(find_kets(psi, cls=TensorKet)): assert phi in codegen._qsd_states
def test_qsd_codegen_initial_state(slh_Sec6): A2 = Destroy(1) Sp = LocalSigma(2, 1, 0) Sm = Sp.dag() psi_cav1 = lambda n: BasisKet(0, n) psi_cav2 = lambda n: BasisKet(1, n) psi_spin = lambda n: BasisKet(2, n) psi_tot = lambda n, m, l: psi_cav1(n) * psi_cav2(m) * psi_spin(l) BasisRegistry.registry = {} # reset psi_cav1(0).space.dimension = 10 psi_cav2(0).space.dimension = 10 psi_spin(0).space.dimension = 2 codegen = QSDCodeGen(circuit=slh_Sec6) codegen.add_observable(Sp * A2 * Sm * Sp, "X1.out") codegen.add_observable(Sm * Sp * A2 * Sm, "X2.out") codegen.add_observable(A2, "A2.out") psi = ((psi_cav1(0) + psi_cav1(1)) / sympy.sqrt(2)) * ((psi_cav2(0) + psi_cav2(1)) / sympy.sqrt(2)) * psi_spin(0) codegen.set_trajectories( psi_initial=psi, stepper="AdaptiveStep", dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10, ) scode = codegen._initial_state_lines(indent=0) assert ( scode == dedent( r""" State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiL3(10,1,FIELD); // HS 0 State phiL4(10,1,FIELD); // HS 1 State phiT0List[3] = {(phiL0 + phiL3), (phiL1 + phiL4), phiL2}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 State psiIni = (1.0L/2.0L) * (phiT0); psiIni.normalize(); """ ).strip() ) alpha = symbols("alpha") psi = CoherentStateKet(0, alpha) * psi_cav2(0) * psi_spin(0) codegen.set_trajectories( psi_initial=psi, stepper="AdaptiveStep", dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10, ) scode = codegen._initial_state_lines(indent=0) assert ( scode == dedent( r""" State phiL0(10,0,FIELD); // HS 1 State phiL1(2,0,FIELD); // HS 2 State phiL2(10,alpha,FIELD); // HS 0 State phiT0List[3] = {phiL2, phiL0, phiL1}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 State psiIni = phiT0; psiIni.normalize(); """ ).strip() ) psi = (psi_tot(1, 0, 0) + psi_tot(0, 1, 0)) / sympy.sqrt(2) codegen.set_trajectories( psi_initial=psi, stepper="AdaptiveStep", dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10, ) scode = codegen._initial_state_lines(indent=0) assert ( scode == dedent( r""" State phiL0(10,0,FIELD); // HS 0 State phiL1(10,0,FIELD); // HS 1 State phiL2(2,0,FIELD); // HS 2 State phiL3(10,1,FIELD); // HS 0 State phiL4(10,1,FIELD); // HS 1 State phiT0List[3] = {phiL0, phiL4, phiL2}; State phiT0(3, phiT0List); // HS 0 * HS 1 * HS 2 State phiT1List[3] = {phiL3, phiL1, phiL2}; State phiT1(3, phiT1List); // HS 0 * HS 1 * HS 2 State psiIni = ((1.0L/2.0L)*sqrt(2)) * ((phiT0 + phiT1)); psiIni.normalize(); """ ).strip() )
def test_qsd_codegen_traj(slh_Sec6): A2 = Destroy(1) Sp = LocalSigma(2, 1, 0) Sm = Sp.dag() codegen = QSDCodeGen(circuit=slh_Sec6) codegen.add_observable(Sp * A2 * Sm * Sp, name="X1") codegen.add_observable(Sm * Sp * A2 * Sm, name="X2") codegen.add_observable(A2, name="A2") with pytest.raises(QSDCodeGenError) as excinfo: scode = codegen._trajectory_lines(indent=0) assert "No trajectories set up" in str(excinfo.value) codegen.set_trajectories( psi_initial=None, stepper="AdaptiveStep", dt=0.01, nt_plot_step=100, n_plot_steps=5, n_trajectories=1, traj_save=10, ) scode = codegen._trajectory_lines(indent=0) assert ( dedent(scode).strip() == dedent( r""" ACG gen(rndSeed); // random number generator ComplexNormal rndm(&gen); // Complex Gaussian random numbers double dt = 0.01; int dtsperStep = 100; int nOfSteps = 5; int nTrajSave = 10; int nTrajectory = 1; int ReadFile = 0; AdaptiveStep stepper(psiIni, H, nL, L); Trajectory traj(psiIni, dt, stepper, &rndm); traj.sumExp(nOfOut, outlist, flist , dtsperStep, nOfSteps, nTrajectory, nTrajSave, ReadFile); """ ).strip() ) with pytest.raises(ValueError) as excinfo: codegen.set_moving_basis(move_dofs=0, delta=0.01, width=2, move_eps=0.01) assert "move_dofs must be an integer >0" in str(excinfo.value) with pytest.raises(ValueError) as excinfo: codegen.set_moving_basis(move_dofs=4, delta=0.01, width=2, move_eps=0.01) assert "move_dofs must not be larger" in str(excinfo.value) with pytest.raises(QSDCodeGenError) as excinfo: codegen.set_moving_basis(move_dofs=3, delta=0.01, width=2, move_eps=0.01) assert "A moving basis cannot be used" in str(excinfo.value) codegen.set_moving_basis(move_dofs=2, delta=0.01, width=2, move_eps=0.01) scode = codegen._trajectory_lines(indent=0) assert ( dedent(scode).strip() == dedent( r""" ACG gen(rndSeed); // random number generator ComplexNormal rndm(&gen); // Complex Gaussian random numbers double dt = 0.01; int dtsperStep = 100; int nOfSteps = 5; int nTrajSave = 10; int nTrajectory = 1; int ReadFile = 0; AdaptiveStep stepper(psiIni, H, nL, L); Trajectory traj(psiIni, dt, stepper, &rndm); int move = 2; double delta = 0.01; int width = 2; double moveEps = 0.01; traj.sumExp(nOfOut, outlist, flist , dtsperStep, nOfSteps, nTrajectory, nTrajSave, ReadFile, move, delta, width, moveEps); """ ).strip() )