FXTensor

FXTensor

A tensor with support for string-labeled dimensions and tensor operations.

FXTensor.profile

Get the tensor's profile as a list of lists [[domain], [codomain]].

FXTensor.labels

Get the tensor's string labels.

FXTensor.names

Axis names (domain, codomain).

FXTensor.rename

Return a copy with axis names replaced.

FXTensor.axis

Return the axis index of name.

FXTensor.get_label_index

Get the index of a label for a given axis.

FXTensor.get_index_label

Get the label for a given axis and index.

FXTensor.copy

FXTensor.composition

Standard tensor composition.

FXTensor.tensor_product

Perform tensor product operation.

FXTensor.marginalization

Marginalize out a part of the codomain by summing over it.

FXTensor.marginal

Keep the named codomain axes, in the order given, and sum out the rest.

FXTensor.marginalize

Sum out the named codomain axes in drop.

FXTensor.permute

Reorder the codomain axes into order.

FXTensor.observe

Condition a state on named outcomes.

FXTensor.discard_prefix

Discard a prefix of the codomain by summing over it.

FXTensor.first_marginalization

Marginalize out the second part of the codomain.

FXTensor.second_marginalization

Marginalize out the first part of the codomain.

FXTensor.partial_composition

Perform partial composition.

FXTensor.jointification

Create a joint state from two tensors.

FXTensor.conditionalization

Create a conditional probability distribution from a joint state.

FXTensor.conditional

Conditional of a kernel f: A → X ⊗ Y as A ⊗ X → Y.

FXTensor.is_conditionally_independent

Return whether X ⊥ Y | Z for codomain order X ⊗ Y ⊗ Z.

FXTensor.is_independent

Return whether X ⊥ Y when the codomain is X ⊗ Y.

FXTensor.conditional_product

Return the conditional product, with codomain X ⊗ Y ⊗ Z.

FXTensor.is_exchangeable

Return whether this state is invariant under every adjacent swap.

FXTensor.symmetrize

Return the average of this state over every permutation of X.

FXTensor.is_kolmogorov_consistent

Return whether discarding the last factor reproduces the previous state.

FXTensor.iid

Return the tensor product of n copies of p.

FXTensor.mixture_of_iid

Return prior ; copy_Θ^{(n)} ; kernel^{⊗n}.

FXTensor.bayesian_inversion

Bayesian inversion of f: X → Y with respect to prior: I → X.

FXTensor.support

Indicator tensor of the nonzero entries (same profile and labels).

FXTensor.almost_surely_equal

Check self = other prior-almost surely.

FXTensor.is_absolutely_continuous

Check self ≪ other: wherever other is zero, self is zero.

FXTensor.is_markov

Check if the tensor is a Markov tensor.

FXTensor.is_deterministic

Check whether every codomain slice is a point mass (one-hot).

FXTensor.from_json

Create a tensor from JSON data.

FXTensor.from_strands

Create a tensor from strands (string representation).

FXTensor.to_json

Convert the tensor to a JSON-serializable dictionary.

FXTensor.save_to_file

Save the tensor to a JSON file.

FXTensor.load_from_file

Load a tensor from a JSON file.

FXTensor.to_original_dict

Convert tensor to original dictionary format with 1-based indexing.

FXTensor.identity_tensor

Create an identity tensor.

FXTensor.copy_tensor

Create a diagonal copy tensor X → X^{⊗ n}.

FXTensor.delta_tensor

Create a delta tensor (identity matrix) with the given dimensions.

FXTensor.swap

Create a swap tensor.

FXTensor.exclamation

Create an exclamation tensor (discarding).

FXTensor.unit_tensor

Create a unit tensor (all ones) with the given dimensions.

class fxtensor_salmon.FXTensor(profile, data=None, names=None)[source]

A tensor with support for string-labeled dimensions and tensor operations.

Optional names give each axis a variable name. Names are not the labels of the values on an axis. names=None leaves the tensor unnamed.

Parameters:
  • profile (Union[List[List[Union[int, List[str]]]], Tuple[List[int], List[int]]])

  • data (Optional[np.ndarray])

  • names (Optional[Tuple[Optional[List[str]], Optional[List[str]]]])

property profile: List[List[int]]

Get the tensor’s profile as a list of lists [[domain], [codomain]].

property labels: Tuple[List[List[str]], List[List[str]]] | None

Get the tensor’s string labels.

property names: Tuple[List[str] | None, List[str] | None]

