You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Following up on #63: After giving it some thought, I think we do need to implement a scalar algebra, mostly to properly handle Braket (and BraOpKet, which is a class we should have). Fully identifying scalars in the various algebras is going to be quite useful, as we can freely commute scalars to bring expressions into some desired form for a simplification. Also, there's a bunch of expressions that commonly occur in perturbation theory (brakets in the denominator) that we currently can't express at all.
Algebraic Elements
Scalar: base class for all scalars, with subclasses:
ValueScalar: wrapper around what we currently consider a scalars. It stores the wrapped value in val attribute (instance of sympy.Basic, int, np.float64,...). Further subclassing into SymbolicScalar to wrap around SymPy expressions and NumericScalar for everything else is possible, but probably not necessary.
ExpressionScalar: base class for e.g. Braket and BraOpKet
Singletons
The Singletons for the neutral elements are Zero and One, and are instances of ValueScalar.
Operations
The Operation subclasses in the algebra would be:
ScalarPlus, e.g. ⟨ϕ|Ψ⟩ + 1
ScalarTimes, e.g. 2⟨ϕ|Ψ⟩
ScalarQuotient, e.g. 1/⟨ϕ|Ψ⟩ (better expressed by ScalarPower)
ScalarPower, e.g. √⟨ϕ|Ψ⟩ or ⟨ϕ|Ψ⟩ⁿ
ScalarAbs, e.g. |⟨ϕ|Ψ⟩|
A ScalarConjugate class for ⟨ϕ|Ψ⟩⁺probably can be avoided, if we can guarantee that for any scalar, scalar.conjugate() can be translated into its operands.
Notes
Any operation between two ValueScalar instances automatically combines the values: ValueScalar(α) + ValueScalar(β) = ValueScalar(α+β). All the numeric magic methods should be defined appropriately.
Operations involving an ExpressionScalar (like the examples above) stay instances of the appropriate Operation subclass
ScalarTimesExpression subclasses will require that the coefficient is a Scalar instance. They will do an automatic conversion in their __init__ routine: if not isinstance(coeff, Scalar): ValueScalar.create(coeff)
Other classes that currently take scalars as parameters, e.g. the amplitude for the CoherentStateKet likewise convert to Scalar in __init__. These conversions must happen in __init__, not in create.
For ValueScalar instance, we definitely want hash(scalar) == hash(scalar.val) and scalar == scalar.val). This will be safe because of the conversions happening in the __init__ routines.
The current SCALAR_TYPES list is obsolete
Scalar instances have a space attribute for an associated Hilbert space. Instances of ValueScalar are associated with TrivialSpace. For Braket, the Hilbert space would be the Hilbert space on which the expression is the inner product. We probably don't really need to enforce that ScalarTimesExpression has a scalar and an expression in compatible spaces (although we could, as a "sanity check"). Mostly, the Hilbert space attribute will be used for printing, and for ordering the operands of ScalarTimes (factors associated with the same Hilbert space should be grouped together, making it easier to apply "binary" simplification rules to them)
When printing ScalarTimesKet, we'd probably want to be a little bit fancy and print ValueScalar factors left of the Ket, and ExpressionScalar factor to the right, to print something like α|Ψ⟩⟨ϕ|Ψ⟩ instead of α⟨ϕ|Ψ⟩|Ψ⟩. For the associated Bra, all factors should be printed on the left.
The text was updated successfully, but these errors were encountered:
Following up on #63: After giving it some thought, I think we do need to implement a scalar algebra, mostly to properly handle
Braket
(andBraOpKet
, which is a class we should have). Fully identifying scalars in the various algebras is going to be quite useful, as we can freely commute scalars to bring expressions into some desired form for a simplification. Also, there's a bunch of expressions that commonly occur in perturbation theory (brakets in the denominator) that we currently can't express at all.Algebraic Elements
Scalar
: base class for all scalars, with subclasses:ValueScalar
: wrapper around what we currently consider a scalars. It stores the wrapped value inval
attribute (instance ofsympy.Basic
,int
,np.float64
,...). Further subclassing intoSymbolicScalar
to wrap around SymPy expressions andNumericScalar
for everything else is possible, but probably not necessary.ExpressionScalar
: base class for e.g.Braket
andBraOpKet
Singletons
The Singletons for the neutral elements are
Zero
andOne
, and are instances ofValueScalar
.Operations
The
Operation
subclasses in the algebra would be:ScalarPlus
, e.g.⟨ϕ|Ψ⟩ + 1
ScalarTimes
, e.g.2⟨ϕ|Ψ⟩
(better expressed byScalarQuotient
, e.g.1/⟨ϕ|Ψ⟩
ScalarPower
)ScalarPower
, e.g.√⟨ϕ|Ψ⟩
or⟨ϕ|Ψ⟩ⁿ
ScalarAbs
, e.g.|⟨ϕ|Ψ⟩|
ScalarConjugate
class for⟨ϕ|Ψ⟩⁺
probably can be avoided, if we can guarantee that for anyscalar
,scalar.conjugate()
can be translated into its operands.Notes
ValueScalar
instances automatically combines the values:ValueScalar(α) + ValueScalar(β) = ValueScalar(α+β)
. All the numeric magic methods should be defined appropriately.ExpressionScalar
(like the examples above) stay instances of the appropriateOperation
subclassScalarTimesExpression
subclasses will require that the coefficient is aScalar
instance. They will do an automatic conversion in their__init__
routine:if not isinstance(coeff, Scalar): ValueScalar.create(coeff)
CoherentStateKet
likewise convert toScalar
in__init__
. These conversions must happen in__init__
, not increate
.ValueScalar
instance, we definitely wanthash(scalar) == hash(scalar.val)
andscalar == scalar.val)
. This will be safe because of the conversions happening in the__init__
routines.SCALAR_TYPES
list is obsoleteScalar
instances have aspace
attribute for an associated Hilbert space. Instances ofValueScalar
are associated withTrivialSpace
.ForBraket
, the Hilbert space would be the Hilbert space on which the expression is the inner product. We probably don't really need to enforce thatScalarTimesExpression
has a scalar and an expression in compatible spaces (although we could, as a "sanity check"). Mostly, the Hilbert space attribute will be used for printing, and for ordering the operands ofScalarTimes
(factors associated with the same Hilbert space should be grouped together, making it easier to apply "binary" simplification rules to them)ScalarTimesKet
, we'd probably want to be a little bit fancy and printValueScalar
factors left of theKet
, andExpressionScalar
factor to the right, to print something likeα|Ψ⟩⟨ϕ|Ψ⟩
instead ofα⟨ϕ|Ψ⟩|Ψ⟩
. For the associatedBra
, all factors should be printed on the left.The text was updated successfully, but these errors were encountered: