find_named_node#

pymc_marketing.mmm.counterfactual.find_named_node(roots, name, *, exclude=())[source]#

Find the one node of a graph that carries a given name.

Not every interesting quantity is a registered variable of a PyMC model: an MMM’s linear predictor is a Deterministic under a log link but only an anonymous intermediate carrying the name mu under an identity link, so it has to be recovered from the graph instead of looked up. Recovering it that way is sound only while the name picks out a single node, and graph traversal is unordered, so taking the first match would bind to whichever node happened to come up first. Downstream that decides whether the increment’s completeness check compares the right two quantities, and a wrong binding is invisible: it either refuses a correct model or passes a broken one. So an ambiguous name is refused rather than guessed at.

Parameters:
rootssequence of Variable

The nodes whose ancestors are searched. The roots themselves are part of the search, as ancestors() yields them.

namestr

The name to look for.

excludeiterable of Variable, optional

Nodes that may not be returned, compared by identity. The observed variable belongs here whenever it could carry the requested name itself, as a target column named after the quantity being searched for would otherwise resolve to the observation.

Returns:
Variable or None

The single node carrying name, or None if the graph carries no such node.

Raises:
ValueError

If more than one distinct node carries name, since no choice between them can be made reliably.

Notes

mu no longer reaches this function from a stock model. It is registered as a Deterministic under both links, so callers resolve it through named_vars and never scan the graph for it. A custom effect whose unregistered intermediate happens to be named mu is therefore shadowed by the model’s own node rather than colliding with it. This function still guards names that are not registered.

A custom effect that registers a Deterministic named mu is a different matter: PyMC enforces unique names, so under the identity link that combination now fails in build_model with Variable name mu already exists. It used to build, because the identity branch only set mu_var.name, which does not register. Such an effect has to be renamed.