{
	"cell_id": 4804704193557178778,
	"cells": [
		{
			"cell_id": 8047503705196211138,
			"cell_origin": "client",
			"cell_type": "latex",
			"cells": [
				{
					"cell_id": 10083330039593489527,
					"cell_origin": "client",
					"cell_type": "latex_view",
					"source": "\\package{cdb.core.trace}{Manipulating Trace objects}\n\nThis package defines functionality for manipulating nodes and expressions which define the \\verb|Trace| property"
				}
			],
			"hidden": true,
			"source": "\\package{cdb.core.trace}{Manipulating Trace objects}\n\nThis package defines functionality for manipulating nodes and expressions which define the \\verb|Trace| property"
		},
		{
			"cell_id": 17733580437840025116,
			"cell_origin": "client",
			"cell_type": "input",
			"source": "from cdb.utils.node import n_indices, nth_child, empty_sum\nfrom cdb.utils.develop import inherit_kernel\nfrom collections import defaultdict"
		},
		{
			"cell_id": 8325441738150275359,
			"cell_origin": "client",
			"cell_type": "latex",
			"cells": [
				{
					"cell_id": 8330453056931653295,
					"cell_origin": "client",
					"cell_type": "latex_view",
					"source": "\\algorithm{combine_traces(ex: Ex) -> Ex}{Combine separate trace nodes into one sum.}\n\nThis will only move nodes which it classifies as safe to do this on, checking that no objects which are non-scalar will be pulled inside the new trace node. If multiple nodes\nwith different names, but the Trace property defined, are found then they will be combined separately."
				}
			],
			"hidden": true,
			"source": "\\algorithm{combine_traces(ex: Ex) -> Ex}{Combine separate trace nodes into one sum.}\n\nThis will only move nodes which it classifies as safe to do this on, checking that no objects which are non-scalar will be pulled inside the new trace node. If multiple nodes\nwith different names, but the Trace property defined, are found then they will be combined separately."
		},
		{
			"cell_id": 12226727171243122299,
			"cell_origin": "client",
			"cell_type": "input",
			"source": "def combine_traces(ex):\n\t__cdbkernel__ = inherit_kernel()\n\tdef recurse(node):\n\t\tnonlocal __cdbkernel__\n\t\tif node.name == \"\\\\sum\":\n\t\t\t# Enumerate all trace terms\n\t\t\tnodes = defaultdict(list)\n\t\t\tfor i, child in enumerate(node.children()):\n\t\t\t\tif child.name == \"\\\\prod\":\n\t\t\t\t\t# Only allow Trace nodes with scalars outside\n\t\t\t\t\tcan_move = False\n\t\t\t\t\tname = \"\"\n\t\t\t\t\tfor obj in child.children():\n\t\t\t\t\t\tif Trace.get(obj) is not None:\n\t\t\t\t\t\t\tif can_move: # Already hit a Trace node, can't move\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\tname = obj.name\n\t\t\t\t\t\t\tcan_move = True\n\t\t\t\t\t\telif n_indices(obj) != 0 or ImplicitIndex.get(obj) is not None:\n\t\t\t\t\t\t\tcan_move = False\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\tif can_move:\n\t\t\t\t\t\tnodes[obj.name].append(i)\n\t\t\t\telif Trace.get(child) is not None:\n\t\t\t\t\tnodes[child.name].append(i)\n\n\t\t\t# Combine traces\n\t\t\tfor t in nodes:\n\t\t\t\tnew_node = node.append_child(Ex(t + \"{}\")).append_child(empty_sum())\n\t\t\t\tfor i, child in enumerate(node.children()):\n\t\t\t\t\tif i in nodes[t]:\n\t\t\t\t\t\tnew_term = new_node.append_child(child)\n\t\t\t\t\t\t# Remove the existing Trace\n\t\t\t\t\t\tif new_term.name == \"\\\\prod\":\n\t\t\t\t\t\t\tfor obj in new_term.children():\n\t\t\t\t\t\t\t\tif Trace.get(obj) is not None:\n\t\t\t\t\t\t\t\t\tr = nth_child(obj, 0)\n\t\t\t\t\t\t\t\t\tr := @(r):\n\t\t\t\t\t\t\t\t\tr *= Ex(obj.multiplier)\n\t\t\t\t\t\t\t\t\tobj = obj.replace(r)\n\t\t\t\t\t\telif Trace.get(new_term) is not None:\n\t\t\t\t\t\t\tr = nth_child(new_term, 0)\n\t\t\t\t\t\t\tr := @(r):\n\t\t\t\t\t\t\tr *= Ex(new_term.multiplier)\n\t\t\t\t\t\t\tnew_term = new_term.replace(r)\n\n\t\t\t# Remove old terms\n\t\t\tindices = list(i for t in nodes for i in nodes[t])\n\t\t\tfor i, child in enumerate(node.children()):\n\t\t\t\tif i in indices:\n\t\t\t\t\tchild.erase()\n\t\t\t\n\t\telse:\n\t\t\t# Go deeper\n\t\t\tfor child in node.children():\n\t\t\t\trecurse(child)\n\trecurse(ex.top())\n\tex.cleanup()\n\treturn ex"
		},
		{
			"cell_id": 1491461674503604418,
			"cell_origin": "client",
			"cell_type": "input",
			"cells": [
				{
					"cell_id": 1302745897165290177,
					"cell_origin": "server",
					"cell_type": "output",
					"source": "\\begin{verbatim}Test 1 passed\n\\end{verbatim}"
				}
			],
			"ignore_on_import": true,
			"source": "def test01():\n\t__cdbkernel__ = create_scope()\n\tTr{#}::Trace.\n\t{A, B, C, D}::NonCommuting.\n\tex := Tr{A B C D + C D A B + B C D A} - 2 * Tr{3 * D A B C}:\n\tcombine_traces(ex)\n\tassert ex == $Tr{A B C D + C D A B + B C D A - 6 D A B C}$\n\tprint(\"Test 1 passed\")\ntest01()"
		},
		{
			"cell_id": 2285946178549455777,
			"cell_origin": "client",
			"cell_type": "input",
			"source": ""
		}
	],
	"description": "Cadabra JSON notebook format",
	"version": 1.0
}
