import Vector from './Vector' ; import Operator from './Operator' ; export interface INamedVector { name : string [ ] ; vector : Vector ; } /**
 * Class for creating and using weighted projections M=wP for POVMs.
 */ export class WeightedProjection { name : string [ ] ; weight : number ; operator : Operator ; constructor ( name , operator , weight ) { this . name = name ; this . operator = operator ; this . weight = weight ; } param name param operator param weight param check returns static new ( name , operator , weight = 1 , check = true ) { if ( check && ! operator . isCloseToProjection ( ) ) { throw Error ( `WeightedProjection ${ name . join ( '&' ) } is not a projection.` ) ; } return new WeightedProjection ( name , operator , weight ) ; } param name param vector returns static fromVector ( name , vector ) { const operator = Operator . projectionOn ( vector . normalize ( ) ) ; return WeightedProjection . new ( name , operator , vector . normSquared ( ) ) ; } scaledOperator ( ) { return this . operator . mulByReal ( this . weight ) ; } transformationOperator ( ) { return this . operator . mulByReal ( Math . sqrt ( this . weight ) ) ; } remainingShift ( ) { return this . operator . mulByReal ( Math . sqrt ( 1 - this . weight ) - 1 ) ; } param vector param coordIndices returns actOnPureState ( vector , coordIndices ) { return this . operator . mulVecPartial ( coordIndices , vector ) . mulByReal ( Math . sqrt ( this . weight ) ) ; } param namedVector param coordIndices returns actOnNamedVector ( namedVector , coordIndices ) { return { name : [ ... namedVector . name , ... this . name ] , vector : this . actOnPureState ( namedVector . vector , coordIndices ) , } ; } } /**
 * Class for performing measurements.
 * Results are labeled by names of types T.
 * Supports successive measurements, to deal with many particles.
 */ export default class Measurement { states : INamedVector [ ] ; constructor ( states ) { this . states = states ; } param vector param name static fromVector ( vector , name = [ ] ) { return new Measurement ( [ { name , vector : vector . normalize ( ) } ] ) ; } destructiveMeasurement ( coordIndices , projections ) { const newStates = this . states . flatMap ( ( state ) => projections . map ( ( projection ) => ( { name : [ ... state . name , ... projection . name ] , vector : projection . vector . innerPartial ( coordIndices , state . vector ) , } ) ) ) ; return new Measurement ( newStates ) ; } nondemolitionMeasurement ( coordIndices , povms , check = true ) { if ( check && ! Operator . add ( povms . map ( ( povm ) => povm . scaledOperator ( ) ) ) . isCloseToIdentity ( ) ) { throw Error ( 'POVMs do not add up to identity, fix or use projectiveMeasurement instead.' ) ; } const newStates = this . states . flatMap ( ( state ) => povms . map ( ( povm ) => povm . actOnNamedVector ( state , coordIndices ) ) ) ; return new Measurement ( newStates ) ; } param coordIndices param measurements param povms returns todo projectiveMeasurement ( coordIndices , projections , povms = [ ] ) { const newStatesProj = this . destructiveMeasurement ( coordIndices , projections ) . states ; const newStatesPOVM = this . nondemolitionMeasurement ( coordIndices , povms , false ) . states ; const projOnMeasured = Operator . add ( projections . map ( ( projection ) => WeightedProjection . fromVector ( [ ] , projection . vector ) . remainingShift ( ) ) . concat ( povms . map ( ( povm ) => povm . remainingShift ( ) ) ) ) ; const notMeasured = this . states . map ( ( { name , vector } ) => { const projectedVec = vector . add ( projOnMeasured . mulVecPartial ( coordIndices , vector ) ) ; return { name , vector : projectedVec , } ; } ) ; const allStates = notMeasured . concat ( newStatesProj ) . concat ( newStatesPOVM ) . filter ( ( state ) => state . vector . normSquared ( ) > 1e-8 ) ; return new Measurement ( allStates ) ; } /**
     * Print outcomes.
     */ toString ( ) { return this . states . map ( ( state ) => { const percent = 100 * state . vector . normSquared ( ) ; const name = state . name . join ( '&' ) ; return `${ percent . toFixed ( 1 ) }% [${ name }] ${ state . vector . normalize ( ) . toKetString ( ) }` ; } ) . join ( '\n' ) ; } /**
     * Randomly selects outcome, according to probabilities.
     */ pickRandom ( ) { const probs = this . states . map ( ( state ) => state . vector . normSquared ( ) ) ; const p = Math . random ( ) ; let acc = 0 ; for ( let i = 0 ; i < this . states . length ; i ++ ) { acc += probs [ i ] ; if ( acc > p ) { const { name , vector } = this . states [ i ] ; return Measurement . fromVector ( vector , name ) ; } } throw new Error ( 'Measurement probabilities does not sum up to 1.' ) ; } }