Problem Description
The current string representation of Qobj's is often not very useful, in particular when dealing with states that are a superposition of just a few basis elements. E.g.
ket = 0.3*tensor(basis(8, 5), basis(2, 1), basis(3, 0)) + 0.5*tensor(basis(8, 3), basis(2, 0), basis(3, 2))
print(ket)
This spams my console with 50 (mostly empty) lines. Having the option to print this as 0.3 |5, 1, 0> + 0.5 |3, 0, 2> would be much nicer.
Proposed Solution
If there is interest for this, I could open a PR to add something like Qobj.print_basis_expansion() or similar (I'd be open for suggestions for a better name).
This is the implementation I've been using so far.
def print_basis_expansion(state: qutip.Qobj, decimal_places: int = 14, dim_separator: str = "auto",
term_separator: str = " +\n", sort: str = "largest-first") -> str:
"""
Return a string-representation of the basis expansion for a ket or a bra, e.g.
"0.5 |010> + 0.25 |000> + ..."
Parameters
----------
decimal_places : int
The number of decimal places to show for the coefficients.
dim_separator: str
Separator string between dimension indices. E.g. use ", " to print as "|0, 0, 0>".
If dim_separator="auto", then "" is used for qubits and ", " is used otherwise.
term_separator: str
Separator string between terms. E.g. use " + "
to print in a single line as "|000> + |111>"
sort: str
Show largest elements (by magnitude) first if "largest-first".
Unsorted otherwise.
Returns
-------
basis_expansion : str
The requested string representation.
"""
if not (state.isket or state.isbra):
raise ValueError(f"Only implemented for states, not {state.type}.")
dims = state.dims[0 if state.isket else 1]
if dim_separator == "auto":
# No separator for pure qubit states, but comma-separator otherwise,
# since bitstrings are nice, but e.g. |153> would be ambiguous.
dim_separator = ", " if any([dim > 2 for dim in dims]) else ""
template = "{} |{}>" if state.isket else "{} <{}|"
ket_full = np.round(state.full(squeeze=True), decimals=decimal_places)
indices = range(len(ket_full))
if sort == "largest-first":
indices = np.argsort(np.abs(ket_full))[::-1]
parts = []
for i in indices:
if np.abs(ket_full[i]) > 10**-(decimal_places):
coeff = ket_full.item(i)
basis_str = dim_separator.join(map(str, np.unravel_index(i, dims)))
parts.append(template.format(coeff, basis_str))
if len(parts) == 0: # return something for norm-zero states.
return "0"
return term_separator.join(parts)
Alternate Solutions
No response
Additional Context
No response
Problem Description
The current string representation of
Qobj's is often not very useful, in particular when dealing with states that are a superposition of just a few basis elements. E.g.This spams my console with 50 (mostly empty) lines. Having the option to print this as
0.3 |5, 1, 0> + 0.5 |3, 0, 2>would be much nicer.Proposed Solution
If there is interest for this, I could open a PR to add something like
Qobj.print_basis_expansion()or similar (I'd be open for suggestions for a better name).This is the implementation I've been using so far.
Alternate Solutions
No response
Additional Context
No response