Skip to content

Commit

Permalink
Adding support for a third 'superposed' uncollapsed quantum state to …
Browse files Browse the repository at this point in the history
…better control the basis, see #28
  • Loading branch information
AgustinVallejo committed Sep 17, 2024
1 parent 044224c commit b152d13
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 41 deletions.
26 changes: 19 additions & 7 deletions js/coins/model/CoinsExperimentSceneModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import TwoStateSystem from '../../common/model/TwoStateSystem.js';
import TwoStateSystemSet from '../../common/model/TwoStateSystemSet.js';
import quantumMeasurement from '../../quantumMeasurement.js';
import { ClassicalCoinStates, ClassicalCoinStateValues } from './ClassicalCoinStates.js';
import { QuantumCoinStates, QuantumCoinStateValues } from './QuantumCoinStates.js';
import { QuantumCoinStates, QuantumCoinStateValues, QuantumUncollapsedCoinStates, QuantumUncollapsedCoinStateValues } from './QuantumCoinStates.js';

type SelfOptions = {
initiallyActive?: boolean;
Expand All @@ -46,7 +46,7 @@ export default class CoinsExperimentSceneModel extends PhetioObject {
public readonly coinSet: TwoStateSystemSet<ClassicalCoinStates | QuantumCoinStates>;

// The initial state of the coin(s) before any flipping or other experiment preparation occurs.
public readonly initialCoinStateProperty: Property<ClassicalCoinStates> | Property<QuantumCoinStates>;
public readonly initialCoinStateProperty: Property<ClassicalCoinStates> | Property<QuantumUncollapsedCoinStates>;

// The bias towards one outcome or another in the initially prepared state, from 0 to 1.
public readonly stateBiasProperty: NumberProperty;
Expand Down Expand Up @@ -95,10 +95,10 @@ export default class CoinsExperimentSceneModel extends PhetioObject {
}
else {
assert && assert( options.systemType === 'quantum', 'unhandled system type' );
this.initialCoinStateProperty = new Property<QuantumCoinStates>( 'up', {
this.initialCoinStateProperty = new Property<QuantumUncollapsedCoinStates>( 'up', {
tandem: options.tandem.createTandem( 'initialCoinStateProperty' ),
phetioValueType: StringUnionIO( QuantumCoinStateValues ),
validValues: QuantumCoinStateValues
phetioValueType: StringUnionIO( QuantumUncollapsedCoinStateValues ),
validValues: QuantumUncollapsedCoinStateValues
} );
this.singleCoin = new TwoStateSystem<QuantumCoinStates>(
QuantumCoinStateValues,
Expand Down Expand Up @@ -128,14 +128,26 @@ export default class CoinsExperimentSceneModel extends PhetioObject {
// chosen by the user so that it will match when it animates into the test box and be correct if revealed right
// away.
this.singleCoin.setMeasurementValueImmediate( this.initialCoinStateProperty.value as never );
this.coinSet.setMeasurementValuesImmediate( this.initialCoinStateProperty.value );
this.coinSet.setMeasurementValuesImmediate( this.initialCoinStateProperty.value as QuantumCoinStates | ClassicalCoinStates );
}
} );

// If this is a quantum system, changing the initial state of the coin sets the bias to match that coin.
if ( this.systemType === 'quantum' ) {
this.initialCoinStateProperty.lazyLink( initialCoinState => {
this.stateBiasProperty.value = initialCoinState === 'up' ? 1 : 0;
if ( initialCoinState !== 'superposed' ) {
this.stateBiasProperty.value = initialCoinState === 'up' ? 1 : 0;
}
} );

this.stateBiasProperty.lazyLink( bias => {
if ( bias !== 0 && bias !== 1 ) {
this.initialCoinStateProperty.value = 'superposed';
}
else {
// TODO: Wouldn't this cause a reentry? https://github.com/phetsims/quantum-measurement/issues/28
this.initialCoinStateProperty.value = bias === 1 ? 'up' : 'down';
}
} );
}
}
Expand Down
7 changes: 6 additions & 1 deletion js/coins/model/QuantumCoinStates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@
* @author John Blanco (PhET Interactive Simulations)
*/

// Collapsed states after measurements
export const QuantumCoinStateValues = [ 'up', 'down' ] as const;
export type QuantumCoinStates = ( typeof QuantumCoinStateValues )[number];
export type QuantumCoinStates = ( typeof QuantumCoinStateValues )[number];

// Uncollapsed states when preparing the coin
export const QuantumUncollapsedCoinStateValues = [ 'up', 'down', 'superposed' ] as const;
export type QuantumUncollapsedCoinStates = ( typeof QuantumUncollapsedCoinStateValues )[number];
64 changes: 31 additions & 33 deletions js/coins/view/InitialCoinStateSelectorNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@
import NumberProperty from '../../../../axon/js/NumberProperty.js';
import Property from '../../../../axon/js/Property.js';
import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';
import { combineOptions } from '../../../../phet-core/js/optionize.js';
import PhetFont from '../../../../scenery-phet/js/PhetFont.js';
import { Color, Text, VBox } from '../../../../scenery/js/imports.js';
import RectangularRadioButtonGroup, { RectangularRadioButtonGroupOptions } from '../../../../sun/js/buttons/RectangularRadioButtonGroup.js';
import { Color, HBox, Text, VBox } from '../../../../scenery/js/imports.js';
import RectangularRadioButton, { RectangularRadioButtonOptions } from '../../../../sun/js/buttons/RectangularRadioButton.js';
import Panel from '../../../../sun/js/Panel.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import { SystemType } from '../../common/model/SystemType.js';
import quantumMeasurement from '../../quantumMeasurement.js';
import QuantumMeasurementStrings from '../../QuantumMeasurementStrings.js';
import { ClassicalCoinStates, ClassicalCoinStateValues } from '../model/ClassicalCoinStates.js';
import { QuantumCoinStates, QuantumCoinStateValues } from '../model/QuantumCoinStates.js';
import { QuantumCoinStates, QuantumCoinStateValues, QuantumUncollapsedCoinStates } from '../model/QuantumCoinStates.js';
import ClassicalCoinNode from './ClassicalCoinNode.js';
import CoinNode from './CoinNode.js';
import QuantumCoinNode from './QuantumCoinNode.js';
Expand All @@ -32,7 +33,7 @@ export default class InitialCoinStateSelectorNode extends VBox {

public readonly orientationIndicatorCoinNode: CoinNode;

public constructor( initialCoinStateProperty: TReadOnlyProperty<ClassicalCoinStates> | TReadOnlyProperty<QuantumCoinStates>,
public constructor( initialCoinStateProperty: TReadOnlyProperty<ClassicalCoinStates> | TReadOnlyProperty<QuantumUncollapsedCoinStates>,
stateBiasProperty: TReadOnlyProperty<number>,
preparingExperimentProperty: TReadOnlyProperty<boolean>,
systemType: SystemType,
Expand All @@ -54,52 +55,49 @@ export default class InitialCoinStateSelectorNode extends VBox {
font: new PhetFont( { size: 18, weight: 'bold' } )
} );

const radioButtonGroupOptions: RectangularRadioButtonGroupOptions = {
orientation: 'horizontal',
spacing: 22,
radioButtonOptions: {
const radioButtonOptions = {
xMargin: 4,
yMargin: 4,
baseColor: Color.WHITE
},
tandem: tandem.createTandem( 'initialOrientationRadioButtonGroup' )
};

const createCoinRadioButton = ( stateValue: string, coinNode: CoinNode ) => {
return new RectangularRadioButton(
initialCoinStateProperty as Property<ClassicalCoinStates>,
stateValue,
combineOptions<RectangularRadioButtonOptions>( {
content: coinNode,
tandem: tandem.createTandem( `${stateValue.toLowerCase()}RadioButton` )
}, radioButtonOptions )
);
};

let initialOrientationRadioButtonGroup;
let initialCoinStateItems;
if ( systemType === 'classical' ) {
const initialCoinStateItems = ClassicalCoinStateValues.map( stateValue => ( {
createNode: () => new ClassicalCoinNode(
initialCoinStateItems = ClassicalCoinStateValues.map( stateValue => {
return createCoinRadioButton( stateValue, new ClassicalCoinNode(
new Property<ClassicalCoinStates>( stateValue ),
RADIO_BUTTON_COIN_NODE_RADIUS,
Tandem.OPT_OUT
),
value: stateValue,
tandemName: `${stateValue.toLowerCase()}RadioButton`
} ) );
initialOrientationRadioButtonGroup = new RectangularRadioButtonGroup<ClassicalCoinStates>(
initialCoinStateProperty as Property<ClassicalCoinStates>,
initialCoinStateItems,
radioButtonGroupOptions
);
) );
} );
}
else {
const initialCoinStateItems = QuantumCoinStateValues.map( stateValue => ( {
createNode: () => new QuantumCoinNode(
initialCoinStateItems = QuantumCoinStateValues.map( stateValue => {
return createCoinRadioButton( stateValue, new QuantumCoinNode(
new Property<QuantumCoinStates>( stateValue ),
new NumberProperty( stateValue === 'up' ? 1 : 0 ),
RADIO_BUTTON_COIN_NODE_RADIUS,
Tandem.OPT_OUT
),
value: stateValue,
tandemName: `${stateValue.toLowerCase()}RadioButton`
} ) );
initialOrientationRadioButtonGroup = new RectangularRadioButtonGroup<QuantumCoinStates>(
initialCoinStateProperty as Property<QuantumCoinStates>,
initialCoinStateItems,
radioButtonGroupOptions
);
) );
} );
}

const initialOrientationRadioButtonGroup = new HBox( {
children: initialCoinStateItems,
spacing: 22
} );

const selectorPanelContent = new VBox( {
children: [ selectionPanelTitle, initialOrientationRadioButtonGroup ],
spacing: 10
Expand Down

0 comments on commit b152d13

Please sign in to comment.