# Notebook from wnbts/amazon-braket-examples
Path: examples/braket_features/Using_the_tensor_network_simulator_TN1.ipynb

# Using the Amazon Braket tensor network simulator TN1

This tutorial serves as an in-depth introduction to TN1, the Amazon Braket tensor network simulator. TN1 was previously introduced in [Running quantum circuits on simulators notebook](../getting_started/1_Running_quantum_circuits_on_simulators.ipynb). This tutorial explains what makes TN1 different from SV1, Braket's state vector simulator, and it discusses which use cases are well suited for tensor network simulations. We examine what circuit properties affect TN1's performance and how TN1 can be used to simulate some types circuits for many more qubits than SV1 can handle._____no_output_____## How TN1 Works

A tensor network simulator models the execution of circuits on a quantum computer by representing each gate in the circuit as a *tensor*. Tensors generalize the concept of vectors and matrices to higher dimensions. The gates in the network form a graph. The simulator works by finding an efficient way to multiply all the different tensors on the graph during the _rehearsal_ stage and then, after a suitable multiplication sequence or _path_ is found, it performs these multiplications in the _contraction_ stage. For more information about TN1 and how it works, see the [TN1 docs](https://docs.aws.amazon.com/braket/latest/developerguide/braket-devices.html#braket-simulator-tn1).

## How is this different from SV1, the state vector simulator?

SV1 works differently -- SV1 simulates all the evolution of all amplitudes as gates are applied. This means that SV1 cannot simulate large numbers of qubits for any circuit, because the memory required becomes infeasible. However, this restriction does not necessarily apply to TN1. Because TN1 works by contracting gates, it is able to work only with worldlines through the circuit which are relevant to the final outcome. However, TN1 can be slower than SV1 for circuits with complex geometry. In circuits which include multi-qubit gates, gates with long range, or circuits with few qubits (fewer than 28), SV1 is often the better choice. To use TN1 effectively it is important to understand that circuit geometry can pose more of a barrier than simple qubit number, as we will see below._____no_output_____## Can my circuit be simulated on TN1?

While SV1 will simulate every circuit within the service limits (i.e., smaller or equal than 34 qubits), TN1 can only decide if a circuit can be contracted after it has the full information from the rehearsal stage. In the best case, this enables you to simulate circuits of much larger size than SV1 (up to 50 qubits) but, on the flip side, that means that in some cases you might find that TN1 will terminate the simulation after the rehearsal if it finds that the projected contraction time exceeds its runtime limit. In this case the `failureReason` for the task will be `Predicted runtime based on best contraction path found exceeds TN1 limit.` The rehearsal stage of TN1 is limited to 10 minutes, but in most cases you will find that TN1 will arrive at a decision much faster.

As we will see below, if this situation occurs for a task for which you have requested a large number of shots, the task may be successful if you lower the shot count. It can also occur, albeit rarely, that the time to find a single contraction path candidate exceeds TN1's internal rehearsal runtime limit -- circuits for which this occurs are extremely unlikely to be contractable in reasonable time. In this case, the `failureReason` for the task will be `No viable contraction path found.`

To learn more about why these two stages are present and what the simulator does in each, you can read the TN1 documentation [here](https://docs.aws.amazon.com/braket/latest/developerguide/braket-devices.html#braket-simulator-tn1)._____no_output_____

Note: In the worst case, the TN1 runtime can scale linearly with the number of shots requested. It is strongly recommended to test your circuit or circuit class with a small number of shots first.

_____no_output_____

# general imports
import numpy as np
import math

import boto3
# AWS imports: Import Braket SDK modules
from braket.circuits import Circuit, circuit, Gate, Instruction
from braket.aws import AwsDevice

tn_device = AwsDevice('arn:aws:braket:::device/quantum-simulator/amazon/tn1')
sv_device = AwsDevice('arn:aws:braket:::device/quantum-simulator/amazon/sv1')_____no_output_____

## Two simple examples: The GHZ state and Quantum Fourier Transform

We already presented the GHZ example circuit in the [Running quantum circuits on simulators notebook](../getting_started/1_Running_quantum_circuits_on_simulators.ipynb). Here, we'll compare the performance of SV1 and TN1 for this relatively simple circuit. The GHZ state is simple to prepare:_____no_output_____

def ghz_circuit(n_qubits: int) -> Circuit:
    """
    Function to return simple GHZ circuit ansatz. Assumes all qubits in range(0, n_qubits-1)
    are entangled.

    :param int n_qubits: number of qubits
    :return: Constructed GHZ circuit
    :rtype: Circuit
    """

    circuit = Circuit()                          # instantiate circuit object
    circuit.h(0)                                 # add Hadamard gate on first qubit

    for ii in range(0, n_qubits-1):
        circuit.cnot(control=ii, target=ii+1)    # apply series of CNOT gates
    return circuit_____no_output_____

We will simulate the measurement counts for this circuit on SV1 and TN1. SV1 can only simulate up to 34 qubits, but TN1 can work with substantially more in this case because of the circuit's geometry. In this case we will not run up to 34 qubits on SV1, because the runtime on that simulator can become quite long. 30 qubits is enough to see that TN1 can equal or outperform SV1 for circuits like GHZ, which has a simple, compact nearest-neighbor circuit geometry. Because the GHZ state is a "cat state", with only two possible measurement outcomes (all up or all down), it is easy for TN1 to explore all possible output bitstrings._____no_output_____

qubit_range = range(20, 31, 5)
tn_qubit_range = range(35, 51, 5)
n_shots     = 100
ghz_circs   = {}
sv_tasks    = {}
tn_tasks    = {}
sv_results  = {}
tn_results  = {}
for num_qubits in qubit_range:
    ghz = ghz_circuit(num_qubits)
    sv_tasks[num_qubits] = sv_device.run(ghz, shots=n_shots)
    tn_tasks[num_qubits] = tn_device.run(ghz, shots=n_shots)
    ghz_circs[num_qubits] = ghz

# Run qubit numbers which only TN1 supports
for num_qubits in tn_qubit_range:
    ghz = ghz_circuit(num_qubits)
    tn_tasks[num_qubits] = tn_device.run(ghz, shots=n_shots)
    ghz_circs[num_qubits] = ghz

for num_qubits in qubit_range:
    tn_status = tn_tasks[num_qubits].state()
    sv_status = sv_tasks[num_qubits].state()
    while tn_status != 'COMPLETED':
        tn_status = tn_tasks[num_qubits].state()
    while sv_status != 'COMPLETED':
        sv_status = sv_tasks[num_qubits].state()

    tn_results[num_qubits] = tn_tasks[num_qubits].result()
    sv_results[num_qubits] = sv_tasks[num_qubits].result()

    # get the running time of the tasks
    sv_runtime = sv_results[num_qubits].additional_metadata.simulatorMetadata.executionDuration
    tn_runtime = tn_results[num_qubits].additional_metadata.simulatorMetadata.executionDuration

    # get the 'shots' parameter from metadata
    tn_num_shots = tn_results[num_qubits].task_metadata.shots
    sv_num_shots = sv_results[num_qubits].task_metadata.shots

    # get the measurement counts
    tn_counts = tn_results[num_qubits].measurement_counts
    sv_counts = sv_results[num_qubits].measurement_counts

    print("GHZ circuit:")
    print(ghz_circs[num_qubits])
    print('{}-qubit TN1 task {}.'.format(num_qubits,tn_status))
    print('Tensor network simulator:')
    print('This task ran {} shots and the total runtime was {} ms'.format(tn_num_shots,tn_runtime))
    print("Measurement results: {}\n".format(tn_counts))
    print('{}-qubit SV1 task {}.'.format(num_qubits,sv_status))
    print('State vector simulator:')
    print('This task ran {} shots and the total runtime was {} ms'.format(sv_num_shots,sv_runtime))
    print("Measurement results: {}\n".format(sv_counts))

for num_qubits in tn_qubit_range:
    tn_status = tn_tasks[num_qubits].state()
    while tn_status != 'COMPLETED':
        tn_status = tn_tasks[num_qubits].state()

    tn_results[num_qubits] = tn_tasks[num_qubits].result()

    # get the running time of the tasks
    tn_runtime = tn_results[num_qubits].additional_metadata.simulatorMetadata.executionDuration

    # get the 'shots' parameter from metadata
    tn_num_shots = tn_results[num_qubits].task_metadata.shots

    # get the measurement counts
    tn_counts = tn_results[num_qubits].measurement_counts

    # we will not print the circuits here as they are quite large
    print('{}-qubit TN1 task {}.'.format(num_qubits,tn_status))
    print('Tensor network simulator:')
    print('This task ran {} shots and the total runtime was {} ms'.format(tn_num_shots,tn_runtime))
    print("Measurement results: {}\n".format(tn_counts))GHZ circuit:
T   : |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|

q0  : -H-C-----------------------------------------------
         |
q1  : ---X-C---------------------------------------------
           |
q2  : -----X-C-------------------------------------------
             |
q3  : -------X-C-----------------------------------------
               |
q4  : ---------X-C---------------------------------------
                 |
q5  : -----------X-C-------------------------------------
                   |
q6  : -------------X-C-----------------------------------
                     |
q7  : ---------------X-C---------------------------------
                       |
q8  : -----------------X-C-------------------------------
                         |
q9  : -------------------X-C-----------------------------
                           |
q10 : ---------------------X--C--------------------------
                              |
q11 : ------------------------X--C-----------------------
                                 |
q12 : ---------------------------X--C--------------------
                                    |
q13 : ------------------------------X--C-----------------
                                       |
q14 : ---------------------------------X--C--------------
                                          |
q15 : ------------------------------------X--C-----------
                                             |
q16 : ---------------------------------------X--C--------
                                                |
q17 : ------------------------------------------X--C-----
                                                   |
q18 : ---------------------------------------------X--C--
                                                      |
q19 : ------------------------------------------------X--

T   : |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|
20-qubit TN1 task COMPLETED.
Tensor network simulator:
This task ran 100 shots and the total runtime was 2364 ms
Measurement results: Counter({'11111111111111111111': 54, '00000000000000000000': 46})

20-qubit SV1 task COMPLETED.
State vector simulator:
This task ran 100 shots and the total runtime was 177 ms
Measurement results: Counter({'00000000000000000000': 55, '11111111111111111111': 45})

GHZ circuit:
T   : |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|

q0  : -H-C--------------------------------------------------------------
         |
q1  : ---X-C------------------------------------------------------------
           |
q2  : -----X-C----------------------------------------------------------
             |
q3  : -------X-C--------------------------------------------------------
               |
q4  : ---------X-C------------------------------------------------------
                 |
q5  : -----------X-C----------------------------------------------------
                   |
q6  : -------------X-C--------------------------------------------------
                     |
q7  : ---------------X-C------------------------------------------------
                       |
q8  : -----------------X-C----------------------------------------------
                         |
q9  : -------------------X-C--------------------------------------------
                           |
q10 : ---------------------X--C-----------------------------------------
                              |
q11 : ------------------------X--C--------------------------------------
                                 |
q12 : ---------------------------X--C-----------------------------------
                                    |
q13 : ------------------------------X--C--------------------------------
                                       |
q14 : ---------------------------------X--C-----------------------------
                                          |
q15 : ------------------------------------X--C--------------------------
                                             |
q16 : ---------------------------------------X--C-----------------------
                                                |
q17 : ------------------------------------------X--C--------------------
                                                   |
q18 : ---------------------------------------------X--C-----------------
                                                      |
q19 : ------------------------------------------------X--C--------------
                                                         |
q20 : ---------------------------------------------------X--C-----------
                                                            |
q21 : ------------------------------------------------------X--C--------
                                                               |
q22 : ---------------------------------------------------------X--C-----
                                                                  |
q23 : ------------------------------------------------------------X--C--
                                                                     |
q24 : ---------------------------------------------------------------X--

T   : |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|
25-qubit TN1 task COMPLETED.
Tensor network simulator:
This task ran 100 shots and the total runtime was 2441 ms
Measurement results: Counter({'1111111111111111111111111': 56, '0000000000000000000000000': 44})

25-qubit SV1 task COMPLETED.
State vector simulator:
This task ran 100 shots and the total runtime was 604 ms
Measurement results: Counter({'0000000000000000000000000': 53, '1111111111111111111111111': 47})

GHZ circuit:
T   : |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|

q0  : -H-C-----------------------------------------------------------------------------
         |
q1  : ---X-C---------------------------------------------------------------------------
           |
q2  : -----X-C-------------------------------------------------------------------------
             |
q3  : -------X-C-----------------------------------------------------------------------
               |
q4  : ---------X-C---------------------------------------------------------------------
                 |
q5  : -----------X-C-------------------------------------------------------------------
                   |
q6  : -------------X-C-----------------------------------------------------------------
                     |
q7  : ---------------X-C---------------------------------------------------------------
                       |
q8  : -----------------X-C-------------------------------------------------------------
                         |
q9  : -------------------X-C-----------------------------------------------------------
                           |
q10 : ---------------------X--C--------------------------------------------------------
                              |
q11 : ------------------------X--C-----------------------------------------------------
                                 |
q12 : ---------------------------X--C--------------------------------------------------
                                    |
q13 : ------------------------------X--C-----------------------------------------------
                                       |
q14 : ---------------------------------X--C--------------------------------------------
                                          |
q15 : ------------------------------------X--C-----------------------------------------
                                             |
q16 : ---------------------------------------X--C--------------------------------------
                                                |
q17 : ------------------------------------------X--C-----------------------------------
                                                   |
q18 : ---------------------------------------------X--C--------------------------------
                                                      |
q19 : ------------------------------------------------X--C-----------------------------
                                                         |
q20 : ---------------------------------------------------X--C--------------------------
                                                            |
q21 : ------------------------------------------------------X--C-----------------------
                                                               |
q22 : ---------------------------------------------------------X--C--------------------
                                                                  |
q23 : ------------------------------------------------------------X--C-----------------
                                                                     |
q24 : ---------------------------------------------------------------X--C--------------
                                                                        |
q25 : ------------------------------------------------------------------X--C-----------
                                                                           |
q26 : ---------------------------------------------------------------------X--C--------
                                                                              |
q27 : ------------------------------------------------------------------------X--C-----
                                                                                |
q28 : ---------------------------------------------------------------------------X--C--
                                                                                |
q29 : ------------------------------------------------------------------------------X--

T   : |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|
30-qubit TN1 task COMPLETED.
Tensor network simulator:
This task ran 100 shots and the total runtime was 2649 ms
Measurement results: Counter({'111111111111111111111111111111': 54, '000000000000000000000000000000': 46})

30-qubit SV1 task COMPLETED.
State vector simulator:
This task ran 100 shots and the total runtime was 17147 ms
Measurement results: Counter({'111111111111111111111111111111': 54, '000000000000000000000000000000': 46})

There are many circuits which can be efficiently simulated by TN1 even up to very large qubit counts. Another example is the quantum Fourier transform (QFT) and its inverse, shown in [the QFT notebook](../advanced_circuits_algorithms/QFT/QFT.ipynb). TN1 is able to efficiently simulate the QFT on an input state of |00..00> because in this case it amounts to a simple rotation, even up to many qubits:_____no_output_____

@circuit.subroutine(register=True)
def qft(qubits):
    """
    Construct a circuit object corresponding to the Quantum Fourier Transform (QFT)
    algorithm, applied to the argument qubits.  Does not use recursion to generate the QFT.

    Args:
        qubits (int): The list of qubits on which to apply the QFT
    """
    qftcirc = Circuit()

    # get number of qubits
    num_qubits = len(qubits)

    for k in range(num_qubits):
        # First add a Hadamard gate
        qftcirc.h(qubits[k])

        # Then apply the controlled rotations, with weights (angles) defined by the distance to the control qubit.
        # Start on the qubit after qubit k, and iterate until the end.  When num_qubits==1, this loop does not run.
        for j in range(1,num_qubits - k):
            angle = 2*math.pi/(2**(j+1))
            qftcirc.cphaseshift(qubits[k+j],qubits[k], angle)

    # Then add SWAP gates to reverse the order of the qubits:
    for i in range(math.floor(num_qubits/2)):
        qftcirc.swap(qubits[i], qubits[-i-1])

    return qftcirc_____no_output_____qubit_range = range(20, 51, 10)
tn_tasks    = {}
tn_results  = {}
for num_qubits in qubit_range:
    # generate QFT circuit
    qft_circ = qft(range(num_qubits))
    tn_tasks[num_qubits] = tn_device.run(qft_circ, shots=n_shots)

for num_qubits in qubit_range:
    tn_status = tn_tasks[num_qubits].state()
    while tn_status != 'COMPLETED':
        tn_status = tn_tasks[num_qubits].state()

    tn_results[num_qubits] = tn_tasks[num_qubits].result()
    # get the running time of the task
    tn_runtime = tn_results[num_qubits].additional_metadata.simulatorMetadata.executionDuration

    # get the measurement counts
    tn_counts = tn_results[num_qubits].measurement_counts

    print('{}-qubit task {}.'.format(num_qubits,tn_status))
    print('QFT:')
    print('This task ran {} shots and the total runtime was {} ms'.format(tn_num_shots,tn_runtime))
    print("Measurement results: {}\n".format(tn_counts))20-qubit task COMPLETED.
QFT:
This task ran 100 shots and the total runtime was 7408 ms
Measurement results: Counter({'00011011011110110110': 1, '11110101000111110010': 1, '00110011000001111111': 1, '10101011000111000110': 1, '10010000010001000011': 1, '00110110001011010101': 1, '01010111111111100100': 1, '11100111011110100011': 1, '00011011011010001011': 1, '01010000101011110000': 1, '10100011111111101011': 1, '10101001110110100000': 1, '01010011101100011110': 1, '10011001011101111000': 1, '01001111100011000011': 1, '00001011000000110000': 1, '11101111110010000001': 1, '01111111010111000101': 1, '01000111101111010011': 1, '10000101110111000011': 1, '01000110010111101101': 1, '11110010101000101010': 1, '01111110000000111101': 1, '00100110111000010100': 1, '00100100010101010101': 1, '01101010010010110011': 1, '11010101100111110001': 1, '10101010001100110001': 1, '11100010110101110101': 1, '10110110100010100001': 1, '01110110010001011110': 1, '01001110001101101000': 1, '00011100111010111111': 1, '10100011000001001100': 1, '00010110110011111000': 1, '01111101000000010110': 1, '01000010101110111101': 1, '10101101110011101001': 1, '01101000010001011010': 1, '01101010001001111000': 1, '01101010111010010001': 1, '01011111001001011011': 1, '10000010111001110110': 1, '01110001110100111110': 1, '11100010010001111010': 1, '11100111011000000001': 1, '10111010001110111100': 1, '11010001110111101001': 1, '10011010100010011101': 1, '11110000100001000011': 1, '11110001011100001101': 1, '00111100001010110010': 1, '10000100000100101000': 1, '11111001111001111010': 1, '01100000010010101100': 1, '01011110110011011001': 1, '00100111010110101101': 1, '10010001110001010111': 1, '11001010111110001101': 1, '10110111001110111011': 1, '11000111000111011111': 1, '11110011010110001011': 1, '10100101010000110010': 1, '01000110000111000010': 1, '11101100010001010010': 1, '01110100111111000000': 1, '01000010001101100101': 1, '10001000011000110111': 1, '11000100010111011100': 1, '00111000000110101111': 1, '01011101111011001010': 1, '10001001100010110010': 1, '00101010101011010111': 1, '00101111111001011010': 1, '10001010000100110010': 1, '10101100100111011100': 1, '00111011011000110110': 1, '11000010110011001001': 1, '01101110010010111011': 1, '11001001000111000000': 1, '01111010100001111000': 1, '11010100011100000101': 1, '11001110011001101100': 1, '11010110011001100111': 1, '11010100100000010000': 1, '11110010100110100100': 1, '11000000001000111001': 1, '11011111010001110010': 1, '00000110010101111001': 1, '01010111101100010001': 1, '11101011110100101000': 1, '10011111100001110001': 1, '11011111110011011010': 1, '01101100101000100100': 1, '11001111001110001100': 1, '10101000011110010100': 1, '10011110011011011011': 1, '11101001111001011001': 1, '01010011011100100111': 1, '00110110111001101001': 1})

30-qubit task COMPLETED.
QFT:
This task ran 100 shots and the total runtime was 16040 ms
Measurement results: Counter({'110101100001110001110111101110': 1, '100000001001111111111100100110': 1, '111011001011001000110111110110': 1, '000010110010010100011101011101': 1, '010101100001001011011010010100': 1, '001000000011010100010111111000': 1, '101110110111000111010001100010': 1, '101001111010110011100100111010': 1, '111010100001110100100011100010': 1, '110110000010111010010000000101': 1, '101110111111001111101101100100': 1, '110010101010101000001100111111': 1, '111001101100110111111111100111': 1, '001000010111001101111100101000': 1, '000001110101111111001110011111': 1, '001111101101001000000010011010': 1, '111101000100111110100111010101': 1, '110011101010111001011100111110': 1, '001011111010000110111000001110': 1, '000111000010000010010010001111': 1, '110110101111010001011110110011': 1, '110110101101100010001111010101': 1, '111000101110001111010000110000': 1, '110110111111101011010001100011': 1, '100011010011100011001111001111': 1, '110001000011100011111110001010': 1, '000111000110101000111100101011': 1, '001101110010110111101010000100': 1, '011010101000001110001001000101': 1, '001000101000110000110110000110': 1, '111001111001100010101111110001': 1, '010110001111111110101000101001': 1, '001001110111100100001101000101': 1, '101000010111010100001010001001': 1, '110010101101010000001101100111': 1, '011101000011010000100001001110': 1, '111110011110100101101100000100': 1, '110111001101010111100010111101': 1, '010011111011000110000100010011': 1, '100000000111001000110001101001': 1, '000001101000110011111000000010': 1, '010111111101100101101001010110': 1, '100100011110011011011111110000': 1, '111011101000111110000101001101': 1, '101000011110000000111111111110': 1, '111010011001010001010111101001': 1, '100011000111111111110011111001': 1, '010101101011101001010111110110': 1, '001111111000001011010100101011': 1, '011000110101000010010010011011': 1, '011010011100111001011111011100': 1, '101000101000001110011111000010': 1, '011111111100111100010111101001': 1, '101010100100000001001011111000': 1, '000111101010110010101000100010': 1, '001000101110000011011111011010': 1, '000110101011101100111010110101': 1, '011001001010010101101111100001': 1, '000000010110110100000111100101': 1, '010100100001101010110001111011': 1, '010110101110010010111111101011': 1, '110111000001101001001110000110': 1, '100010100111000010000000010010': 1, '110100011111101111111010111101': 1, '100000010111000100010101111110': 1, '110010010000010111110010110001': 1, '001101000101000100001010110010': 1, '010001010011100011010011110011': 1, '011010110001000110011110100101': 1, '010100010111110011101111001111': 1, '011111100100001001000010011101': 1, '110110001110001100011000001011': 1, '101010010111001000100110100100': 1, '101010011110100100000000111000': 1, '100010101110110111010111010010': 1, '101000011011101101100001001101': 1, '101101000100010000111111111111': 1, '010100110001100101000101000011': 1, '001000101001001110110110011100': 1, '011000010010011010111000111010': 1, '101110011001011010011100000011': 1, '100101010000111101110101110010': 1, '001011101010110001000010110010': 1, '110100100011001010100111110000': 1, '100111011001010111000110001111': 1, '010001110011010111010011110010': 1, '100101000000110110110010000011': 1, '010110000100111101101111001111': 1, '011101001100001001001001110111': 1, '000011000100100110000011000010': 1, '110110000101000101000001010100': 1, '011110011100110011101110110011': 1, '011100110100100110101100010010': 1, '111101100011001111111010100000': 1, '011111011111011000111111111010': 1, '000110000000110101001011011011': 1, '101110110110110010101000011011': 1, '000100010001101011001001111011': 1, '000010101011100111100110001111': 1, '011010110111010111000101110101': 1})

40-qubit task COMPLETED.
QFT:
This task ran 100 shots and the total runtime was 29304 ms
Measurement results: Counter({'0111101100100010100100000111011001110100': 1, '1110111000001001011001101100110010000001': 1, '1010000111110100011100010011100110011101': 1, '0101111100111000100110010111000101010000': 1, '1000001001101000010100101000111010001111': 1, '1110100101100010101101000100100000011010': 1, '1100001000100100011001010001001110100100': 1, '1000100101010110101101001010100010010000': 1, '1011010111101011111111010111011011100100': 1, '0110011100010101011011111110010010010001': 1, '1101100011011101001100111001011010110010': 1, '1001000110101001110010111001101101110110': 1, '0010110001111001110100011100111110010101': 1, '1111000010101010100111001011100011110110': 1, '1001011111001100010010111101000101011010': 1, '1011000001011001011100111101110111000000': 1, '0000110001010011011001101111110000010100': 1, '1000110111101010000000101111001100111000': 1, '1111110100111011001010010101011101101000': 1, '0000101100110001101110111011000111000010': 1, '1111010100010110101101001111101111111111': 1, '1100100010000111101111011001100110011010': 1, '1111011001111010010111001110111011001110': 1, '0111010111100101000111111111100000111010': 1, '0110110110011100011111010100011010100000': 1, '0011111001110110111001100011000011001100': 1, '1100110001111011000100000010000011011010': 1, '1110100001010011000001000000110100011011': 1, '0100100001010001000101111110101110111100': 1, '0001001001011101110010011000100010001110': 1, '0111011010100010011010101000000100111101': 1, '1101001100110000010000001011101100101010': 1, '1000001000101001101001000101011100000100': 1, '0010100011010001111010011101100011100000': 1, '0010110100101110111000000011111100110110': 1, '0000101111110101111110101010110101101000': 1, '1111111010000100001010100000101011111011': 1, '0110110101000111010111010011110011101100': 1, '0101001100011100110011110100001010001010': 1, '1011001001011110101101010101100010011010': 1, '0000111101110111101011111111111011001011': 1, '0101000101011110010101111000110011000000': 1, '1100011010101110000101100111111000011110': 1, '1001010101100000011011101100010111000111': 1, '1001001100011111010010101000010000110110': 1, '1011110100001010111010011111011001110111': 1, '0011111111101011000100001111111111011111': 1, '1101110100000100010100001110001110100101': 1, '1110110011011100000010100011110010111101': 1, '0111111011111000010111010000101001110010': 1, '0010100110100001100001100111101100011001': 1, '1100100101000011001010010101100100100100': 1, '0110111100110101101010000000000011011001': 1, '0111101001111011110100100101010001010000': 1, '1001111010001010000010110100111111111000': 1, '1000010100010101000000000110000010000110': 1, '0011011101100111101001110001100100101110': 1, '1110010111000101011100011000110100000111': 1, '1100001000110010010110100101101110000001': 1, '1010010100111000000000010101000101011011': 1, '0110111011000111001011000110010110001001': 1, '1101100111011111100001011000001001100100': 1, '0111001110101011001010000010000111001100': 1, '0000001000011001011110011110110110010101': 1, '0101110011101110000101010100000111100000': 1, '1010111001000010010011000000001010010111': 1, '0001010001101000000111101010011100110110': 1, '0001001000011011011100000011011100111000': 1, '1100101001000011111110101100010101001110': 1, '1100000001000110100110101011111111101110': 1, '1000010100110100100110110001011110100001': 1, '0100111000000000100110001101110111111001': 1, '0000011111000010000111010111000010100000': 1, '0010000100100100010000000000111001100111': 1, '1101101101100101000111111000110100100100': 1, '1001111100101101100101001110011101100011': 1, '0111100100011111010001011010101110111111': 1, '0001001100101000010110001010110110011011': 1, '1100100110101000001110100101010111010010': 1, '1101100010110001011001001010110000101010': 1, '0100011111111100101010011110001110001101': 1, '1000011000101111110001110101101110000011': 1, '0001010110111010010110011011110110101101': 1, '0011000001000011011111010111001010100110': 1, '0110000000001010001100100111001100101100': 1, '0010011000101101010001101101100010001100': 1, '1010101101010111001100001011111100110111': 1, '0010001100001100111111100101001000000001': 1, '1011010001101100111101111010101011001011': 1, '1110110111011001100001110001001100000001': 1, '0000010011101111000000000110000001001000': 1, '0010000111010011010001110011111111100101': 1, '0010010110001100000111110010010000011011': 1, '0111011101001000100000101111100111100100': 1, '1101100100101100111111101110110010011001': 1, '0100101010010111111100100110001011110101': 1, '0001011111001010001001100100110010100111': 1, '0011001100011101011110110000011110000110': 1, '0111010100001110010100111001010101000100': 1, '1101110011101101111011001100001100110010': 1})

## Circuit geometry is extremely important for TN1

We'll now examine a type of circuit that is harder for the tensor network simulator: local Hayden-Preskill circuits. "Local" here means that multi-qubit gates only act on qubits which are nearest-neighbors. In this case, we will simulate a one-dimensional chain, and so any 2-qubit gates will act on qubits `q` and `q+1`. These circuits are generated in the following way:

For each of `N` gates:
- Choose a single qubit gate with 50% chance
    - Choose between x-, y-, or z-rotations and Hadamard with equal likelihood.
    - If a rotation is chosen, the angle is chosen from a uniform random distribution between `0` and `2*pi`.
    - The qubit `q` to which to apply the gate is chosen randomly with equal likelihood from among all the available `N` qubits
- Choose a CZ gate with 50% chance
    - The qubit `q` to which to apply the control is chosen randomly with equal likelihood from among `N-1` qubits. The `Z` gate is applied to `q+1`.

Circuits of this type are effective at generating entanglement among qubits. We can see this by scaling the number of gates applied quadratically with the number of qubits. This is enough gates to spread entanglement throughout all the qubits. We see that the circuit becomes more time consuming to simulate as we apply more gates._____no_output_____

@circuit.subroutine(register=True)
def local_Hayden_Preskill(num_qubits, num_gates):
    hp_circ = Circuit()
    """Yields the circuit elements for a scrambling unitary.
    Generates a circuit with numgates gates by laying down a
    random gate at each time step.  Gates are chosen from single
    qubit unitary rotations by a random angle, Hadamard, or a
    controlled-Z between a qubit and its nearest neighbor (i.e.,
    incremented by 1)."""
    qubits = range(num_qubits)
    for i in range(num_gates):
        if np.random.random_sample() > 0.5:
            """CZ between a random qubit and the next qubit to its left."""
            a = np.random.choice(range(len(qubits)-1), 1, replace=True)[0]
            hp_circ.cz(qubits[a],qubits[a+1])
        else:
            """Random single qubit rotation."""
            angle = np.random.uniform(0, 2 * math.pi)
            qubit = np.random.choice(qubits,1,replace=True)[0]
            gate  = np.random.choice([Gate.Rx(angle), Gate.Ry(angle), Gate.Rz(angle), Gate.H()], 1, replace=True)[0]
            hp_circ.add_instruction(Instruction(gate, qubit))
    return hp_circ_____no_output_____

## Visualizing the Hayden-Preskill circuit

Let's examine the geometry of some HP circuits of varying depths. We can see that the deeper the circuit, the more likely it is for (mediated) connections to exist among all qubits._____no_output_____

num_qubits = 5
for num_gates in range(5, 26, 5):
    print('')
    print(f"HAYDEN PRESKILL CIRCUIT WITH {num_gates} GATES:")
    my_hp_circ = local_Hayden_Preskill(num_qubits, num_gates)
    print(my_hp_circ)
HAYDEN PRESKILL CIRCUIT WITH 5 GATES:
T  : |   0   |1|2|

q0 : -Ry(4.4)-----

q1 : -C-------C---
      |       |
q2 : -Z-------Z-H-

q4 : -H-----------

T  : |   0   |1|2|

HAYDEN PRESKILL CIRCUIT WITH 10 GATES:
T  : |   0    |   1    |   2    |   3    |   4    |

q0 : -Rx(2.55)-C--------Ry(2.69)-------------------
               |
q1 : -Rz(3.43)-Z-----------------------------------

q2 : -------------------C--------------------------
                        |
q3 : -C--------Rz(1.55)-Z--------Ry(1.85)-Ry(2.18)-
      |
q4 : -Z--------Rz(4.75)----------------------------

T  : |   0    |   1    |   2    |   3    |   4    |

HAYDEN PRESKILL CIRCUIT WITH 15 GATES:
T  : |   0    |   1    |   2    |   3    |   4    |5|

q0 : -Rx(5.92)-Rx(4.39)-Ry(4.23)---------------------

q1 : -C-----------------C--------H-------------------
      |                 |
q2 : -Z--------Ry(3.48)-Z--------Ry(4.12)-C--------C-
                                          |        |
q3 : ----------C--------------------------Z--------Z-
               |
q4 : -Rz(3.71)-Z--------Rz(3.6)--Rz(5.85)-Ry(3.85)---

T  : |   0    |   1    |   2    |   3    |   4    |5|

HAYDEN PRESKILL CIRCUIT WITH 20 GATES:
T  : |0|    1    |   2    |3|4|   5    |   6    |7|8|9|   10   |11|12|

q0 : -C-Rz(0.617)-Ry(5.44)-C-C-C--------H-----------------------------
      |                    | | |
q1 : -Z-C---------C--------Z-Z-Z--------------------------------------
        |         |
q2 : ---Z---------Z--------C-C-Rz(3.42)------------C---------------C--
                           | |                     |               |
q3 : ----------------------Z-Z-Ry(5.33)-Rx(4.68)-H-Z-C-Rx(4.48)-C--Z--
                                                     |          |
q4 : ------------------------------------------------Z----------Z-----

T  : |0|    1    |   2    |3|4|   5    |   6    |7|8|9|   10   |11|12|

HAYDEN PRESKILL CIRCUIT WITH 25 GATES:
T  : |   0    |   1    |   2   |   3    |   4    |5|   6    |   7    |   8    |   9    |

q0 : ----------C--------Rz(2.4)-Rz(2.91)-Ry(5.41)-C-Ry(1.73)----------------------------
               |                                  |
q1 : -C--------Z----------------------------------Z-C--------C--------------------------
      |                                             |        |
q2 : -Z--------H--------H-------Ry(1.62)-C--------H-Z--------Z--------Ry(2.88)-Ry(1.73)-
                                         |
q3 : -H----------------------------------Z--------C-Rx(1.78)-Ry(4.73)-Ry(3.26)----------
                                                  |
q4 : -Rz(0.39)-Rx(2.86)-H-------Ry(6.23)----------Z-------------------------------------

T  : |   0    |   1    |   2   |   3    |   4    |5|   6    |   7    |   8    |   9    |

## Experimenting with Hayden-Preskill circuits

We will examine runtimes for various depths of circuits at relatively low (for TN1) qubit counts. This is to ensure that our job finishes in a reasonable amount of time. We'll examine the measurement counts at the end of each simulation. Because these are random circuits, we should not expect to see the measurement counts highly concentrated in a few outcomes._____no_output_____

Caution: Running the following cell will take about 2 minutes. Only uncomment it if you are happy to wait.

_____no_output_____

#num_qubits  = 50
#n_shots     = 10
#gate_range  = range(500, 1001, 250)
#tn_tasks    = {}
#tn_results  = {}
#for gates in gate_range:
#    # construct HP circuit
#    circ = Circuit()
#    # ensure the HP circuit is runnable -- circuits must have depth <= 100
#    while True:
#        circ = local_Hayden_Preskill(num_qubits, gates)
#        if circ.depth <= 100:
#            break
#    tn_tasks[circ.depth] = tn_device.run(circ, shots=n_shots)
#
#for depth in tn_tasks.keys():
#    tn_status = tn_tasks[depth].state()
#    while tn_status != 'COMPLETED':
#        tn_status = tn_tasks[depth].state()
#
#    tn_results[depth] = tn_tasks[depth].result()
#    # get the running time of the task
#    tn_runtime = tn_results[depth].additional_metadata.simulatorMetadata.executionDuration
#
#    # get the measurement counts
#    tn_counts = tn_results[depth].measurement_counts
#
#
#    print('{}-qubit {}-depth task {}.'.format(num_qubits,depth,tn_status))
#    print('Hayden-Preskill circuit:')
#    print('This task ran {} shots and the total runtime was {} ms'.format(n_shots,tn_runtime))
#    print("Measurement results: {}\n".format(tn_counts))50-qubit 33-depth task COMPLETED.
Hayden-Preskill circuit:
This task ran 10 shots and the total runtime was 16752 ms
Measurement results: Counter({'10000011001011101000000100111011111110000010001010': 1, '00000111110011001110011101101011010101101111001000': 1, '01010111011111010110000100100011011101001111001101': 1, '10010011111110101000010010101010010010010110001000': 1, '10010111010010101111000011101011010110011100101000': 1, '10010111001000001110011100100010010110110101101001': 1, '10011110101011101101010100101011110110011010001001': 1, '10001011110000101101011111111111011111101101101000': 1, '11000011111101011001010111010010010111000111101000': 1, '10000111111111001111001000101101010111010101101000': 1})

50-qubit 44-depth task COMPLETED.
Hayden-Preskill circuit:
This task ran 10 shots and the total runtime was 28063 ms
Measurement results: Counter({'01110001110011011110010000011001000000101101010011': 1, '10111011100100110111000110011000001000001010000001': 1, '10100001110011110011101100011000000011101100010010': 1, '01001001101101110111100010101101000011111011010011': 1, '11101011100000111000000000101001000010100011010011': 1, '01110001100001110011100101011001000000000100011011': 1, '10000001110101110101100110101011001010101100110011': 1, '00011001110101011011100110101100000011101001101000': 1, '00100001110001110001100010000110010000100001010011': 1, '10110011010011010010000010111000000011110010110011': 1})

50-qubit 61-depth task COMPLETED.
Hayden-Preskill circuit:
This task ran 10 shots and the total runtime was 41970 ms
Measurement results: Counter({'01101001011011100001000111011010110000000111010111': 1, '01101100011000000000011100111111111000011101111011': 1, '01000011010111001100100111101111011000110001111101': 1, '01111011110111101000010000011010100101110001010111': 1, '01000001110111111100110010010000000010001001110010': 1, '01000110010111010000000101001110010010011011010111': 1, '01010111000111111100001110010101111110000100110111': 1, '01000100011010010010001111010000011101011001111011': 1, '11101000011011111100100100011000100100001111110111': 1, '01010111111011000001001111010100101100000101110111': 1})

## The effect of shot counts on runtimes in TN1

In order to generate samples from a quantum circuit, TN1 first partitions the qubits into groups, and then contracts each group in turn, generating a prediction for the current group's configuration based on the results of previously encountered groups. Because of this, in the worst case, the time to generate `n` shots may scale linearly with `n`. However, if the number of possible outcomes is small (as it is in the GHZ or QFT case), the runtime is effectively constant no matter the number of shots. We will examine this behavior below. It's therefore important to understand that your job may be rejected if the time to contract all the shots you have requested is too large. In this case your task will finish with a `FAILED` message, and the `failureReason` will be `Predicted runtime based on best contraction path found exceeds TN1 limit.` -- in this case you can attempt to retry the computation with fewer shots._____no_output_____

Note: Because the runtime of the task can scale linearly with the number of shots in the worst case, it is strongly advised that users run their circuits with a small number of shots (20 or fewer) to explore typical runtimes for their circuit before running the circuit for many shots.

_____no_output_____

Caution: Running the following cell will take about 3 minutes. Only uncomment it if you are happy to wait.

_____no_output_____

#num_qubits = 30
#ghz_circ = ghz_circuit(num_qubits)
#qft_circ = qft(range(num_qubits))
#hp_circ  = Circuit()
#while True:
#    hp_circ = local_Hayden_Preskill(num_qubits, 750)
#    if circ.depth <= 100:
#        break
#ghz_tasks    = {}
#ghz_results  = {}
#qft_tasks    = {}
#qft_results  = {}
#hp_tasks     = {}
#hp_results   = {}
#for n_shots in [10, 40]:
#    ghz_tasks[n_shots] = tn_device.run(ghz_circ, n_shots)
#    qft_tasks[n_shots] = tn_device.run(qft_circ, n_shots)
#    hp_tasks[n_shots]  = tn_device.run(hp_circ, n_shots)
#
#for n_shots in [10, 40]:
#    ghz_status = ghz_tasks[n_shots].state()
#    while ghz_status != 'COMPLETED':
#        ghz_status = ghz_tasks[n_shots].state()
#
#    qft_status = qft_tasks[n_shots].state()
#    while qft_status != 'COMPLETED':
#        qft_status = qft_tasks[n_shots].state()
#
#    hp_status  = hp_tasks[n_shots].state()
#    while hp_status != 'COMPLETED':
#        hp_status = hp_tasks[n_shots].state()
#
#    ghz_results[n_shots] = ghz_tasks[n_shots].result()
#    qft_results[n_shots] = qft_tasks[n_shots].result()
#    hp_results[n_shots]  = hp_tasks[n_shots].result()
#    # get the running time of the task
#    ghz_runtime = ghz_results[n_shots].additional_metadata.simulatorMetadata.executionDuration
#    qft_runtime = qft_results[n_shots].additional_metadata.simulatorMetadata.executionDuration
#    hp_runtime  = hp_results[n_shots].additional_metadata.simulatorMetadata.executionDuration
#
#    print('GHZ task ran {} shots and the total runtime was {} ms'.format(n_shots,ghz_runtime))
#    print('QFT task ran {} shots and the total runtime was {} ms'.format(n_shots,qft_runtime))
#    print('HP task ran {} shots and the total runtime was {} ms'.format(n_shots,hp_runtime))GHZ task ran 10 shots and the total runtime was 2510 ms
QFT task ran 10 shots and the total runtime was 7197 ms
HP task ran 10 shots and the total runtime was 22564 ms
GHZ task ran 40 shots and the total runtime was 2545 ms
QFT task ran 40 shots and the total runtime was 10201 ms
HP task ran 40 shots and the total runtime was 36307 ms


# Notebook from noaodatalab/notebooks_default
Path: 06_EPO/TeenAstronomyCafe/08_Breaking_the_Solar_System/Breaking_the_Solar_System.ipynb

# Breaking the Solar System
### And other ways simulations help us understand the Universe

Created by Rachel Smullen and Christine O'Donnell in Spring 2020.

In this computer activity, we're going to run simulations of planetary systems in order to understand how stable the Solar System is. Would the Solar System look the same if everything was 10 times more massive? What about if the planets were spaced closer together? Farther apart?

We hope that, by the end of today's activity, you'll have the answers!
_____no_output_____The type of simulations we're running here are called **N-body simulations** because they use the gravitational force between bodies to predict the positions of those bodies in the future.  Remember that the gravitational force between two bodies is defined as

$$
 F = \frac{-Gm_1m_2}{r^2}
$$

where $G$ is the gravitational constant, $m_1$ is the mass of one body, $m_2$ is the mass of the other body, and $r$ is the distance between bodies. If the objects are closer, or if one of the bodies is massive, the force will be larger, leading to larger tugs between bodies that can make some crazy things happen._____no_output_____**For the rest of this notebook, your tasks will always be bold and red like this.**

This activity is designed to be used in conjunction with the worksheet in this folder.
________no_output_____## How to Use This Notebook

The webpage you are in is actually an app - much like the ones on your cellphone. This app consists of cells.

An *input* cell looks like a light grey box with an `In [ ]:` on its left. Input cells each contain code - instructions to make the computer do something.

To activate or select a cell, click anywhere inside of it. It will be outlined in a green box if it is selected.

**Select the cell below and read its contents.**_____no_output_____

# Text that follows a "#" is known as a comment.
# Comments do not affect your code in any way.
# You should always read the comments at the top of each cell you interact with.
# Comments will be used to describe what the cell's code is actually doing._____no_output_____

To execute or run a selected cell, hit `[Shift + Enter]` on your keyboard.

If you accidentally double click on a text cell and it looks like a code cell, use `[Shift + Enter]` to put it back to normal.

**Select the cell below and read its contents. Then, run the cell.**_____no_output_____

# Text that DOESN'T follow a "#" is considered code.
# Lines of code are instructions given to your computer.
# The line of code below is a "print" statement.
# A print statement literally prints out the text between its quotes.

print("Congrats! You have successfully run your first cell!")_____no_output_____

Running a cell creates an *output* directly below it. An output can be some text, a graph, an interactive slider, or even nothing at all! For that last case, you know you have run a cell when the `In [ ]:` becomes `In [#]:`, where "#" is any number.  If the code is still in progress, the input cell will look like `In [*]:`.

You can learn more about how Jupyter notebooks work at https://try.jupyter.org/_____no_output________
#### Before we start simulating
We need to load the software we'll use in this activity. We're using a really nice simulation package called `Rebound` that does most of the hard work for us.  The first rule of writing new software is that it has to have a good name!
**Run the cell below.**_____no_output_____

# Software loading
# DO NOT CHANGE ANYTHING IN THIS CELL

# Simulation package
import rebound

# Math packages
from numpy import *

# Plotting packages and settings
import matplotlib.pyplot as plt
plt.rcParams['animation.html']='jshtml'
plt.rcParams['animation.embed_limit']=1024
%matplotlib inline

# Behind-the-scenes tools to simplify code
%run Files/tools.ipynb _____no_output_____

___
## Simulate a Single Planet_____no_output_____There are four steps to running a simulation of a planetary system.  This section walks you through each piece of the puzzle.

Run each of the code cells below when you understand what it does._____no_output_____1\. First, we need to **create a Rebound simulation**

We'll add all of our stars and planets to this simulation object._____no_output_____

mysim = initialize_simulation() # This will create a simulation called 'mysim'_____no_output_____

2\. Next, we need to **add a central star** for our planets to orbit.  We must specify the star's _mass_ and _name_. The star should always be the first object added to the simulation.

The star's mass must have units of **solar masses** (units where the Sun's mass is 1) and can have any name you want (as long as it is surrounded by quotation marks `"` or `'`)_____no_output_____

add_star(mysim,name='star',mass=1.0) # add a star to mysim, with mass in units of solar masses_____no_output_____

3\. Then, we need to **add our planet(s)**.  Planets must have a *mass*, *name*, and *semi-major axis*. Each planet requires its own line

Planets can also have an *eccentricity*, *inclination*, *argument of perihelion*, *longitude of ascending node*, and *true anomaly*, but these values default to 0 if not specified. Remember that these quantities are described on your worksheet. The values $i$, $\omega$, $\Omega$ and $f$ all have units of degrees ($0-360^\circ$). You can specify as many or as few of these quantities as needed.

The planet's mass must be in units of **Jupiter masses** (units where the mass of Jupiter is 1), and the semi-major axis must have units in **astronomical units (AU)** (units where the distance between the Sun and Earth is 1). Again, the name must be wrapped in quotation marks.

As an aside: Jupiter's mass is ${\approx}1/1000$ times that of the Sun. Earth's mass is ${\approx}\frac{1}{300}$ times that of Jupiter, or $\frac{1}{300{,}000}$ times the mass of the Sun. _____no_output_____

add_planet(mysim,name='planet',mass=1,a=1) # add a planet to mysim with mass in Jupiter masses and a in AU_____no_output_____

4\. Finally, we need to **run our simulation** for an amount of time that we specify with the variable *end\_time*.  This piece of code returns a movie of the orbits that we can look at by typing the movie's name. It also returns a plot of the semi-major axis, distance from the star, and eccentricity as a function of time

Time in the simulation is measured in **years**.  This step can take a while! The code is running if you see `In [*]:`_____no_output_____

movie = run_simulation(mysim,end_time=10) # run mysim for 10 years
movie # show the movie_____no_output_____

There are some things you should notice that may be helpful in the next steps.

First, while the simulation was running, you should have seen a progress bar with some numbers off to the side. The progress bar is to help you see the status of your simulation.  For very short simulations, the simulation may run too fast for the progress bar to show up. The meaning of the numbers are shown in the picture below.  In particular, the "% Done" and "Time Remaining" numbers are quite useful._____no_output__________no_output_____Second, you have a movie to play with that shows a "top down" view of our planetary system.  The controls of the movie are shown in the picture below._____no_output__________no_output_____Sometimes the movies may appear to run backward or stay stationary.  This is called the ["wagon wheel effect"](https://en.wikipedia.org/wiki/Wagon-wheel_effect).  If the planet appears to stay still, the frames in the movie are being output once every time the planet goes around the star an integer number of times.  If the planet appears to move backward, the frames are being output when the planet goes around more than once but less than twice (or an integer multiple of that) between frames._____no_output_____**Before we go any further**, know that we can put all of the code into one cell to make things simpler. An example is shown below.  You do _not_ need to run this code._____no_output_____

# Create simulation
mysim = initialize_simulation()

# Add a star
add_star(mysim, name='Sun', mass=1.0)

# Add some planets
add_planet(mysim, name='big planet', mass=1, a=1) # a Jupiter at 1 AU
add_planet(mysim, name='small planet', mass=1/300, a=5, e=0.2, i=10, omega=180, Omega=90, f=143) # an eccentric Earth at 5 AU

# Run the simulation and show the movie
movie = run_simulation(mysim,end_time=100)
movie_____no_output_____

___
## Simulate a Hot Jupiter Exoplanet

We first discovered a planet outside our own Solar System in 1995.  The planet is named 51 Pegasi b, and the two scientists who found it were awarded the Nobel Prize in Physics in 2019 for their discovery.

51 Pegasi b, and most of the other exoplanets (planets outside our own Solar System) discovered before 2012 are a class of planets called **hot Jupiters**.  These are _massive_ planets that orbit _very close_ to their host star and are typically _eccentric_.  We've compiled a list of known hot Jupiters at [this link](Files/hot_Jupiters.html).
_____no_output_____**Following along in your worksheet, simulate your first planet!** Select your favorite hot Jupiter from the list linked above. Create a new simulation and add your star and planet. Run the simulation for 5 years. Assume any orbital parameters not listed in the table are 0.

Copy-paste is totally okay, as long as you check all of your numbers! 🙃 _____no_output_____🛑 **Let's wait for everyone to get here before going further.**  Make sure your worksheet is filled out! If you're done early, share your results._____no_output_________
## Simulate the Solar System_____no_output_____Before we get to breaking the Solar System, let's first make sure we can get it to work in it's current configuration.

**First, un-comment all lines in the cell below (remove the first '#' sign from all lines), and add the Sun and the giant planets to the simulation below and run it for 100 years.** The orbital elements for the Solar System are in your worksheet. Neptune's orbit takes 164 years. Does it even make one full orbit around the Sun? How do you expect the orbital elements will change on long timescales, considering that the Solar System has existed for 4.5 billion years?_____no_output_____

## Initialize the simulation
#mysim = initialize_simulation()
#
## Add the Sun here
#
#
## The inner terrestrial planets
#add_planet(mysim, name='Mercury', mass=0.00017, a=0.38, e=0.22, i=7.1, omega=30,  Omega=48,  f=201)
#add_planet(mysim, name='Venus',   mass=0.0026,  a=0.74, e=0.02, i=3.4, omega=91,  Omega=7,   f=347)
#add_planet(mysim, name='Earth',   mass=0.0031,  a=1.00, e=0.01, i=0.0, omega=335, Omega=133, f=86)
#add_planet(mysim, name='Mars',    mass=0.00034, a=1.51, e=0.09, i=1.9, omega=292, Omega=49,  f=281)
#
## Add the giant planets here
#
#
## Pluto-Charon, just for fun. :)
#add_planet(mysim, name='Pluto-Charon', mass=0.000007, a=39.5, e=0.25, i=17.1, omega=114, Omega=110, f=69)
#
## Run the simulation
#movie = run_simulation(mysim, end_time=0)
#movie_____no_output_____

You might have noticed that this simulation took a long time to run compared to the simulations we ran earlier. There are three big things that impact the time you have to twiddle your thumbs when running simulations like these:
1. The finishing time of the simulation (obviously).
2. The number of bodies in the simulation. Each step requires $N^2$ calculations, so for a two planet system, there are four calculations required (the star on each planet and each planet on each other) and for an eight planet system, like the Solar System, there are 256.  Fewer planets means a faster simulation.
3. The distance of the closest planet to the star.  Because we're approximating the orbits between timesteps, we have to take smaller steps to get a good approximation if there is a close in planet. For instance, if we put Mercury in our simulation, one year requires 83 simulation steps, but if Jupiter is the closest planet to the Sun, one year requires 2 simulation steps. A more distant inner planet means a faster simulation._____no_output_____🛑  **Before moving on to the next section of coding, do Section 3 of the worksheet. Consider what you've learned in the lecture and the coding activities you've already done.**  We'll have a group discussion before moving on to the final section._____no_output________
## ...And Now Break the Solar System

How sensitive is the stability of the Solar System? You get to find out!_____no_output_____**Run a few simulations to figure out the smallest change you need to break the Solar System based on the criterion you defined in the worksheet!**

* Each simulation you test should go in its own cell.  At the top of the cell, type a comment to remind yourself what you're testing. Remember that comments start with `#`.
* Run each simulation to an end time of 10 million years.  This can be written in your code as `end_time=10E6` (capital E is important; in code talk, this translates to $10\times10^6$).
* Make sure to fill out your worksheet as you go along!
_____no_output_____

# Parameter being tested:

# Add your simulation below
_____no_output_____# Parameter being tested:

# Add your simulation below
_____no_output_____# Parameter being tested:

# Add your simulation below
_____no_output_____# Parameter being tested:

# Add your simulation below
_____no_output_____# Parameter being tested:

# Add your simulation below
_____no_output_____

Do you really like a movie you made? You can save it to take home by putting the following command at the end of the cell that made the movie (you can change `'mymovie'` to any name you like) . It will then be in the folder for you to download to your local computer._____no_output_____

movie.save('mymovie.mpeg')_____no_output_____