def detect_nan(fgraph, i, node, fn): for output in fn.outputs: if np.isnan(output[0]).any(): print("*** NaN detected ***") debugprint(node) print("Inputs : %s" % [input[0] for input in fn.inputs]) print("Outputs: %s" % [output[0] for output in fn.outputs]) nan_detected[0] = True break
def detect_nan(fgraph, i, node, fn): from aesara.printing import debugprint for output in fn.outputs: if (not isinstance(output[0], np.random.RandomState) and np.isnan(output[0]).any()): print("*** NaN detected ***") debugprint(node) print("Inputs : %s" % [input[0] for input in fn.inputs]) print("Outputs: %s" % [output[0] for output in fn.outputs]) break
def test_scan_debugprint2(): coefficients = vector("coefficients") x = scalar("x") max_coefficients_supported = 10000 # Generate the components of the polynomial components, updates = aesara.scan( fn=lambda coefficient, power, free_variable: coefficient * (free_variable ** power), outputs_info=None, sequences=[coefficients, aet.arange(max_coefficients_supported)], non_sequences=x, ) # Sum them up polynomial = components.sum() output_str = debugprint(polynomial, file="str") lines = output_str.split("\n") expected_output = """Sum{acc_dtype=float64} [id A] '' |for{cpu,scan_fn} [id B] '' |Elemwise{scalar_minimum,no_inplace} [id C] '' | |Subtensor{int64} [id D] '' | | |Shape [id E] '' | | | |Subtensor{int64::} [id F] 'coefficients[0:]' | | | |coefficients [id G] | | | |ScalarConstant{0} [id H] | | |ScalarConstant{0} [id I] | |Subtensor{int64} [id J] '' | |Shape [id K] '' | | |Subtensor{int64::} [id L] '' | | |ARange{dtype='int64'} [id M] '' | | | |TensorConstant{0} [id N] | | | |TensorConstant{10000} [id O] | | | |TensorConstant{1} [id P] | | |ScalarConstant{0} [id Q] | |ScalarConstant{0} [id R] |Subtensor{:int64:} [id S] '' | |Subtensor{int64::} [id F] 'coefficients[0:]' | |ScalarFromTensor [id T] '' | |Elemwise{scalar_minimum,no_inplace} [id C] '' |Subtensor{:int64:} [id U] '' | |Subtensor{int64::} [id L] '' | |ScalarFromTensor [id V] '' | |Elemwise{scalar_minimum,no_inplace} [id C] '' |Elemwise{scalar_minimum,no_inplace} [id C] '' |x [id W] Inner graphs of the scan ops: for{cpu,scan_fn} [id B] '' >Elemwise{mul,no_inplace} [id X] '' > |coefficients[t] [id Y] -> [id S] > |Elemwise{pow,no_inplace} [id Z] '' > |x_copy [id BA] -> [id W] > |<TensorType(int64, scalar)> [id BB] -> [id U]""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_debugprint(): x, y, z = matrices("xyz") e = x + y * z op = OpFromGraph([x, y, z], [e]) out = op(x, y, z) output_str = debugprint(out, file="str") lines = output_str.split("\n") exp_res = """OpFromGraph{inline=False} [id A] |x [id B] |y [id C] |z [id D] Inner graphs: OpFromGraph{inline=False} [id A] >Elemwise{add,no_inplace} [id E] > |*0-<TensorType(float64, (None, None))> [id F] > |Elemwise{mul,no_inplace} [id G] > |*1-<TensorType(float64, (None, None))> [id H] > |*2-<TensorType(float64, (None, None))> [id I] """ for truth, out in zip(exp_res.split("\n"), lines): assert truth.strip() == out.strip()
def test_debugprint_compiled_fn(): M = at.tensor(np.float64, shape=(20000, 2, 2)) one = at.as_tensor(1, dtype=np.int64) zero = at.as_tensor(0, dtype=np.int64) def no_shared_fn(n, x_tm1, M): p = M[n, x_tm1] return at.switch(at.lt(zero, p[0]), one, zero) out, updates = aesara.scan( no_shared_fn, outputs_info=[{ "initial": zero, "taps": [-1] }], sequences=[at.arange(M.shape[0])], non_sequences=[M], allow_gc=False, mode="FAST_RUN", ) # In this case, `debugprint` should print the compiled inner-graph # (i.e. from `Scan._fn`) out = aesara.function([M], out, updates=updates, mode="FAST_RUN") expected_output = """forall_inplace,cpu,scan_fn} [id A] 2 (outer_out_sit_sot-0) |TensorConstant{20000} [id B] (n_steps) |TensorConstant{[ 0 ..998 19999]} [id C] (outer_in_seqs-0) |IncSubtensor{InplaceSet;:int64:} [id D] 1 (outer_in_sit_sot-0) | |AllocEmpty{dtype='int64'} [id E] 0 | | |TensorConstant{20000} [id B] | |TensorConstant{(1,) of 0} [id F] | |ScalarConstant{1} [id G] |<TensorType(float64, (20000, 2, 2))> [id H] (outer_in_non_seqs-0) Inner graphs: forall_inplace,cpu,scan_fn} [id A] (outer_out_sit_sot-0) >Elemwise{Composite{Switch(LT(i0, i1), i2, i0)}} [id I] (inner_out_sit_sot-0) > |TensorConstant{0} [id J] > |Subtensor{int64, int64, int64} [id K] > | |*2-<TensorType(float64, (20000, 2, 2))> [id L] -> [id H] (inner_in_non_seqs-0) > | |ScalarFromTensor [id M] > | | |*0-<TensorType(int64, ())> [id N] -> [id C] (inner_in_seqs-0) > | |ScalarFromTensor [id O] > | | |*1-<TensorType(int64, ())> [id P] -> [id D] (inner_in_sit_sot-0) > | |ScalarConstant{0} [id Q] > |TensorConstant{1} [id R] """ output_str = debugprint(out, file="str", print_op_info=True) lines = output_str.split("\n") for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_debugprint_ids(): a_at = dvector() b_at = dmatrix() d_at = b_at.dot(a_at) e_at = d_at + a_at s = StringIO() debugprint(e_at, ids="auto", file=s) s = s.getvalue() exp_res = f"""Elemwise{{add,no_inplace}} [id {e_at.auto_name}] |dot [id {d_at.auto_name}] | |<TensorType(float64, (None, None))> [id {b_at.auto_name}] | |<TensorType(float64, (None,))> [id {a_at.auto_name}] |<TensorType(float64, (None,))> [id {a_at.auto_name}] """ assert [l.strip() for l in s.split("\n") ] == [l.strip() for l in exp_res.split("\n")]
def test_scan_debugprint1(): k = iscalar("k") A = dvector("A") # Symbolic description of the result result, updates = aesara.scan( fn=lambda prior_result, A: prior_result * A, outputs_info=aet.ones_like(A), non_sequences=A, n_steps=k, ) final_result = result[-1] output_str = debugprint(final_result, file="str") lines = output_str.split("\n") expected_output = """Subtensor{int64} [id A] '' |Subtensor{int64::} [id B] '' | |for{cpu,scan_fn} [id C] '' | | |k [id D] | | |IncSubtensor{Set;:int64:} [id E] '' | | | |AllocEmpty{dtype='float64'} [id F] '' | | | | |Elemwise{add,no_inplace} [id G] '' | | | | | |k [id D] | | | | | |Subtensor{int64} [id H] '' | | | | | |Shape [id I] '' | | | | | | |Rebroadcast{(0, False)} [id J] '' | | | | | | |InplaceDimShuffle{x,0} [id K] '' | | | | | | |Elemwise{second,no_inplace} [id L] '' | | | | | | |A [id M] | | | | | | |InplaceDimShuffle{x} [id N] '' | | | | | | |TensorConstant{1.0} [id O] | | | | | |ScalarConstant{0} [id P] | | | | |Subtensor{int64} [id Q] '' | | | | |Shape [id R] '' | | | | | |Rebroadcast{(0, False)} [id J] '' | | | | |ScalarConstant{1} [id S] | | | |Rebroadcast{(0, False)} [id J] '' | | | |ScalarFromTensor [id T] '' | | | |Subtensor{int64} [id H] '' | | |A [id M] | |ScalarConstant{1} [id U] |ScalarConstant{-1} [id V] Inner graphs: for{cpu,scan_fn} [id C] '' >Elemwise{mul,no_inplace} [id W] '' > |<TensorType(float64, vector)> [id X] -> [id E] > |A_copy [id Y] -> [id M]""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_scan_debugprint5(): k = iscalar("k") A = dvector("A") # Symbolic description of the result result, updates = aesara.scan( fn=lambda prior_result, A: prior_result * A, outputs_info=aet.ones_like(A), non_sequences=A, n_steps=k, ) final_result = aesara.grad(result[-1].sum(), A) output_str = debugprint(final_result, file="str") lines = output_str.split("\n") expected_output = """Subtensor{int64} [id A] '' |for{cpu,grad_of_scan_fn}.1 [id B] '' | |Elemwise{sub,no_inplace} [id C] '' | | |Subtensor{int64} [id D] '' | | | |Shape [id E] '' | | | | |for{cpu,scan_fn} [id F] '' | | | | |k [id G] | | | | |IncSubtensor{Set;:int64:} [id H] '' | | | | | |AllocEmpty{dtype='float64'} [id I] '' | | | | | | |Elemwise{add,no_inplace} [id J] '' | | | | | | | |k [id G] | | | | | | | |Subtensor{int64} [id K] '' | | | | | | | |Shape [id L] '' | | | | | | | | |Rebroadcast{(0, False)} [id M] '' | | | | | | | | |InplaceDimShuffle{x,0} [id N] '' | | | | | | | | |Elemwise{second,no_inplace} [id O] '' | | | | | | | | |A [id P] | | | | | | | | |InplaceDimShuffle{x} [id Q] '' | | | | | | | | |TensorConstant{1.0} [id R] | | | | | | | |ScalarConstant{0} [id S] | | | | | | |Subtensor{int64} [id T] '' | | | | | | |Shape [id U] '' | | | | | | | |Rebroadcast{(0, False)} [id M] '' | | | | | | |ScalarConstant{1} [id V] | | | | | |Rebroadcast{(0, False)} [id M] '' | | | | | |ScalarFromTensor [id W] '' | | | | | |Subtensor{int64} [id K] '' | | | | |A [id P] | | | |ScalarConstant{0} [id X] | | |TensorConstant{1} [id Y] | |Subtensor{:int64:} [id Z] '' | | |Subtensor{::int64} [id BA] '' | | | |Subtensor{:int64:} [id BB] '' | | | | |for{cpu,scan_fn} [id F] '' | | | | |ScalarConstant{-1} [id BC] | | | |ScalarConstant{-1} [id BD] | | |ScalarFromTensor [id BE] '' | | |Elemwise{sub,no_inplace} [id C] '' | |Subtensor{:int64:} [id BF] '' | | |Subtensor{:int64:} [id BG] '' | | | |Subtensor{::int64} [id BH] '' | | | | |for{cpu,scan_fn} [id F] '' | | | | |ScalarConstant{-1} [id BI] | | | |ScalarConstant{-1} [id BJ] | | |ScalarFromTensor [id BK] '' | | |Elemwise{sub,no_inplace} [id C] '' | |Subtensor{::int64} [id BL] '' | | |IncSubtensor{Inc;int64::} [id BM] '' | | | |Elemwise{second,no_inplace} [id BN] '' | | | | |for{cpu,scan_fn} [id F] '' | | | | |InplaceDimShuffle{x,x} [id BO] '' | | | | |TensorConstant{0.0} [id BP] | | | |IncSubtensor{Inc;int64} [id BQ] '' | | | | |Elemwise{second,no_inplace} [id BR] '' | | | | | |Subtensor{int64::} [id BS] '' | | | | | | |for{cpu,scan_fn} [id F] '' | | | | | | |ScalarConstant{1} [id BT] | | | | | |InplaceDimShuffle{x,x} [id BU] '' | | | | | |TensorConstant{0.0} [id BV] | | | | |Elemwise{second} [id BW] '' | | | | | |Subtensor{int64} [id BX] '' | | | | | | |Subtensor{int64::} [id BS] '' | | | | | | |ScalarConstant{-1} [id BY] | | | | | |InplaceDimShuffle{x} [id BZ] '' | | | | | |Elemwise{second,no_inplace} [id CA] '' | | | | | |Sum{acc_dtype=float64} [id CB] '' | | | | | | |Subtensor{int64} [id BX] '' | | | | | |TensorConstant{1.0} [id CC] | | | | |ScalarConstant{-1} [id BY] | | | |ScalarConstant{1} [id BT] | | |ScalarConstant{-1} [id CD] | |Alloc [id CE] '' | | |TensorConstant{0.0} [id CF] | | |Elemwise{add,no_inplace} [id CG] '' | | | |Elemwise{sub,no_inplace} [id C] '' | | | |TensorConstant{1} [id CH] | | |Subtensor{int64} [id CI] '' | | |Shape [id CJ] '' | | | |A [id P] | | |ScalarConstant{0} [id CK] | |A [id P] |ScalarConstant{-1} [id CL] Inner graphs: for{cpu,grad_of_scan_fn}.1 [id B] '' >Elemwise{add,no_inplace} [id CM] '' > |Elemwise{mul} [id CN] '' > | |<TensorType(float64, vector)> [id CO] -> [id BL] > | |A_copy [id CP] -> [id P] > |<TensorType(float64, vector)> [id CQ] -> [id BL] >Elemwise{add,no_inplace} [id CR] '' > |Elemwise{mul} [id CS] '' > | |<TensorType(float64, vector)> [id CO] -> [id BL] > | |<TensorType(float64, vector)> [id CT] -> [id Z] > |<TensorType(float64, vector)> [id CU] -> [id CE] for{cpu,scan_fn} [id F] '' >Elemwise{mul,no_inplace} [id CV] '' > |<TensorType(float64, vector)> [id CT] -> [id H] > |A_copy [id CP] -> [id P] for{cpu,scan_fn} [id F] '' >Elemwise{mul,no_inplace} [id CV] '' for{cpu,scan_fn} [id F] '' >Elemwise{mul,no_inplace} [id CV] '' for{cpu,scan_fn} [id F] '' >Elemwise{mul,no_inplace} [id CV] '' for{cpu,scan_fn} [id F] '' >Elemwise{mul,no_inplace} [id CV] ''""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_debugprint_nitsot(): coefficients = vector("coefficients") x = scalar("x") max_coefficients_supported = 10000 # Generate the components of the polynomial components, updates = aesara.scan( fn=lambda coefficient, power, free_variable: coefficient * (free_variable**power), outputs_info=None, sequences=[coefficients, at.arange(max_coefficients_supported)], non_sequences=x, ) # Sum them up polynomial = components.sum() output_str = debugprint(polynomial, file="str", print_op_info=True) lines = output_str.split("\n") expected_output = """Sum{acc_dtype=float64} [id A] |for{cpu,scan_fn} [id B] (outer_out_nit_sot-0) |Elemwise{scalar_minimum,no_inplace} [id C] (outer_in_nit_sot-0) | |Subtensor{int64} [id D] | | |Shape [id E] | | | |Subtensor{int64::} [id F] 'coefficients[0:]' | | | |coefficients [id G] | | | |ScalarConstant{0} [id H] | | |ScalarConstant{0} [id I] | |Subtensor{int64} [id J] | |Shape [id K] | | |Subtensor{int64::} [id L] | | |ARange{dtype='int64'} [id M] | | | |TensorConstant{0} [id N] | | | |TensorConstant{10000} [id O] | | | |TensorConstant{1} [id P] | | |ScalarConstant{0} [id Q] | |ScalarConstant{0} [id R] |Subtensor{:int64:} [id S] (outer_in_seqs-0) | |Subtensor{int64::} [id F] 'coefficients[0:]' | |ScalarFromTensor [id T] | |Elemwise{scalar_minimum,no_inplace} [id C] |Subtensor{:int64:} [id U] (outer_in_seqs-1) | |Subtensor{int64::} [id L] | |ScalarFromTensor [id V] | |Elemwise{scalar_minimum,no_inplace} [id C] |Elemwise{scalar_minimum,no_inplace} [id C] (outer_in_nit_sot-0) |x [id W] (outer_in_non_seqs-0) Inner graphs: for{cpu,scan_fn} [id B] (outer_out_nit_sot-0) >Elemwise{mul,no_inplace} [id X] (inner_out_nit_sot-0) > |*0-<TensorType(float64, ())> [id Y] -> [id S] (inner_in_seqs-0) > |Elemwise{pow,no_inplace} [id Z] > |*2-<TensorType(float64, ())> [id BA] -> [id W] (inner_in_non_seqs-0) > |*1-<TensorType(int64, ())> [id BB] -> [id U] (inner_in_seqs-1)""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_scan_debugprint3(): coefficients = dvector("coefficients") max_coefficients_supported = 10 k = iscalar("k") A = dvector("A") # compute A**k def compute_A_k(A, k): # Symbolic description of the result result, updates = aesara.scan( fn=lambda prior_result, A: prior_result * A, outputs_info=aet.ones_like(A), non_sequences=A, n_steps=k, ) A_k = result[-1] return A_k # Generate the components of the polynomial components, updates = aesara.scan( fn=lambda coefficient, power, some_A, some_k: coefficient * (compute_A_k(some_A, some_k)**power), outputs_info=None, sequences=[coefficients, aet.arange(max_coefficients_supported)], non_sequences=[A, k], ) # Sum them up polynomial = components.sum() final_result = polynomial output_str = debugprint(final_result, file="str") lines = output_str.split("\n") expected_output = """Sum{acc_dtype=float64} [id A] '' |for{cpu,scan_fn} [id B] '' |Elemwise{scalar_minimum,no_inplace} [id C] '' | |Subtensor{int64} [id D] '' | | |Shape [id E] '' | | | |Subtensor{int64::} [id F] 'coefficients[0:]' | | | |coefficients [id G] | | | |ScalarConstant{0} [id H] | | |ScalarConstant{0} [id I] | |Subtensor{int64} [id J] '' | |Shape [id K] '' | | |Subtensor{int64::} [id L] '' | | |ARange{dtype='int64'} [id M] '' | | | |TensorConstant{0} [id N] | | | |TensorConstant{10} [id O] | | | |TensorConstant{1} [id P] | | |ScalarConstant{0} [id Q] | |ScalarConstant{0} [id R] |Subtensor{:int64:} [id S] '' | |Subtensor{int64::} [id F] 'coefficients[0:]' | |ScalarFromTensor [id T] '' | |Elemwise{scalar_minimum,no_inplace} [id C] '' |Subtensor{:int64:} [id U] '' | |Subtensor{int64::} [id L] '' | |ScalarFromTensor [id V] '' | |Elemwise{scalar_minimum,no_inplace} [id C] '' |Elemwise{scalar_minimum,no_inplace} [id C] '' |A [id W] |k [id X] Inner graphs: for{cpu,scan_fn} [id B] '' >Elemwise{mul,no_inplace} [id Y] '' > |InplaceDimShuffle{x} [id Z] '' > | |coefficients[t] [id BA] -> [id S] > |Elemwise{pow,no_inplace} [id BB] '' > |Subtensor{int64} [id BC] '' > | |Subtensor{int64::} [id BD] '' > | | |for{cpu,scan_fn} [id BE] '' > | | | |k_copy [id BF] -> [id X] > | | | |IncSubtensor{Set;:int64:} [id BG] '' > | | | | |AllocEmpty{dtype='float64'} [id BH] '' > | | | | | |Elemwise{add,no_inplace} [id BI] '' > | | | | | | |k_copy [id BF] -> [id X] > | | | | | | |Subtensor{int64} [id BJ] '' > | | | | | | |Shape [id BK] '' > | | | | | | | |Rebroadcast{(0, False)} [id BL] '' > | | | | | | | |InplaceDimShuffle{x,0} [id BM] '' > | | | | | | | |Elemwise{second,no_inplace} [id BN] '' > | | | | | | | |A_copy [id BO] -> [id W] > | | | | | | | |InplaceDimShuffle{x} [id BP] '' > | | | | | | | |TensorConstant{1.0} [id BQ] > | | | | | | |ScalarConstant{0} [id BR] > | | | | | |Subtensor{int64} [id BS] '' > | | | | | |Shape [id BT] '' > | | | | | | |Rebroadcast{(0, False)} [id BL] '' > | | | | | |ScalarConstant{1} [id BU] > | | | | |Rebroadcast{(0, False)} [id BL] '' > | | | | |ScalarFromTensor [id BV] '' > | | | | |Subtensor{int64} [id BJ] '' > | | | |A_copy [id BO] -> [id W] > | | |ScalarConstant{1} [id BW] > | |ScalarConstant{-1} [id BX] > |InplaceDimShuffle{x} [id BY] '' > |<TensorType(int64, scalar)> [id BZ] -> [id U] for{cpu,scan_fn} [id BE] '' >Elemwise{mul,no_inplace} [id CA] '' > |<TensorType(float64, vector)> [id CB] -> [id BG] > |A_copy [id CC] -> [id BO]""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_scan_debugprint4(): def fn(a_m2, a_m1, b_m2, b_m1): return a_m1 + a_m2, b_m1 + b_m2 a0 = aesara.shared(np.arange(2, dtype="int64")) b0 = aesara.shared(np.arange(2, dtype="int64")) (a, b), _ = aesara.scan( fn, outputs_info=[ { "initial": a0, "taps": [-2, -1] }, { "initial": b0, "taps": [-2, -1] }, ], n_steps=5, ) final_result = a + b output_str = debugprint(final_result, file="str") lines = output_str.split("\n") expected_output = """Elemwise{add,no_inplace} [id A] '' |Subtensor{int64::} [id B] '' | |for{cpu,scan_fn}.0 [id C] '' | | |TensorConstant{5} [id D] | | |IncSubtensor{Set;:int64:} [id E] '' | | | |AllocEmpty{dtype='int64'} [id F] '' | | | | |Elemwise{add,no_inplace} [id G] '' | | | | |TensorConstant{5} [id D] | | | | |Subtensor{int64} [id H] '' | | | | |Shape [id I] '' | | | | | |Subtensor{:int64:} [id J] '' | | | | | |<TensorType(int64, vector)> [id K] | | | | | |ScalarConstant{2} [id L] | | | | |ScalarConstant{0} [id M] | | | |Subtensor{:int64:} [id J] '' | | | |ScalarFromTensor [id N] '' | | | |Subtensor{int64} [id H] '' | | |IncSubtensor{Set;:int64:} [id O] '' | | |AllocEmpty{dtype='int64'} [id P] '' | | | |Elemwise{add,no_inplace} [id Q] '' | | | |TensorConstant{5} [id D] | | | |Subtensor{int64} [id R] '' | | | |Shape [id S] '' | | | | |Subtensor{:int64:} [id T] '' | | | | |<TensorType(int64, vector)> [id U] | | | | |ScalarConstant{2} [id V] | | | |ScalarConstant{0} [id W] | | |Subtensor{:int64:} [id T] '' | | |ScalarFromTensor [id X] '' | | |Subtensor{int64} [id R] '' | |ScalarConstant{2} [id Y] |Subtensor{int64::} [id Z] '' |for{cpu,scan_fn}.1 [id C] '' |ScalarConstant{2} [id BA] Inner graphs: for{cpu,scan_fn}.0 [id C] '' >Elemwise{add,no_inplace} [id BB] '' > |<TensorType(int64, scalar)> [id BC] -> [id E] > |<TensorType(int64, scalar)> [id BD] -> [id E] >Elemwise{add,no_inplace} [id BE] '' > |<TensorType(int64, scalar)> [id BF] -> [id O] > |<TensorType(int64, scalar)> [id BG] -> [id O] for{cpu,scan_fn}.1 [id C] '' >Elemwise{add,no_inplace} [id BB] '' >Elemwise{add,no_inplace} [id BE] ''""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_debugprint_mitsot(): def fn(a_m2, a_m1, b_m2, b_m1): return a_m1 + a_m2, b_m1 + b_m2 a0 = aesara.shared(np.arange(2, dtype="int64")) b0 = aesara.shared(np.arange(2, dtype="int64")) (a, b), _ = aesara.scan( fn, outputs_info=[ { "initial": a0, "taps": [-2, -1] }, { "initial": b0, "taps": [-2, -1] }, ], n_steps=5, ) final_result = a + b output_str = debugprint(final_result, file="str", print_op_info=True) lines = output_str.split("\n") expected_output = """Elemwise{add,no_inplace} [id A] |Subtensor{int64::} [id B] | |for{cpu,scan_fn}.0 [id C] (outer_out_mit_sot-0) | | |TensorConstant{5} [id D] (n_steps) | | |IncSubtensor{Set;:int64:} [id E] (outer_in_mit_sot-0) | | | |AllocEmpty{dtype='int64'} [id F] | | | | |Elemwise{add,no_inplace} [id G] | | | | |TensorConstant{5} [id D] | | | | |Subtensor{int64} [id H] | | | | |Shape [id I] | | | | | |Subtensor{:int64:} [id J] | | | | | |<TensorType(int64, (None,))> [id K] | | | | | |ScalarConstant{2} [id L] | | | | |ScalarConstant{0} [id M] | | | |Subtensor{:int64:} [id J] | | | |ScalarFromTensor [id N] | | | |Subtensor{int64} [id H] | | |IncSubtensor{Set;:int64:} [id O] (outer_in_mit_sot-1) | | |AllocEmpty{dtype='int64'} [id P] | | | |Elemwise{add,no_inplace} [id Q] | | | |TensorConstant{5} [id D] | | | |Subtensor{int64} [id R] | | | |Shape [id S] | | | | |Subtensor{:int64:} [id T] | | | | |<TensorType(int64, (None,))> [id U] | | | | |ScalarConstant{2} [id V] | | | |ScalarConstant{0} [id W] | | |Subtensor{:int64:} [id T] | | |ScalarFromTensor [id X] | | |Subtensor{int64} [id R] | |ScalarConstant{2} [id Y] |Subtensor{int64::} [id Z] |for{cpu,scan_fn}.1 [id C] (outer_out_mit_sot-1) |ScalarConstant{2} [id BA] Inner graphs: for{cpu,scan_fn}.0 [id C] (outer_out_mit_sot-0) >Elemwise{add,no_inplace} [id BB] (inner_out_mit_sot-0) > |*1-<TensorType(int64, ())> [id BC] -> [id E] (inner_in_mit_sot-0-1) > |*0-<TensorType(int64, ())> [id BD] -> [id E] (inner_in_mit_sot-0-0) >Elemwise{add,no_inplace} [id BE] (inner_out_mit_sot-1) > |*3-<TensorType(int64, ())> [id BF] -> [id O] (inner_in_mit_sot-1-1) > |*2-<TensorType(int64, ())> [id BG] -> [id O] (inner_in_mit_sot-1-0) for{cpu,scan_fn}.1 [id C] (outer_out_mit_sot-1) >Elemwise{add,no_inplace} [id BB] (inner_out_mit_sot-0) >Elemwise{add,no_inplace} [id BE] (inner_out_mit_sot-1)""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_debugprint_inner_graph(): r1, r2 = MyVariable("1"), MyVariable("2") o1 = MyOp("op1")(r1, r2) o1.name = "o1" # Inner graph igo_in_1 = MyVariable("4") igo_in_2 = MyVariable("5") igo_out_1 = MyOp("op2")(igo_in_1, igo_in_2) igo_out_1.name = "igo1" igo = MyInnerGraphOp([igo_in_1, igo_in_2], [igo_out_1]) r3, r4 = MyVariable("3"), MyVariable("4") out = igo(r3, r4) output_str = debugprint(out, file="str") lines = output_str.split("\n") exp_res = """MyInnerGraphOp [id A] |3 [id B] |4 [id C] Inner graphs: MyInnerGraphOp [id A] >op2 [id D] 'igo1' > |*0-<MyType()> [id E] > |*1-<MyType()> [id F] """ for exp_line, res_line in zip(exp_res.split("\n"), lines): assert exp_line.strip() == res_line.strip() # Test nested inner-graph `Op`s igo_2 = MyInnerGraphOp([r3, r4], [out]) r5 = MyVariable("5") out_2 = igo_2(r5) output_str = debugprint(out_2, file="str") lines = output_str.split("\n") exp_res = """MyInnerGraphOp [id A] |5 [id B] Inner graphs: MyInnerGraphOp [id A] >MyInnerGraphOp [id C] > |*0-<MyType()> [id D] > |*1-<MyType()> [id E] MyInnerGraphOp [id C] >op2 [id F] 'igo1' > |*0-<MyType()> [id D] > |*1-<MyType()> [id E] """ for exp_line, res_line in zip(exp_res.split("\n"), lines): assert exp_line.strip() == res_line.strip()
def test_debugprint(): with pytest.raises(TypeError): debugprint("blah") A = matrix(name="A") B = matrix(name="B") C = A + B C.name = "C" D = matrix(name="D") E = matrix(name="E") F = D + E G = C + F mode = aesara.compile.get_default_mode().including("fusion") g = aesara.function([A, B, D, E], G, mode=mode) # just test that it work s = StringIO() debugprint(G, file=s) # test ids=int s = StringIO() debugprint(G, file=s, ids="int") s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} [id 0]", " |Elemwise{add,no_inplace} [id 1] 'C'", " | |A [id 2]", " | |B [id 3]", " |Elemwise{add,no_inplace} [id 4]", " |D [id 5]", " |E [id 6]", ]) + "\n") assert s == reference # test ids=CHAR s = StringIO() debugprint(G, file=s, ids="CHAR") s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} [id A]", " |Elemwise{add,no_inplace} [id B] 'C'", " | |A [id C]", " | |B [id D]", " |Elemwise{add,no_inplace} [id E]", " |D [id F]", " |E [id G]", ]) + "\n") assert s == reference # test ids=CHAR, stop_on_name=True s = StringIO() debugprint(G, file=s, ids="CHAR", stop_on_name=True) s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} [id A]", " |Elemwise{add,no_inplace} [id B] 'C'", " |Elemwise{add,no_inplace} [id C]", " |D [id D]", " |E [id E]", ]) + "\n") assert s == reference # test ids= s = StringIO() debugprint(G, file=s, ids="") s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace}", " |Elemwise{add,no_inplace} 'C'", " | |A", " | |B", " |Elemwise{add,no_inplace}", " |D", " |E", ]) + "\n") assert s == reference # test print_storage=True s = StringIO() debugprint(g, file=s, ids="", print_storage=True) s = s.getvalue() reference = ("\n".join([ "Elemwise{add,no_inplace} 0 [None]", " |A [None]", " |B [None]", " |D [None]", " |E [None]", ]) + "\n") assert s == reference A = dmatrix(name="A") B = dmatrix(name="B") D = dmatrix(name="D") J = dvector() s = StringIO() debugprint( aesara.function([A, B, D, J], A + (B.dot(J) - D), mode="FAST_RUN"), file=s, ids="", print_destroy_map=True, print_view_map=True, ) s = s.getvalue() exp_res = r"""Elemwise{Composite{(i0 + (i1 - i2))}} 4 |A |InplaceDimShuffle{x,0} v={0: [0]} 3 | |CGemv{inplace} d={0: [0]} 2 | |AllocEmpty{dtype='float64'} 1 | | |Shape_i{0} 0 | | |B | |TensorConstant{1.0} | |B | |<TensorType(float64, (None,))> | |TensorConstant{0.0} |D """ assert [l.strip() for l in s.split("\n") ] == [l.strip() for l in exp_res.split("\n")]
def test_debugprint(): with pytest.raises(TypeError): debugprint("blah") A = matrix(name="A") B = matrix(name="B") C = A + B C.name = "C" D = matrix(name="D") E = matrix(name="E") F = D + E G = C + F mode = aesara.compile.get_default_mode().including("fusion") g = aesara.function([A, B, D, E], G, mode=mode) # just test that it work s = StringIO() debugprint(G, file=s) # test ids=int s = StringIO() debugprint(G, file=s, ids="int") s = s.getvalue() # The additional white space are needed! reference = ( "\n".join( [ "Elemwise{add,no_inplace} [id 0] '' ", " |Elemwise{add,no_inplace} [id 1] 'C' ", " | |A [id 2]", " | |B [id 3]", " |Elemwise{add,no_inplace} [id 4] '' ", " |D [id 5]", " |E [id 6]", ] ) + "\n" ) if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test ids=CHAR s = StringIO() debugprint(G, file=s, ids="CHAR") s = s.getvalue() # The additional white space are needed! reference = ( "\n".join( [ "Elemwise{add,no_inplace} [id A] '' ", " |Elemwise{add,no_inplace} [id B] 'C' ", " | |A [id C]", " | |B [id D]", " |Elemwise{add,no_inplace} [id E] '' ", " |D [id F]", " |E [id G]", ] ) + "\n" ) if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test ids=CHAR, stop_on_name=True s = StringIO() debugprint(G, file=s, ids="CHAR", stop_on_name=True) s = s.getvalue() # The additional white space are needed! reference = ( "\n".join( [ "Elemwise{add,no_inplace} [id A] '' ", " |Elemwise{add,no_inplace} [id B] 'C' ", " |Elemwise{add,no_inplace} [id C] '' ", " |D [id D]", " |E [id E]", ] ) + "\n" ) if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test ids= s = StringIO() debugprint(G, file=s, ids="") s = s.getvalue() # The additional white space are needed! reference = ( "\n".join( [ "Elemwise{add,no_inplace} '' ", " |Elemwise{add,no_inplace} 'C' ", " | |A ", " | |B ", " |Elemwise{add,no_inplace} '' ", " |D ", " |E ", ] ) + "\n" ) if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test print_storage=True s = StringIO() debugprint(g, file=s, ids="", print_storage=True) s = s.getvalue() # The additional white space are needed! reference = ( "\n".join( [ "Elemwise{add,no_inplace} '' 0 [None]", " |A [None]", " |B [None]", " |D [None]", " |E [None]", ] ) + "\n" ) if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference
def test_debugprint_nested_scans(): c = dvector("c") n = 10 k = iscalar("k") A = dvector("A") def compute_A_k(A, k): result, updates = aesara.scan( fn=lambda prior_result, A: prior_result * A, outputs_info=at.ones_like(A), non_sequences=A, n_steps=k, ) A_k = result[-1] return A_k components, updates = aesara.scan( fn=lambda c, power, some_A, some_k: c * (compute_A_k(some_A, some_k)**power), outputs_info=None, sequences=[c, at.arange(n)], non_sequences=[A, k], ) final_result = components.sum() output_str = debugprint(final_result, file="str", print_op_info=True) lines = output_str.split("\n") expected_output = """Sum{acc_dtype=float64} [id A] |for{cpu,scan_fn} [id B] (outer_out_nit_sot-0) |Elemwise{scalar_minimum,no_inplace} [id C] (outer_in_nit_sot-0) | |Subtensor{int64} [id D] | | |Shape [id E] | | | |Subtensor{int64::} [id F] 'c[0:]' | | | |c [id G] | | | |ScalarConstant{0} [id H] | | |ScalarConstant{0} [id I] | |Subtensor{int64} [id J] | |Shape [id K] | | |Subtensor{int64::} [id L] | | |ARange{dtype='int64'} [id M] | | | |TensorConstant{0} [id N] | | | |TensorConstant{10} [id O] | | | |TensorConstant{1} [id P] | | |ScalarConstant{0} [id Q] | |ScalarConstant{0} [id R] |Subtensor{:int64:} [id S] (outer_in_seqs-0) | |Subtensor{int64::} [id F] 'c[0:]' | |ScalarFromTensor [id T] | |Elemwise{scalar_minimum,no_inplace} [id C] |Subtensor{:int64:} [id U] (outer_in_seqs-1) | |Subtensor{int64::} [id L] | |ScalarFromTensor [id V] | |Elemwise{scalar_minimum,no_inplace} [id C] |Elemwise{scalar_minimum,no_inplace} [id C] (outer_in_nit_sot-0) |A [id W] (outer_in_non_seqs-0) |k [id X] (outer_in_non_seqs-1) Inner graphs: for{cpu,scan_fn} [id B] (outer_out_nit_sot-0) >Elemwise{mul,no_inplace} [id Y] (inner_out_nit_sot-0) > |InplaceDimShuffle{x} [id Z] > | |*0-<TensorType(float64, ())> [id BA] -> [id S] (inner_in_seqs-0) > |Elemwise{pow,no_inplace} [id BB] > |Subtensor{int64} [id BC] > | |Subtensor{int64::} [id BD] > | | |for{cpu,scan_fn} [id BE] (outer_out_sit_sot-0) > | | | |*3-<TensorType(int32, ())> [id BF] -> [id X] (inner_in_non_seqs-1) (n_steps) > | | | |IncSubtensor{Set;:int64:} [id BG] (outer_in_sit_sot-0) > | | | | |AllocEmpty{dtype='float64'} [id BH] > | | | | | |Elemwise{add,no_inplace} [id BI] > | | | | | | |*3-<TensorType(int32, ())> [id BF] -> [id X] (inner_in_non_seqs-1) > | | | | | | |Subtensor{int64} [id BJ] > | | | | | | |Shape [id BK] > | | | | | | | |Rebroadcast{(0, False)} [id BL] > | | | | | | | |InplaceDimShuffle{x,0} [id BM] > | | | | | | | |Elemwise{second,no_inplace} [id BN] > | | | | | | | |*2-<TensorType(float64, (None,))> [id BO] -> [id W] (inner_in_non_seqs-0) > | | | | | | | |InplaceDimShuffle{x} [id BP] > | | | | | | | |TensorConstant{1.0} [id BQ] > | | | | | | |ScalarConstant{0} [id BR] > | | | | | |Subtensor{int64} [id BS] > | | | | | |Shape [id BT] > | | | | | | |Rebroadcast{(0, False)} [id BL] > | | | | | |ScalarConstant{1} [id BU] > | | | | |Rebroadcast{(0, False)} [id BL] > | | | | |ScalarFromTensor [id BV] > | | | | |Subtensor{int64} [id BJ] > | | | |*2-<TensorType(float64, (None,))> [id BO] -> [id W] (inner_in_non_seqs-0) (outer_in_non_seqs-0) > | | |ScalarConstant{1} [id BW] > | |ScalarConstant{-1} [id BX] > |InplaceDimShuffle{x} [id BY] > |*1-<TensorType(int64, ())> [id BZ] -> [id U] (inner_in_seqs-1) for{cpu,scan_fn} [id BE] (outer_out_sit_sot-0) >Elemwise{mul,no_inplace} [id CA] (inner_out_sit_sot-0) > |*0-<TensorType(float64, (None,))> [id CB] -> [id BG] (inner_in_sit_sot-0) > |*1-<TensorType(float64, (None,))> [id CC] -> [id BO] (inner_in_non_seqs-0)""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip() fg = FunctionGraph([c, k, A], [final_result]) output_str = debugprint(fg, file="str", print_op_info=True, print_fgraph_inputs=True) lines = output_str.split("\n") expected_output = """-c [id A] -k [id B] -A [id C] Sum{acc_dtype=float64} [id D] 13 |for{cpu,scan_fn} [id E] 12 (outer_out_nit_sot-0) |Elemwise{scalar_minimum,no_inplace} [id F] 7 (outer_in_nit_sot-0) | |Subtensor{int64} [id G] 6 | | |Shape [id H] 5 | | | |Subtensor{int64::} [id I] 'c[0:]' 4 | | | |c [id A] | | | |ScalarConstant{0} [id J] | | |ScalarConstant{0} [id K] | |Subtensor{int64} [id L] 3 | |Shape [id M] 2 | | |Subtensor{int64::} [id N] 1 | | |ARange{dtype='int64'} [id O] 0 | | | |TensorConstant{0} [id P] | | | |TensorConstant{10} [id Q] | | | |TensorConstant{1} [id R] | | |ScalarConstant{0} [id S] | |ScalarConstant{0} [id T] |Subtensor{:int64:} [id U] 11 (outer_in_seqs-0) | |Subtensor{int64::} [id I] 'c[0:]' 4 | |ScalarFromTensor [id V] 10 | |Elemwise{scalar_minimum,no_inplace} [id F] 7 |Subtensor{:int64:} [id W] 9 (outer_in_seqs-1) | |Subtensor{int64::} [id N] 1 | |ScalarFromTensor [id X] 8 | |Elemwise{scalar_minimum,no_inplace} [id F] 7 |Elemwise{scalar_minimum,no_inplace} [id F] 7 (outer_in_nit_sot-0) |A [id C] (outer_in_non_seqs-0) |k [id B] (outer_in_non_seqs-1) Inner graphs: for{cpu,scan_fn} [id E] (outer_out_nit_sot-0) -*0-<TensorType(float64, ())> [id Y] -> [id U] (inner_in_seqs-0) -*1-<TensorType(int64, ())> [id Z] -> [id W] (inner_in_seqs-1) -*2-<TensorType(float64, (None,))> [id BA] -> [id C] (inner_in_non_seqs-0) -*3-<TensorType(int32, ())> [id BB] -> [id B] (inner_in_non_seqs-1) >Elemwise{mul,no_inplace} [id BC] (inner_out_nit_sot-0) > |InplaceDimShuffle{x} [id BD] > | |*0-<TensorType(float64, ())> [id Y] (inner_in_seqs-0) > |Elemwise{pow,no_inplace} [id BE] > |Subtensor{int64} [id BF] > | |Subtensor{int64::} [id BG] > | | |for{cpu,scan_fn} [id BH] (outer_out_sit_sot-0) > | | | |*3-<TensorType(int32, ())> [id BB] (inner_in_non_seqs-1) (n_steps) > | | | |IncSubtensor{Set;:int64:} [id BI] (outer_in_sit_sot-0) > | | | | |AllocEmpty{dtype='float64'} [id BJ] > | | | | | |Elemwise{add,no_inplace} [id BK] > | | | | | | |*3-<TensorType(int32, ())> [id BB] (inner_in_non_seqs-1) > | | | | | | |Subtensor{int64} [id BL] > | | | | | | |Shape [id BM] > | | | | | | | |Rebroadcast{(0, False)} [id BN] > | | | | | | | |InplaceDimShuffle{x,0} [id BO] > | | | | | | | |Elemwise{second,no_inplace} [id BP] > | | | | | | | |*2-<TensorType(float64, (None,))> [id BA] (inner_in_non_seqs-0) > | | | | | | | |InplaceDimShuffle{x} [id BQ] > | | | | | | | |TensorConstant{1.0} [id BR] > | | | | | | |ScalarConstant{0} [id BS] > | | | | | |Subtensor{int64} [id BT] > | | | | | |Shape [id BU] > | | | | | | |Rebroadcast{(0, False)} [id BN] > | | | | | |ScalarConstant{1} [id BV] > | | | | |Rebroadcast{(0, False)} [id BN] > | | | | |ScalarFromTensor [id BW] > | | | | |Subtensor{int64} [id BL] > | | | |*2-<TensorType(float64, (None,))> [id BA] (inner_in_non_seqs-0) (outer_in_non_seqs-0) > | | |ScalarConstant{1} [id BX] > | |ScalarConstant{-1} [id BY] > |InplaceDimShuffle{x} [id BZ] > |*1-<TensorType(int64, ())> [id Z] (inner_in_seqs-1) for{cpu,scan_fn} [id BH] (outer_out_sit_sot-0) -*0-<TensorType(float64, (None,))> [id CA] -> [id BI] (inner_in_sit_sot-0) -*1-<TensorType(float64, (None,))> [id CB] -> [id BA] (inner_in_non_seqs-0) >Elemwise{mul,no_inplace} [id CC] (inner_out_sit_sot-0) > |*0-<TensorType(float64, (None,))> [id CA] (inner_in_sit_sot-0) > |*1-<TensorType(float64, (None,))> [id CB] (inner_in_non_seqs-0)""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_debugprint_mitmot(): k = iscalar("k") A = dvector("A") # Symbolic description of the result result, updates = aesara.scan( fn=lambda prior_result, A: prior_result * A, outputs_info=at.ones_like(A), non_sequences=A, n_steps=k, ) final_result = aesara.grad(result[-1].sum(), A) output_str = debugprint(final_result, file="str", print_op_info=True) lines = output_str.split("\n") expected_output = """Subtensor{int64} [id A] |for{cpu,grad_of_scan_fn}.1 [id B] (outer_out_sit_sot-0) | |Elemwise{sub,no_inplace} [id C] (n_steps) | | |Subtensor{int64} [id D] | | | |Shape [id E] | | | | |for{cpu,scan_fn} [id F] (outer_out_sit_sot-0) | | | | |k [id G] (n_steps) | | | | |IncSubtensor{Set;:int64:} [id H] (outer_in_sit_sot-0) | | | | | |AllocEmpty{dtype='float64'} [id I] | | | | | | |Elemwise{add,no_inplace} [id J] | | | | | | | |k [id G] | | | | | | | |Subtensor{int64} [id K] | | | | | | | |Shape [id L] | | | | | | | | |Rebroadcast{(0, False)} [id M] | | | | | | | | |InplaceDimShuffle{x,0} [id N] | | | | | | | | |Elemwise{second,no_inplace} [id O] | | | | | | | | |A [id P] | | | | | | | | |InplaceDimShuffle{x} [id Q] | | | | | | | | |TensorConstant{1.0} [id R] | | | | | | | |ScalarConstant{0} [id S] | | | | | | |Subtensor{int64} [id T] | | | | | | |Shape [id U] | | | | | | | |Rebroadcast{(0, False)} [id M] | | | | | | |ScalarConstant{1} [id V] | | | | | |Rebroadcast{(0, False)} [id M] | | | | | |ScalarFromTensor [id W] | | | | | |Subtensor{int64} [id K] | | | | |A [id P] (outer_in_non_seqs-0) | | | |ScalarConstant{0} [id X] | | |TensorConstant{1} [id Y] | |Subtensor{:int64:} [id Z] (outer_in_seqs-0) | | |Subtensor{::int64} [id BA] | | | |Subtensor{:int64:} [id BB] | | | | |for{cpu,scan_fn} [id F] (outer_out_sit_sot-0) | | | | |ScalarConstant{-1} [id BC] | | | |ScalarConstant{-1} [id BD] | | |ScalarFromTensor [id BE] | | |Elemwise{sub,no_inplace} [id C] | |Subtensor{:int64:} [id BF] (outer_in_seqs-1) | | |Subtensor{:int64:} [id BG] | | | |Subtensor{::int64} [id BH] | | | | |for{cpu,scan_fn} [id F] (outer_out_sit_sot-0) | | | | |ScalarConstant{-1} [id BI] | | | |ScalarConstant{-1} [id BJ] | | |ScalarFromTensor [id BK] | | |Elemwise{sub,no_inplace} [id C] | |Subtensor{::int64} [id BL] (outer_in_mit_mot-0) | | |IncSubtensor{Inc;int64::} [id BM] | | | |Elemwise{second,no_inplace} [id BN] | | | | |for{cpu,scan_fn} [id F] (outer_out_sit_sot-0) | | | | |InplaceDimShuffle{x,x} [id BO] | | | | |TensorConstant{0.0} [id BP] | | | |IncSubtensor{Inc;int64} [id BQ] | | | | |Elemwise{second,no_inplace} [id BR] | | | | | |Subtensor{int64::} [id BS] | | | | | | |for{cpu,scan_fn} [id F] (outer_out_sit_sot-0) | | | | | | |ScalarConstant{1} [id BT] | | | | | |InplaceDimShuffle{x,x} [id BU] | | | | | |TensorConstant{0.0} [id BV] | | | | |Elemwise{second} [id BW] | | | | | |Subtensor{int64} [id BX] | | | | | | |Subtensor{int64::} [id BS] | | | | | | |ScalarConstant{-1} [id BY] | | | | | |InplaceDimShuffle{x} [id BZ] | | | | | |Elemwise{second,no_inplace} [id CA] | | | | | |Sum{acc_dtype=float64} [id CB] | | | | | | |Subtensor{int64} [id BX] | | | | | |TensorConstant{1.0} [id CC] | | | | |ScalarConstant{-1} [id BY] | | | |ScalarConstant{1} [id BT] | | |ScalarConstant{-1} [id CD] | |Alloc [id CE] (outer_in_sit_sot-0) | | |TensorConstant{0.0} [id CF] | | |Elemwise{add,no_inplace} [id CG] | | | |Elemwise{sub,no_inplace} [id C] | | | |TensorConstant{1} [id CH] | | |Subtensor{int64} [id CI] | | |Shape [id CJ] | | | |A [id P] | | |ScalarConstant{0} [id CK] | |A [id P] (outer_in_non_seqs-0) |ScalarConstant{-1} [id CL] Inner graphs: for{cpu,grad_of_scan_fn}.1 [id B] (outer_out_sit_sot-0) >Elemwise{add,no_inplace} [id CM] (inner_out_mit_mot-0-0) > |Elemwise{mul} [id CN] > | |*2-<TensorType(float64, (None,))> [id CO] -> [id BL] (inner_in_mit_mot-0-0) > | |*5-<TensorType(float64, (None,))> [id CP] -> [id P] (inner_in_non_seqs-0) > |*3-<TensorType(float64, (None,))> [id CQ] -> [id BL] (inner_in_mit_mot-0-1) >Elemwise{add,no_inplace} [id CR] (inner_out_sit_sot-0) > |Elemwise{mul} [id CS] > | |*2-<TensorType(float64, (None,))> [id CO] -> [id BL] (inner_in_mit_mot-0-0) > | |*0-<TensorType(float64, (None,))> [id CT] -> [id Z] (inner_in_seqs-0) > |*4-<TensorType(float64, (None,))> [id CU] -> [id CE] (inner_in_sit_sot-0) for{cpu,scan_fn} [id F] (outer_out_sit_sot-0) >Elemwise{mul,no_inplace} [id CV] (inner_out_sit_sot-0) > |*0-<TensorType(float64, (None,))> [id CT] -> [id H] (inner_in_sit_sot-0) > |*1-<TensorType(float64, (None,))> [id CW] -> [id P] (inner_in_non_seqs-0)""" for truth, out in zip(expected_output.split("\n"), lines): assert truth.strip() == out.strip()
def test_debugprint(): A = tensor.matrix(name="A") B = tensor.matrix(name="B") C = A + B C.name = "C" D = tensor.matrix(name="D") E = tensor.matrix(name="E") F = D + E G = C + F mode = aesara.compile.get_default_mode().including("fusion") g = aesara.function([A, B, D, E], G, mode=mode) # just test that it work s = StringIO() debugprint(G, file=s) # test ids=int s = StringIO() debugprint(G, file=s, ids="int") s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} [id 0] '' ", " |Elemwise{add,no_inplace} [id 1] 'C' ", " | |A [id 2]", " | |B [id 3]", " |Elemwise{add,no_inplace} [id 4] '' ", " |D [id 5]", " |E [id 6]", ]) + "\n") if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test ids=CHAR s = StringIO() debugprint(G, file=s, ids="CHAR") s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} [id A] '' ", " |Elemwise{add,no_inplace} [id B] 'C' ", " | |A [id C]", " | |B [id D]", " |Elemwise{add,no_inplace} [id E] '' ", " |D [id F]", " |E [id G]", ]) + "\n") if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test ids=CHAR, stop_on_name=True s = StringIO() debugprint(G, file=s, ids="CHAR", stop_on_name=True) s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} [id A] '' ", " |Elemwise{add,no_inplace} [id B] 'C' ", " |Elemwise{add,no_inplace} [id C] '' ", " |D [id D]", " |E [id E]", ]) + "\n") if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test ids= s = StringIO() debugprint(G, file=s, ids="") s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} '' ", " |Elemwise{add,no_inplace} 'C' ", " | |A ", " | |B ", " |Elemwise{add,no_inplace} '' ", " |D ", " |E ", ]) + "\n") if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test print_storage=True s = StringIO() debugprint(g, file=s, ids="", print_storage=True) s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} '' 0 [None]", " |A [None]", " |B [None]", " |D [None]", " |E [None]", ]) + "\n") if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference # test clients s = StringIO() # We must force the mode as otherwise it can change the clients order f = aesara.function([A, B, D], [A + B, A + B - D], mode="FAST_COMPILE") debugprint(f, file=s, print_clients=True) s = s.getvalue() # The additional white space are needed! reference = ("\n".join([ "Elemwise{add,no_inplace} [id A] '' 0 clients:[('output', ''), ('[id C]', 1)]", " |A [id D]", " |B [id E]", "Elemwise{sub,no_inplace} [id C] '' 1", " |Elemwise{add,no_inplace} [id A] '' 0 clients:[('output', ''), ('[id C]', 1)]", " |D [id F]", ]) + "\n") if s != reference: print("--" + s + "--") print("--" + reference + "--") assert s == reference