Axis names (domain, codomain).

(None, None) means the tensor was constructed without names. None on one side means that side has no axes. Names are unique across the tensor and are not value labels.

get_label_index(axis, label)[source]

Get the index of a label for a given axis.

Parameters:
  • axis (int)

  • label (str)

Return type:

int

get_index_label(axis, index)[source]

Get the label for a given axis and index.

Parameters:
  • axis (int)

  • index (int)

Return type:

str

copy()[source]
Return type:

FXTensor

almost_surely_equal(other, prior)

Check self = other prior-almost surely.

For f, g: X → Y and a state p: I → X this is Fritz’s p ; copy ; (id ⊗ f) = p ; copy ; (id ⊗ g); for finite tensors it means f(·|x) = g(·|x) for every x with p(x) > 0. Only profiles are compared, not labels.

Parameters:
Return type:

bool

axis(name)

Return the axis index of name.

Domain axes are counted first, then codomain axes, as in get_label_index().

Parameters:

name (str)

Return type:

int

bayesian_inversion(prior)

Bayesian inversion of f: X → Y with respect to prior: I → X.

Returns f†: Y → X with f†(x|y) = prior(x) f(y|x) / Σ_x' prior(x') f(y|x') (Cho & Jacobs 2017). Rows with zero evidence stay zero. Labels are swapped from self (or taken from prior for X).

Parameters:

prior (FXTensor)

Return type:

FXTensor

composition(other)

Standard tensor composition.

Parameters:

other (FXTensor)

Return type:

FXTensor

conditional(concat_start_index)

Conditional of a kernel f: A → X ⊗ Y as A ⊗ X → Y.

Generalizes conditionalization() to tensors with a domain. concat_start_index (1-based) is the first codomain axis of Y. Entries with f_X(x|a) = 0 stay zero, as in conditionalization(). For a state the result equals conditionalization(concat_start_index).

Parameters:

concat_start_index (int)

Return type:

FXTensor

classmethod conditional_product(p_xz, q_yz, on, atol=None, rtol=None)

Return the conditional product, with codomain X ⊗ Y ⊗ Z.

p_xz has codomain X ⊗ Z and q_yz has codomain Y ⊗ Z. on is the 1-based index of the first Z factor in both codomains, or a pair (on_p, on_q) when X and Y have different numbers of factors. Both arguments are states, or both are kernels with the same domain.

The value is p_Z ; copy_Z ; (p(x|z) ⊗ id_Z ⊗ q(y|z)) with Z then moved past Y. That diagram has wires X ⊗ Z ⊗ Y; the tensor returned here is X ⊗ Y ⊗ Z, which satisfies X ⊥ Y | Z. p_Z is the Z marginal of p_xz. The two Z marginals must agree within atol and rtol (defaults: FXTensor._ATOL and FXTensor._RTOL).

Raises:

ValueError – If on is out of range, the domains differ, the Z factor sizes differ, or the Z marginals disagree.

conditionalization(concat_start_index)

Create a conditional probability distribution from a joint state.

Parameters:

concat_start_index (int)

Return type:

FXTensor

classmethod copy_tensor(list_x, n=2)

Create a diagonal copy tensor X → X^{⊗ n}.

n=0 is discard (exclamation), n=1 is identity.

Parameters:
  • list_x (Union[List[int], List[List[str]]])

  • n (int)

Return type:

FXTensor

classmethod delta_tensor(dims)

Create a delta tensor (identity matrix) with the given dimensions.

Parameters:

dims (List[int])

Return type:

FXTensor

discard_prefix(start_B)

Discard a prefix of the codomain by summing over it.

Parameters:

start_B (int)

Return type:

FXTensor

classmethod exclamation(list_x)

Create an exclamation tensor (discarding).

Parameters:

list_x (List[int])

Return type:

FXTensor

first_marginalization(concat_start_index)

Marginalize out the second part of the codomain.

Parameters:

concat_start_index (int)

Return type:

FXTensor

classmethod from_json(json_data)

Create a tensor from JSON data.

A names entry, when present, is [domain names, codomain names]. JSON written before axis names existed has no names key; those tensors stay unnamed.

Parameters:

json_data (Dict[str, Any])

Return type:

FXTensor

classmethod from_strands(profile, strands)

Create a tensor from strands (string representation).

Parameters:
  • profile (Union[Tuple[List[int], List[int]], List[List[List[str]]]])

  • strands (Dict[str, Union[float, Fraction]])

Return type:

FXTensor

classmethod identity_tensor(list_x)

Create an identity tensor.

Parameters:

list_x (Union[List[int], List[List[str]]])

Return type:

FXTensor

classmethod iid(p, n)

Return the tensor product of n copies of p.

Labels are taken from p. For a state I → X the result is I → X^{⊗n}. n=1 returns a copy of p.

Raises:

ValueError – If p is not an FXTensor, or n is not a positive integer.

is_absolutely_continuous(other)

Check self ≪ other: wherever other is zero, self is zero.

For states this is the usual absolute continuity of distributions; for kernels f, g: A → X it holds input-wise, i.e. f(·|a) ≪ g(·|a) for every a (finite case of Fritz et al., arXiv:2308.00651). Only profiles are compared, not labels.

Parameters:

other (FXTensor)

Return type:

bool

is_conditionally_independent(split_x, split_y, atol=None, rtol=None)

Return whether X ⊥ Y | Z for codomain order X ⊗ Y ⊗ Z.

split_x and split_y are 1-based, like conditional. Factors 1 .. split_x - 1 are X, factors split_x .. split_y - 1 are Y, and the remaining factors are Z. Any of the three blocks may be empty. A state I → X ⊗ Y ⊗ Z and a kernel A → X ⊗ Y ⊗ Z use the same splits.

The predicate holds when self equals the conditional product of its X ⊗ Z and Y ⊗ Z marginals: the finite form of Fritz’s copy–discard equation (arXiv:1908.07021, Def. 12.1 for states and Def. 12.16 for kernels). Values are compared with numpy.allclose. atol and rtol default to FXTensor._ATOL and FXTensor._RTOL.

Raises:

ValueError – If a split is not a 1-based index in range.

is_deterministic()

Check whether every codomain slice is a point mass (one-hot).

In finite stochastic matrices this is equivalent to Fritz’s definition f ; copy = copy ; (f ⊗ f) for Markov kernels. Zero slices are not considered deterministic.

Return type:

bool

is_exchangeable(block=None, atol=None, rtol=None)

Return whether this state is invariant under every adjacent swap.

The state p: I → X^{⊗n} is exchangeable at position k (1-based) when

p ; (id^{⊗(k-1)} ⊗ swap(X, X) ⊗ id^{⊗(n-k-1)}) = p.

Swapping the k-th and (k+1)-th wires leaves p unchanged. The identity wires and the two swapped wires use (k-1) + 2 + (n-k-1) = n factors. Adjacent transpositions generate the symmetric group, so this checks k = 1 .. n-1. n < 2 is vacuously true.

block is the dimension list of one factor X. The default, None, takes each codomain axis as one factor; those axes must share a size. swap carries no labels, so the comparison is on data via numpy.allclose. atol and rtol default to FXTensor._ATOL and FXTensor._RTOL.

Raises:

ValueError – If self is not a state, or the codomain is not X^{⊗n}.

is_independent(split, atol=None, rtol=None)

Return whether X ⊥ Y when the codomain is X ⊗ Y.

split is the 1-based first factor of Y. This is is_conditionally_independent() with an empty Z. atol and rtol are forwarded.

Raises:

ValueError – If split is not a 1-based index in range.

classmethod is_kolmogorov_consistent(states, block=None, atol=None, rtol=None)

Return whether discarding the last factor reproduces the previous state.

states is the list [p_1, p_2, ..., p_N] with p_n: I → X^{⊗n} (so states[0] is p_1). The sequence is Kolmogorov consistent when, for every n ≥ 2,

p_n ; (id^{⊗(n-1)} ⊗ !) = p_{n-1}.

! is exclamation() on the last factor: discarding the n-th wire of p_n yields p_{n-1}. A list of length 0 or 1 is consistent. block selects X as in is_exchangeable(); the default is one axis, and states[n-1] must then have n axes of that size. Values are compared on data with numpy.allclose. atol and rtol default to FXTensor._ATOL and FXTensor._RTOL.

Raises:

ValueError – If an entry is not a state I → X^{⊗n} for that position, or the factors are not a common type X.

is_markov()

Check if the tensor is a Markov tensor.

For every domain index the codomain slice must sum to 1 (or 0, so that zero rows produced by conditionalization() are accepted). States (empty domain) always return False; check np.isclose(state.data.sum(), 1) for a normalized state.

Return type:

bool

jointification(other)

Create a joint state from two tensors.

Parameters:

other (FXTensor)

Return type:

FXTensor

classmethod load_from_file(filename)

Load a tensor from a JSON file.

Parameters:

filename (str)

Return type:

FXTensor

marginal(*keep)

Keep the named codomain axes, in the order given, and sum out the rest.

A middle axis can be kept or dropped. For a state p: I → A ⊗ B ⊗ C, p.marginal("B") equals p ; (! ⊗ id_B ⊗ !): the deterministic wiring that discards every codomain wire except B. Labels move with the kept axes. The domain is unchanged.

Parameters:

keep (str)

Return type:

FXTensor

marginalization(start_B)

Marginalize out a part of the codomain by summing over it.

Parameters:

start_B (int)

Return type:

FXTensor

marginalize(drop)

Sum out the named codomain axes in drop.

The remaining codomain axes stay in their original order. This is marginal of the complement of drop.

Parameters:

drop (Sequence[str])

Return type:

FXTensor

classmethod mixture_of_iid(prior, kernel, n)

Return prior ; copy_Θ^{(n)} ; kernel^{⊗n}.

prior is a state I → Θ and kernel is a kernel Θ → X. The result is a state I → X^{⊗n}: one draw from the prior, copied, then n independent samples from the kernel. It is exchangeable and, as n varies, Kolmogorov consistent. Codomain labels are the codomain labels of kernel, repeated n times.

Raises:

ValueError – If prior is not a state, the profiles do not meet, or n is not a positive integer.

observe(**evidence)

Condition a state on named outcomes.

evidence maps an axis name to a label, or to an integer index when that axis has no labels. The result is (posterior, probability): the posterior is the joint state on the remaining axes, in their original order, and the probability is the evidence. Observing several axes at once matches observing them one at a time; the probability is then the joint probability of all of the outcomes.

The posterior is the row of conditionalization() after permute() moves the observed wires to the front. Evidence 0 raises ValueError.

Raises:

ValueError – If self is not a state, a name or label is unknown, or the evidence has probability 0.

Return type:

Tuple[‘FXTensor’, float]

partial_composition(other, concat_start_index)

Perform partial composition.

Parameters:
  • other (FXTensor)

  • concat_start_index (int)

Return type:

FXTensor

permute(order)

Reorder the codomain axes into order.

The domain is unchanged. Labels move with their axes. order must be a permutation of the codomain names. For a state the codomain is the whole profile, so this reorders every axis.

Parameters:

order (Sequence[str])

Return type:

FXTensor

rename(**mapping)

Return a copy with axis names replaced.

Each keyword is an existing name and its value is the new name. Names that are not mentioned stay. The result must still be unique.

Parameters:

mapping (str)

Return type:

FXTensor

save_to_file(filename)

Save the tensor to a JSON file.

Parameters:

filename (str)

Return type:

None

second_marginalization(concat_start_index)

Marginalize out the first part of the codomain.

Parameters:

concat_start_index (int)

Return type:

FXTensor

support()

Indicator tensor of the nonzero entries (same profile and labels).

For a state p: I → X this is the support {x : p(x) > 0}; for a kernel f: A → X it is the support relation {(a, x) : f(x|a) > 0}. Entries within _ATOL of zero count as zero.

Return type:

FXTensor

classmethod swap(list_a, list_b)

Create a swap tensor.

Parameters:
  • list_a (List[int])

  • list_b (List[int])

Return type:

FXTensor

symmetrize(block=None)

Return the average of this state over every permutation of X.

The result has the same profile and labels and satisfies is_exchangeable() for the same block. Averaging again changes nothing, and an exchangeable state is left unchanged. n > 8 warns: the average runs through n! permutations.

Raises:

ValueError – If self is not a state, or the codomain is not X^{⊗n}.

tensor_product(other)

Perform tensor product operation.

Parameters:

other (FXTensor)

Return type:

FXTensor

to_json()

Convert the tensor to a JSON-serializable dictionary.

Unnamed tensors omit names. Named tensors store [domain names, codomain names] under names.

Return type:

dict

to_original_dict()

Convert tensor to original dictionary format with 1-based indexing.

Return type:

Dict[str, Any]

classmethod unit_tensor(dims)

Create a unit tensor (all ones) with the given dimensions.

Parameters:

dims (List[int])

Return type:

FXTensor

The conditional-independence methods are implemented in fxtensor_salmon.independence and mixed into FXTensor.

Conditional independence for finite Markov kernels.

Fritz’s copy–discard equation (arXiv:1908.07021, Definitions 12.1 and 12.16) and the conditional product (Definition 12.8). Codomains are ordered X ⊗ Y ⊗ Z. The string diagram draws the same variables as X ⊗ Z ⊗ Y.

class fxtensor_salmon.independence.IndependenceMixin[source]

Bases: object

Mixin that adds conditional independence to FXTensor.

Codomains are ordered X ⊗ Y ⊗ Z. The string diagram draws the same variables as X ⊗ Z ⊗ Y.

is_conditionally_independent(split_x, split_y, atol=None, rtol=None)[source]

Return whether X ⊥ Y | Z for codomain order X ⊗ Y ⊗ Z.

split_x and split_y are 1-based, like conditional. Factors 1 .. split_x - 1 are X, factors split_x .. split_y - 1 are Y, and the remaining factors are Z. Any of the three blocks may be empty. A state I → X ⊗ Y ⊗ Z and a kernel A → X ⊗ Y ⊗ Z use the same splits.

The predicate holds when self equals the conditional product of its X ⊗ Z and Y ⊗ Z marginals: the finite form of Fritz’s copy–discard equation (arXiv:1908.07021, Def. 12.1 for states and Def. 12.16 for kernels). Values are compared with numpy.allclose. atol and rtol default to FXTensor._ATOL and FXTensor._RTOL.

Raises:

ValueError – If a split is not a 1-based index in range.

is_independent(split, atol=None, rtol=None)[source]

Return whether X ⊥ Y when the codomain is X ⊗ Y.

split is the 1-based first factor of Y. This is is_conditionally_independent() with an empty Z. atol and rtol are forwarded.

Raises:

ValueError – If split is not a 1-based index in range.

classmethod conditional_product(p_xz, q_yz, on, atol=None, rtol=None)[source]

Return the conditional product, with codomain X ⊗ Y ⊗ Z.

p_xz has codomain X ⊗ Z and q_yz has codomain Y ⊗ Z. on is the 1-based index of the first Z factor in both codomains, or a pair (on_p, on_q) when X and Y have different numbers of factors. Both arguments are states, or both are kernels with the same domain.

The value is p_Z ; copy_Z ; (p(x|z) ⊗ id_Z ⊗ q(y|z)) with Z then moved past Y. That diagram has wires X ⊗ Z ⊗ Y; the tensor returned here is X ⊗ Y ⊗ Z, which satisfies X ⊥ Y | Z. p_Z is the Z marginal of p_xz. The two Z marginals must agree within atol and rtol (defaults: FXTensor._ATOL and FXTensor._RTOL).

Raises:

ValueError – If on is out of range, the domains differ, the Z factor sizes differ, or the Z marginals disagree.

The exchangeability methods are implemented in fxtensor_salmon.exchangeability and mixed into FXTensor.

Exchangeability and Kolmogorov consistency for finite states.

A state p: I → X^{⊗n} is exchangeable at position k (1-based) when

p ; (id^{⊗(k-1)} ⊗ swap(X, X) ⊗ id^{⊗(n-k-1)}) = p.

Swapping the k-th and (k+1)-th wires leaves p unchanged. Those wires use (k-1) + 2 + (n-k-1) = n factors.

A sequence p_n: I → X^{⊗n} is Kolmogorov consistent when

p_n ; (id^{⊗(n-1)} ⊗ !) = p_{n-1}.

Discarding the n-th wire of p_n yields p_{n-1}.

class fxtensor_salmon.exchangeability.ExchangeabilityMixin[source]

Bases: object

Mixin that adds exchangeability and Kolmogorov consistency.

States are morphisms I → X^{⊗n}. X is one codomain axis unless block gives the dimension list of a multi-axis factor.

is_exchangeable(block=None, atol=None, rtol=None)[source]

Return whether this state is invariant under every adjacent swap.

The state p: I → X^{⊗n} is exchangeable at position k (1-based) when

p ; (id^{⊗(k-1)} ⊗ swap(X, X) ⊗ id^{⊗(n-k-1)}) = p.

Swapping the k-th and (k+1)-th wires leaves p unchanged. The identity wires and the two swapped wires use (k-1) + 2 + (n-k-1) = n factors. Adjacent transpositions generate the symmetric group, so this checks k = 1 .. n-1. n < 2 is vacuously true.

block is the dimension list of one factor X. The default, None, takes each codomain axis as one factor; those axes must share a size. swap carries no labels, so the comparison is on data via numpy.allclose. atol and rtol default to FXTensor._ATOL and FXTensor._RTOL.

Raises:

ValueError – If self is not a state, or the codomain is not X^{⊗n}.

symmetrize(block=None)[source]

Return the average of this state over every permutation of X.

The result has the same profile and labels and satisfies is_exchangeable() for the same block. Averaging again changes nothing, and an exchangeable state is left unchanged. n > 8 warns: the average runs through n! permutations.

Raises:

ValueError – If self is not a state, or the codomain is not X^{⊗n}.

classmethod is_kolmogorov_consistent(states, block=None, atol=None, rtol=None)[source]

Return whether discarding the last factor reproduces the previous state.

states is the list [p_1, p_2, ..., p_N] with p_n: I → X^{⊗n} (so states[0] is p_1). The sequence is Kolmogorov consistent when, for every n ≥ 2,

p_n ; (id^{⊗(n-1)} ⊗ !) = p_{n-1}.

! is exclamation() on the last factor: discarding the n-th wire of p_n yields p_{n-1}. A list of length 0 or 1 is consistent. block selects X as in is_exchangeable(); the default is one axis, and states[n-1] must then have n axes of that size. Values are compared on data with numpy.allclose. atol and rtol default to FXTensor._ATOL and FXTensor._RTOL.

Raises:

ValueError – If an entry is not a state I → X^{⊗n} for that position, or the factors are not a common type X.

classmethod iid(p, n)[source]

Return the tensor product of n copies of p.

Labels are taken from p. For a state I → X the result is I → X^{⊗n}. n=1 returns a copy of p.

Raises:

ValueError – If p is not an FXTensor, or n is not a positive integer.

classmethod mixture_of_iid(prior, kernel, n)[source]

Return prior ; copy_Θ^{(n)} ; kernel^{⊗n}.

prior is a state I → Θ and kernel is a kernel Θ → X. The result is a state I → X^{⊗n}: one draw from the prior, copied, then n independent samples from the kernel. It is exchangeable and, as n varies, Kolmogorov consistent. Codomain labels are the codomain labels of kernel, repeated n times.

Raises:

ValueError – If prior is not a state, the profiles do not meet, or n is not a positive integer.

The named-axis methods are implemented in fxtensor_salmon.naming and mixed into FXTensor.

Axis names for FXTensor: permute, marginal, and observe.

Names are variable names on wires. They are not the labels of the points on a wire. A tensor constructed with names=None stays unnamed, and the numeric operations are unchanged.

class fxtensor_salmon.naming.NamingMixin[source]

Bases: object

Name-based permute, marginal, and observe.

rename(**mapping)[source]

Return a copy with axis names replaced.

Each keyword is an existing name and its value is the new name. Names that are not mentioned stay. The result must still be unique.

Parameters:

mapping (str)

Return type:

FXTensor

axis(name)[source]

Return the axis index of name.

Domain axes are counted first, then codomain axes, as in get_label_index().

Parameters:

name (str)

Return type:

int

permute(order)[source]

Reorder the codomain axes into order.

The domain is unchanged. Labels move with their axes. order must be a permutation of the codomain names. For a state the codomain is the whole profile, so this reorders every axis.

Parameters:

order (Sequence[str])

Return type:

FXTensor

marginal(*keep)[source]

Keep the named codomain axes, in the order given, and sum out the rest.

A middle axis can be kept or dropped. For a state p: I → A ⊗ B ⊗ C, p.marginal("B") equals p ; (! ⊗ id_B ⊗ !): the deterministic wiring that discards every codomain wire except B. Labels move with the kept axes. The domain is unchanged.

Parameters:

keep (str)

Return type:

FXTensor

marginalize(drop)[source]

Sum out the named codomain axes in drop.

The remaining codomain axes stay in their original order. This is marginal of the complement of drop.

Parameters:

drop (Sequence[str])

Return type:

FXTensor

observe(**evidence)[source]

Condition a state on named outcomes.

evidence maps an axis name to a label, or to an integer index when that axis has no labels. The result is (posterior, probability): the posterior is the joint state on the remaining axes, in their original order, and the probability is the evidence. Observing several axes at once matches observing them one at a time; the probability is then the joint probability of all of the outcomes.

The posterior is the row of conditionalization() after permute() moves the observed wires to the front. Evidence 0 raises ValueError.

Raises:

ValueError – If self is not a state, a name or label is unknown, or the evidence has probability 0.

Return type:

Tuple[‘FXTensor’, float]