```python
!git clone https://github.com/abdalazizrashid/AI-Feynman.git
```

    fatal: destination path 'AI-Feynman' already exists and is not an empty directory.

```python
!pip install -r AI-Feynman/requirements.txt
```

    Requirement already satisfied: torch in /usr/local/lib/python3.6/dist-packages (from -r AI-Feynman/requirements.txt (line 1)) (1.6.0+cu101)
    Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (from -r AI-Feynman/requirements.txt (line 2)) (1.18.5)
    Requirement already satisfied: matplotlib in /usr/local/lib/python3.6/dist-packages (from -r AI-Feynman/requirements.txt (line 3)) (3.2.2)
    Requirement already satisfied: sympy in /usr/local/lib/python3.6/dist-packages (from -r AI-Feynman/requirements.txt (line 4)) (1.1.1)
    Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (from -r AI-Feynman/requirements.txt (line 5)) (1.0.5)
    Requirement already satisfied: scipy in /usr/local/lib/python3.6/dist-packages (from -r AI-Feynman/requirements.txt (line 6)) (1.4.1)
    Requirement already satisfied: sortedcontainers in /usr/local/lib/python3.6/dist-packages (from -r AI-Feynman/requirements.txt (line 7)) (2.2.2)
    Requirement already satisfied: tabulate in /usr/local/lib/python3.6/dist-packages (from -r AI-Feynman/requirements.txt (line 8)) (0.8.7)
    Requirement already satisfied: future in /usr/local/lib/python3.6/dist-packages (from torch->-r AI-Feynman/requirements.txt (line 1)) (0.16.0)
    Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->-r AI-Feynman/requirements.txt (line 3)) (2.8.1)
    Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->-r AI-Feynman/requirements.txt (line 3)) (1.2.0)
    Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib->-r AI-Feynman/requirements.txt (line 3)) (0.10.0)
    Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->-r AI-Feynman/requirements.txt (line 3)) (2.4.7)
    Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.6/dist-packages (from sympy->-r AI-Feynman/requirements.txt (line 4)) (1.1.0)
    Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.6/dist-packages (from pandas->-r AI-Feynman/requirements.txt (line 5)) (2018.9)
    Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (from python-dateutil>=2.1->matplotlib->-r AI-Feynman/requirements.txt (line 3)) (1.15.0)

```python
!cd /content/AI-Feynman/Code/ && ./compile.sh && apt install -y parallel

```

    Reading package lists... Done
    Building dependency tree
    Reading state information... Done
    parallel is already the newest version (20161222-1).
    The following package was automatically installed and is no longer required:
      libnvidia-common-440
    Use 'apt autoremove' to remove it.
    0 upgraded, 0 newly installed, 0 to remove and 35 not upgraded.

```python
import os
os.chdir("/content/AI-Feynman/Code/")
print(os.getcwd())
```

    /content/AI-Feynman/Code

```python
from S_run_aifeynman import run_aifeynman

```

## Original Code Example

```python
%%time
run_aifeynman("../example_data/","example1.txt",30,"14ops.txt", polyfit_deg=3, NN_epochs=400)
```

    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [36.83243537730492, 29.12634010089305, cos(x0) + cos(x2 + x3) + 2.333740234375]
    [55.42220420859321, 29.09077077952536, cos(x2 + x3) + 1.88584470748901]
    [63.97127597744305, 28.649814958454094, '1.808310192134*(cos(((x3-x2)/pi)))**(-1)']
    [73.2730466728654, 26.754024113174246, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.125*x1 + 0.2*x2**2 - 0.444444444444444*x2*x3 + 0.166666666666667*x2 + 0.2*x3**2 + 0.166666666666667*x3 + 0.2']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [36.83243537730492, 29.12634010089305, cos(x0) + cos(x2 + x3) + 2.333740234375]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [48.48784302438703, 26.85871313046377, 'tan(0.036548656722*exp(pi))']
    [48.613819620546025, 26.858713124630636, 'tan(0.269214177330*pi)']
    [73.2730466728654, 26.754024113174246, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.125*x1 + 0.2*x2**2 - 0.444444444444444*x2*x3 + 0.166666666666667*x2 + 0.2*x3**2 + 0.166666666666667*x3 + 0.2']
    [206.23011212397856, 26.70884811651698, tan(0.694796025753021*log(-0.642380475997925*cos(x2 - 1.00466322898865*x3) + 3.26658010482788))]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [36.83243537730492, 29.12634010089305, cos(x0) + cos(x2 + x3) + 2.333740234375]
    [44.620081767607, 28.75693944878952, -0.270385265350342]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [48.48784302438703, 26.85871313046377, 'tan(0.036548656722*exp(pi))']
    [48.613819620546025, 26.858713124630636, 'tan(0.269214177330*pi)']
    [73.2730466728654, 26.754024113174246, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.125*x1 + 0.2*x2**2 - 0.444444444444444*x2*x3 + 0.166666666666667*x2 + 0.2*x3**2 + 0.166666666666667*x3 + 0.2']
    [206.23011212397856, 26.70884811651698, tan(0.694796025753021*log(-0.642380475997925*cos(x2 - 1.00466322898865*x3) + 3.26658010482788))]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [36.83243537730492, 29.12634010089305, cos(x0) + cos(x2 + x3) + 2.333740234375]
    [44.620081767607, 28.75693944878952, -0.270385265350342]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [48.48784302438703, 26.85871313046377, 'tan(0.036548656722*exp(pi))']
    [48.613819620546025, 26.858713124630636, 'tan(0.269214177330*pi)']
    [73.2730466728654, 26.754024113174246, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.125*x1 + 0.2*x2**2 - 0.444444444444444*x2*x3 + 0.166666666666667*x2 + 0.2*x3**2 + 0.166666666666667*x3 + 0.2']
    [206.23011212397856, 26.70884811651698, tan(0.694796025753021*log(-0.642380475997925*cos(x2 - 1.00466322898865*x3) + 3.26658010482788))]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [2.584962500721156, 30.42456896678888, '0.333333333333333']
    [32.00876552846736, 28.13821400441772, '1/(-0.934925954011+x1)']
    [46.070972708611805, 28.114455148352643, 0.739170650917556]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [48.48784302438703, 26.85871313046377, 'tan(0.036548656722*exp(pi))']
    [48.613819620546025, 26.858713124630636, 'tan(0.269214177330*pi)']
    [73.2730466728654, 26.754024113174246, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.125*x1 + 0.2*x2**2 - 0.444444444444444*x2*x3 + 0.166666666666667*x2 + 0.2*x3**2 + 0.166666666666667*x3 + 0.2']
    [206.23011212397856, 26.70884811651698, tan(0.694796025753021*log(-0.642380475997925*cos(x2 - 1.00466322898865*x3) + 3.26658010482788))]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [2.584962500721156, 30.42456896678888, '0.333333333333333']
    [28.865610660795387, 29.201384954099407, -4.89119133556296e-6]
    [32.00876552846736, 28.13821400441772, '1/(-0.934925954011+x1)']
    [46.070972708611805, 28.114455148352643, 0.739170650917556]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [48.48784302438703, 26.85871313046377, 'tan(0.036548656722*exp(pi))']
    [48.613819620546025, 26.858713124630636, 'tan(0.269214177330*pi)']
    [73.2730466728654, 26.754024113174246, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.125*x1 + 0.2*x2**2 - 0.444444444444444*x2*x3 + 0.166666666666667*x2 + 0.2*x3**2 + 0.166666666666667*x3 + 0.2']
    [206.23011212397856, 26.70884811651698, tan(0.694796025753021*log(-0.642380475997925*cos(x2 - 1.00466322898865*x3) + 3.26658010482788))]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [2.584962500721156, 30.42456896678888, '0.333333333333333']
    [28.865610660795387, 29.201384954099407, -4.89119133556296e-6]
    [28.88485156251213, 29.114959286627403, 'asin(-0.000004956861+(x1*sin(pi)))']
    [29.02302728370149, 29.114941148276046, 'asin(-3.141598108678+pi)']
    [32.00876552846736, 28.13821400441772, '1/(-0.934925954011+x1)']
    [46.070972708611805, 28.114455148352643, 0.739170650917556]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [48.48784302438703, 26.85871313046377, 'tan(0.036548656722*exp(pi))']
    [48.613819620546025, 26.858713124630636, 'tan(0.269214177330*pi)']
    [73.2730466728654, 26.754024113174246, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.125*x1 + 0.2*x2**2 - 0.444444444444444*x2*x3 + 0.166666666666667*x2 + 0.2*x3**2 + 0.166666666666667*x3 + 0.2']
    [206.23011212397856, 26.70884811651698, tan(0.694796025753021*log(-0.642380475997925*cos(x2 - 1.00466322898865*x3) + 3.26658010482788))]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [2.584962500721156, 30.42456896678888, '0.333333333333333']
    [28.865610660795387, 29.201384954099407, -4.89119133556296e-6]
    [28.88485156251213, 29.114959286627403, 'asin(-0.000004956861+(x1*sin(pi)))']
    [29.02302728370149, 29.114941148276046, 'asin(-3.141598108678+pi)']
    [32.00876552846736, 28.13821400441772, '1/(-0.934925954011+x1)']
    [46.070972708611805, 28.114455148352643, 0.739170650917556]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [48.48784302438703, 26.85871313046377, 'tan(0.036548656722*exp(pi))']
    [48.613819620546025, 26.858713124630636, 'tan(0.269214177330*pi)']
    [73.2730466728654, 26.754024113174246, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.125*x1 + 0.2*x2**2 - 0.444444444444444*x2*x3 + 0.166666666666667*x2 + 0.2*x3**2 + 0.166666666666667*x3 + 0.2']
    [206.23011212397856, 26.70884811651698, tan(0.694796025753021*log(-0.642380475997925*cos(x2 - 1.00466322898865*x3) + 3.26658010482788))]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [1.0, 29.661717905473818, '1']
    [28.865610660795387, 29.201384954099407, -4.89119133556296e-6]
    [28.88485156251213, 29.114959286627403, 'asin(-0.000004956861+(x1*sin(pi)))']
    [29.02302728370149, 29.114941148276046, 'asin(-3.141598108678+pi)']
    [32.00876552846736, 28.13821400441772, '1/(-0.934925954011+x1)']
    [35.50977500432694, 1.6280023074285465e-06, '(x0**2 - 2*x0*x1 + x1**2 + x2**2 - 2*x2*x3 + x3**2)**0.5']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [1.0, 29.661717905473818, '1']
    [28.865610660795387, 29.201384954099407, -4.89119133556296e-6]
    [28.88485156251213, 29.114959286627403, 'asin(-0.000004956861+(x1*sin(pi)))']
    [29.02302728370149, 29.114941148276046, 'asin(-3.141598108678+pi)']
    [32.00876552846736, 28.13821400441772, '1/(-0.934925954011+x1)']
    [35.50977500432694, 1.6280023074285465e-06, '(x0**2 - 2*x0*x1 + x1**2 + x2**2 - 2*x2*x3 + x3**2)**0.5']
    Checking for symmetry
     example1.txt_train
    Training a NN on the data...

    tensor(0.0404, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0282, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0354, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0265, device='cuda:0', grad_fn=<DivBackward0>)
    NN loss:  tensor(0.0029, device='cuda:0', grad_fn=<DivBackward0>)

    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [47.56309550289244, 29.20117684355327, 2.07930612564087]
    [50.5090504796962, 28.162061596052734, '0.005215765238+sqrt((x2*x2))']
    [53.788821841164236, 27.623981263190988, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.111111111111111*x0 + 0.2*x1**2 + 0.111111111111111*x1 + 0.2*x2**2 + 0.625']
    [118.35791391022252, 27.41497824744871, -0.971029222011566*cos(x2) + cos(x0 + sin(x1)) + 2.61414766311646]
    [174.23364071878729, 27.411232030672863, '0.2*x0**2 - 0.444444444444444*x0*x1 + 0.117043664748057*x0 + 0.2*x1**2 + 0.111111111111111*x1 + 0.215954831506172*x2**2 + 0.618452302296974']
    [202.75973089793666, 26.4718092017765, -0.971062898635864*cos(x2) - 0.97521698474884*cos(x0 - 0.988607943058014*x1) + 2.4916136264801]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [26.416665599935456, 31.151831594084907, '-tan(0.1*x0*x1 - 0.625)']
    [40.392864438595524, 29.960782005496213, 'tan(-23.126257072703+exp(pi))']
    [40.393057897115405, 29.960777143296564, 'tan(-3.127155157913+pi)']
    [46.0166311684591, 29.95909299612648, '0.711846380458438']
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [46.56058152917947, 27.13339217046357, 1.03784298896790]
    [46.68158917359681, 26.85871306245941, 'tan(-0.845761305278*(x1-(x1+1)))']
    [151.3842928046349, 26.449089073084824, -0.889655292034149*tan(0.102245159447193*cos(x2) - 0.877891777343642)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [4.0, 30.771263892512106, 'acos(-666.000000000000*(x1-((x1+1)-1)))']
    [13.60964047443681, 30.24841398745967, 'acos(0.000000000038*(x0+exp(exp(pi))))']
    [40.392864438595524, 29.960782005496213, 'tan(-23.126257072703+exp(pi))']
    [40.393057897115405, 29.960777143296564, 'tan(-3.127155157913+pi)']
    [44.620081767607, 28.75693944878952, -0.270385265350342]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.56056711257602, 27.133459108345154, 1.03783261803319]
    [46.56057649641146, 27.13342067603215, 1.03783936851191]
    [46.560576570214884, 27.133420535207133, 1.03783942160429]
    [46.56058152917947, 27.13339217046357, 1.03784298896790]
    [46.68158917359681, 26.85871306245941, 'tan(-0.845761305278*(x1-(x1+1)))']
    [151.3842928046349, 26.449089073084824, -0.889655292034149*tan(0.102245159447193*cos(x2) - 0.877891777343642)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [4.0, 30.771263892512106, 'acos(-666.000000000000*(x1-((x1+1)-1)))']
    [13.60964047443681, 30.24841398745967, 'acos(0.000000000038*(x0+exp(exp(pi))))']
    [39.56224242422107, 27.05989455935905, 'log(3*x0**2 - 6*x0*x1 - x0 + 3*x1**2 - x1 + 3*x2**2)']
    [46.68158917359681, 26.85871306245941, 'tan(-0.845761305278*(x1-(x1+1)))']
    [151.3842928046349, 26.449089073084824, -0.889655292034149*tan(0.102245159447193*cos(x2) - 0.877891777343642)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [2.0, 30.21233279612709, '0.500000000000000']
    [32.00876552846736, 28.13821400441772, '1/(-0.934925954011+x1)']
    [39.56224242422107, 27.05989455935905, 'log(3*x0**2 - 6*x0*x1 - x0 + 3*x1**2 - x1 + 3*x2**2)']
    [46.68158917359681, 26.85871306245941, 'tan(-0.845761305278*(x1-(x1+1)))']
    [151.3842928046349, 26.449089073084824, -0.889655292034149*tan(0.102245159447193*cos(x2) - 0.877891777343642)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [2.0, 30.21233279612709, '0.500000000000000']
    [26.736183635149136, 28.02326246238811, exp(-0.119926199316978*exp(exp(cos(x2))))]
    [39.56224242422107, 27.05989455935905, 'log(3*x0**2 - 6*x0*x1 - x0 + 3*x1**2 - x1 + 3*x2**2)']
    [46.68158917359681, 26.85871306245941, 'tan(-0.845761305278*(x1-(x1+1)))']
    [151.3842928046349, 26.449089073084824, -0.889655292034149*tan(0.102245159447193*cos(x2) - 0.877891777343642)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [2.0, 30.21233279612709, '0.500000000000000']
    [26.736183635149136, 28.02326246238811, exp(-0.119926199316978*exp(exp(cos(x2))))]
    [39.56224242422107, 27.05989455935905, 'log(3*x0**2 - 6*x0*x1 - x0 + 3*x1**2 - x1 + 3*x2**2)']
    [46.68158917359681, 26.85871306245941, 'tan(-0.845761305278*(x1-(x1+1)))']
    [151.3842928046349, 26.449089073084824, -0.889655292034149*tan(0.102245159447193*cos(x2) - 0.877891777343642)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [2.0, 30.21233279612709, '0.500000000000000']
    [26.736183635149136, 28.02326246238811, exp(-0.119926199316978*exp(exp(cos(x2))))]
    [39.56224242422107, 27.05989455935905, 'log(3*x0**2 - 6*x0*x1 - x0 + 3*x1**2 - x1 + 3*x2**2)']
    [46.68158917359681, 26.85871306245941, 'tan(-0.845761305278*(x1-(x1+1)))']
    [151.3842928046349, 26.449089073084824, -0.889655292034149*tan(0.102245159447193*cos(x2) - 0.877891777343642)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [1.0, 29.661717905473818, '1']
    [26.736183635149136, 28.02326246238811, exp(-0.119926199316978*exp(exp(cos(x2))))]
    [27.991334457287852, 8.839887073688955e-07, '(x0**2 - 2*x0*x1 + x1**2 + x2**2)**0.5']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 30.834454019627426, '0']
    [1.0, 29.661717905473818, '1']
    [26.736183635149136, 28.02326246238811, exp(-0.119926199316978*exp(exp(cos(x2))))]
    [27.991334457287852, 8.839887073688955e-07, '(x0**2 - 2*x0*x1 + x1**2 + x2**2)**0.5']
    Checking for symmetry
     example1.txt_train-translated_minus
    Found pretrained NN

    tensor(0.0134, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0198, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0220, device='cuda:0', grad_fn=<DivBackward0>)
    NN loss after training:  tensor(0.0051, device='cuda:0', grad_fn=<DivBackward0>)

    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [16.779565475879124, 0.0, '0.000000000000+sqrt(((x1*x1)+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [16.779565475879124, 0.0, '0.000000000000+sqrt(((x1*x1)+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [16.779565475879124, 0.0, '0.000000000000+sqrt(((x1*x1)+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [16.779565475879124, 0.0, '0.000000000000+sqrt(((x1*x1)+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [16.779565475879124, 0.0, '0.000000000000+sqrt(((x1*x1)+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [16.779565475879124, 0.0, '0.000000000000+sqrt(((x1*x1)+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [16.779565475879124, 0.0, '0.000000000000+sqrt(((x1*x1)+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [16.779565475879124, 0.0, '0.000000000000+sqrt(((x1*x1)+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [1.0, 29.661717905473818, '1']
    [4.0, 29.274727392929375, 'pi/2']
    [13.169925001442312, 0.0, '(x0**2 + x1**2)**0.5']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [1.0, 29.661717905473818, '1']
    [4.0, 29.274727392929375, 'pi/2']
    [13.169925001442312, 0.0, '(x0**2 + x1**2)**0.5']
    Checking for symmetry
     example1.txt_train-translated_minus-translated_minus
    Found pretrained NN

    tensor(0.0258, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0227, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0499, device='cuda:0', grad_fn=<DivBackward0>)
    NN loss after training:  tensor(0.0171, device='cuda:0', grad_fn=<DivBackward0>)

    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [12.1357092861044, 29.214205611514426, '1.78000000000000']
    [27.36452797660028, 28.767880375411565, '0.04*x0**2 + 1.78']
    [61.704892355813804, 27.90519712519376, '1.002287261112*log((pi+(x0*x0)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [12.1357092861044, 29.214205611514426, '1.78000000000000']
    [27.36452797660028, 28.767880375411565, '0.04*x0**2 + 1.78']
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [12.1357092861044, 29.214205611514426, '1.78000000000000']
    [27.36452797660028, 28.767880375411565, '0.04*x0**2 + 1.78']
    [44.619738251519436, 28.75697271359565, -0.270320892333984]
    [44.620081767607, 28.75693944878952, -0.270385265350342]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [12.1357092861044, 29.214205611514426, '1.78000000000000']
    [12.584962500721156, 28.563725251344263, 'log(x0**2 + 7)']
    [22.53445297804259, 28.460572241792615, 'log(0.888888888888889*x0**2 + 7)']
    [35.60876171948284, 28.441523309583, 'log(0.888888888888889*x0**2 + 6.89)']
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 29.274727392929375, 'pi/2']
    [12.1357092861044, 29.214205611514426, '1.78000000000000']
    [12.584962500721156, 28.563725251344263, 'log(x0**2 + 7)']
    [22.53445297804259, 28.460572241792615, 'log(0.888888888888889*x0**2 + 7)']
    [35.60876171948284, 28.441523309583, 'log(0.888888888888889*x0**2 + 6.89)']
    [46.070972708611805, 28.114455148352643, 0.739170650917556]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [3.0, 29.304496932666545, '1.50000000000000']
    [4.0, 28.26178092441696, 'exp(-23.140666108580+exp(pi))']
    [42.736802128832295, 28.259201258812894, 'exp(0.000000392728*(sin((pi-(cos(x0)-1))))**(-1))']
    [46.070972708611805, 28.114455148352643, 0.739170650917556]
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [3.0, 29.304496932666545, '1.50000000000000']
    [4.0, 28.26178092441696, 'exp(-23.140666108580+exp(pi))']
    [23.550746785383243, 27.481599263478095, 'asin(-0.02*x0**2 + 0.7)']
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [3.0, 29.304496932666545, '1.50000000000000']
    [4.0, 28.26178092441696, 'exp(-23.140666108580+exp(pi))']
    [23.550746785383243, 27.481599263478095, 'asin(-0.02*x0**2 + 0.7)']
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [3.0, 29.304496932666545, '1.50000000000000']
    [4.0, 28.26178092441696, 'exp(-23.140666108580+exp(pi))']
    [23.550746785383243, 27.481599263478095, 'asin(-0.02*x0**2 + 0.7)']
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [3.0, 29.304496932666545, '1.50000000000000']
    [4.0, 28.26178092441696, 'exp(-23.140666108580+exp(pi))']
    [23.550746785383243, 27.481599263478095, 'asin(-0.02*x0**2 + 0.7)']
    [46.5605178945111, 27.13368508267342, 1.03779721260071]
    [46.560609037047406, 27.133341532987984, 1.03786277770996]
    [46.56082212240015, 27.132627863336616, 1.03801608085632]
    [159.48362903293216, 26.68961200174967, tan(1.36156690120697*cos(exp(exp(x0 - 1.45150196552277*exp(x0))))**0.627788364887238)]
    Checking for symmetry
     example1.txt_train-translated_minus-translated_minus-translated_multiply
    Just one variable!
    example1.txt_train-translated_minus-translated_minus-translated_multiply just one variable for ADD

    example1.txt_train-translated_minus-translated_minus-translated_multiply just one variable for ADD

    example1.txt_train-translated_minus-translated_minus-translated_multiply just one variable for ADD

    example1.txt_train-translated_minus-translated_minus-translated_multiply just one variable for ADD

    example1.txt_train-translated_minus-translated_minus-translated_multiply just one variable for ADD
    example1.txt_train-translated_minus-translated_minus-translated_multiply just one variable for ADD
    CPU times: user 31min 53s, sys: 1min 6s, total: 33min
    Wall time: 1h 11min

    array([['30.834454019627426', '4.946471395876568', '593576.5675051882',
            '0.0', '30.834454019627426', '0'],
           ['29.661717905473818', '4.890530251072885', '586863.6301287463',
            '1.0', '29.661717905473818', '1'],
           ['29.304496932666545', '4.873050165836775', '584766.019900413',
            '3.0', '29.304496932666545', '1.50000000000000'],
           ['29.66164889019033', '4.820780475275042', '578493.657033005',
            '4.0', '28.26178092441696', 'exp(-23.140666108580+exp(pi))'],
           ['0.0', '-inf', '-inf', '13.169925001442312', '0.0',
            '((x0-x1)**2 + (x2-x3)**2)**0.5']], dtype='<U32')

## Download the dataset from the main website
https://www.dropbox.com/s/7kgfr00qpokgz8w/Feynman_with_units.tar.gz?dl=0
https://www.dropbox.com/s/9i05v6yw1kbkup3/Feynman_without_units.tar.gz?dl=0

The link below is no persistant you need to go to the main dropbox download link
and inspect the page under network tab pick the `file?_download_id=xxxxxxxx` and copy it as a
cURL command and paste down below.

```python
!cd /content && curl 'https://uc4b304c377d76cb47fbccc918e2.dl.dropboxusercontent.com/cd/0/get/A860-WwfdpJE63yyVv70rwlAAmIJB8K8vnHiq-jv6a45vXzyK9a-6Yqb5zKfPHI50Znd3yw1rwwnGvoCMl2pLaOQm4N9gML1KP83d2OcgANC-g/file?_download_id=31784720549261183848105032197111167178761710119256631792641873289&_notify_domain=www.dropbox.com&dl=1' \
  -H 'authority: uc4b304c377d76cb47fbccc918e2.dl.dropboxusercontent.com' \
  -H 'upgrade-insecure-requests: 1' \
  -H 'dnt: 1' \
  -H 'user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36' \
  -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \
  -H 'sec-fetch-site: cross-site' \
  -H 'sec-fetch-mode: navigate' \
  -H 'sec-fetch-dest: iframe' \
  -H 'referer: https://www.dropbox.com/' \
  -H 'accept-language: en-US,en;q=0.9,ar;q=0.8,ru;q=0.7' \
  --compressed > with_units.gz
```

      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 1661M  100 1661M    0     0  17.0M      0  0:01:37  0:01:37 --:--:-- 17.6M

```python
!cd /content && tar -xzf with_units.gz && cd /content/AI-Feynman/Code
```

## Solver configurations

```python
_CFG = {
  "dataset_path"      : "/content/Feynman_with_units",
  "operations_file"   : "./14ops.txt",
  "polynomial_degree" : 3,
  "number_of_epochs"  : 500,
  "bruteforce_time"   : 20,
  "test_percentage"   : 0,
}
```

```python
import logging
import argparse
import pathlib
import os

from threading import active_count
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool
from random import shuffle
from tabulate import tabulate
from pathlib import Path
from functools import partial

from S_run_aifeynman import run_aifeynman

_CFG = {
  "dataset_path"      : "../../Feynman_without_units/",
  "operations_file"   : "./14ops.txt",
  "polynomial_degree" : 3,
  "number_of_epochs"  : 500,
  "bruteforce_time"   : 60,
  "test_percentage"   : 0,
}

class RunAll:
    """
    Run the solver on the whole dataset
    """

    def __init__(self, *,  cfg=_CFG):
        logging.basicConfig(filename="output_no_units_parallel.log", level=logging.DEBUG)
        self.cfg = cfg
        self.results = {}

    def print_results(self):
        table = []
        for file, sol in self.results.items():
            table.append(sol[-1])
        print(tabulate(
                table,
                headers=[
                    "Average error",
                    "Cumulative error",
                    "Error",
                    "Symbolic expression",
                ],
            )
        )

    def run_solver(self, dirs=None):
        if not dirs:
            path = Path(self.cfg["dataset_path"])
            dirs = list(path.iterdir())
            shuffle(dirs) # Shuffle to sample a different file each time

        else:
            path=Path(self.cfg["dataset_path"])
            child = dirs

        print(f"Process PID: {os.getpid()} ---------------- Number of threads: {active_count()}" )
        self.results[str(child).split("/")[-1]] = run_aifeynman(
            pathdir=str(path.resolve()) + "/",
            filename=str(child).split("/")[-1],
            BF_try_time=int(self.cfg["bruteforce_time"]),
            BF_ops_file_type=Path(self.cfg["operations_file"]),
            polyfit_deg=int(self.cfg["polynomial_degree"]),
            NN_epochs=int(self.cfg["number_of_epochs"]),
            vars_name=[],
            test_percentage=int(self.cfg["test_percentage"]),
        )

        logging.info(self.results)
        print("@"*120)
        print("@"*120)

        self.print_results()

```

```python
def get_files(path: str, chunks=None):
    dirs = list(Path(path).iterdir())
    dirs = [file.name for file in dirs if not (str(file).endswith("test") or str(file).endswith("train"))]
    if chunks:
      for i in range(0, len(dirs), chunks):
          yield dirs[i : i + chunks]
    yield dirs

files = list(get_files(Path("/content/Feynman_without_units")))

with open("files.txt", "w") as F:
  for line in files[-1]:
    F.write(f"{line}\n")
```

```python
%%time

solver = RunAll().run_solver
path = Path(_CFG["dataset_path"])
#dirs = list(path.iterdir())
#chunked_dirs = list(get_files(dirs, chunks=24))
# print(chunked_dirs[0], len(chunked_dirs[0]))
#    for dd in chunked_dirs:
#       pool = Pool(len(dd))
#      print(dd, len(dd))
#    pool.map(print, dd)
#     pool.map(solver, dd)
# pool.close()

solver(files[-1][-1])

```

```python
%%time
RunAll(cfg=_CFG)

```

    /content/Feynman_with_units/I.34.8
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [16.194602975157967, nan, 'acos(-x0 - x1 - x2 + 2)']
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [16.194602975157967, nan, 'acos(-x0 - x1 - x2 + 2)']
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [16.194602975157967, nan, 'acos(-x0 - x1 - x2 + 2)']
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [16.194602975157967, nan, 'acos(-x0 - x1 - x2 + 2)']
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 29.021163959047044, 'asin(666.000000000000*(x2-((x2+1)-1)))']
    [16.194602975157967, nan, 'acos(-x0 - x1 - x2 + 2)']
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 29.021163959047044, 'asin(666.000000000000*(x2-((x2+1)-1)))']
    [16.194602975157967, nan, 'acos(-x0 - x1 - x2 + 2)']
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 29.021163959047044, 'asin(666.000000000000*(x2-((x2+1)-1)))']
    [16.194602975157967, nan, 'acos(-x0 - x1 - x2 + 2)']
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 29.021163959047044, 'asin(666.000000000000*(x2-((x2+1)-1)))']
    [16.194602975157967, nan, 'acos(-x0 - x1 - x2 + 2)']
    [17.509775004326936, 0.0, '1.000000000000*(x2*(x1*(x0/x3)))']
    Checking for symmetry
     I.34.8_train
    Training a NN on the data...

    tensor(0.0918, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0656, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0516, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0221, device='cuda:0', grad_fn=<DivBackward0>)
    NN loss:  tensor(0.0038, device='cuda:0', grad_fn=<DivBackward0>)

    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [1.0, 32.555376461840865, '1']
    [4.0, 32.33086112527217, 'pi/2']
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [1.0, 32.555376461840865, '1']
    [4.0, 32.33086112527217, 'pi/2']
    [12.60964047443681, 9.234604872781642e-07, '0.000000000000+(x1*(x0/x2))']
    Checking for symmetry
     I.34.8_train-translated_multiply
    Found pretrained NN

    tensor(0.0416, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0176, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0303, device='cuda:0', grad_fn=<DivBackward0>)
    NN loss after training:  tensor(0.0040, device='cuda:0', grad_fn=<DivBackward0>)

    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [4.0, 32.33086112527217, 'pi/2']
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 32.919359912499495, '0']
    [4.0, 32.33086112527217, 'pi/2']
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 32.919359912499495, '0']
    [4.0, 32.33086112527217, 'pi/2']
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 32.919359912499495, '0']
    [1.0, 32.555376461840865, '1']
    [4.0, 32.33086112527217, 'pi/2']
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 32.919359912499495, '0']
    [1.0, 32.555376461840865, '1']
    [4.0, 32.33086112527217, 'pi/2']
    [5.754887502163468, 9.234604872781642e-07, '0.000000000000+(x0/x1)']
    Checking for symmetry
     I.34.8_train-translated_multiply-translated_multiply
    Found pretrained NN

    tensor(0.0311, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0333, device='cuda:0', grad_fn=<DivBackward0>)
    tensor(0.0225, device='cuda:0', grad_fn=<DivBackward0>)
    NN loss after training:  tensor(0.0062, device='cuda:0', grad_fn=<DivBackward0>)

    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for brute force +

    Checking for brute force *

    Checking polyfit

    Complexity  RMSE  Expression
    [0.0, 9.234604872781642e-07, '0.000000000000+x0']
    Checking for symmetry
     I.34.8_train-translated_multiply-translated_multiply-translated_divide
    Just one variable!
    I.34.8_train-translated_multiply-translated_multiply-translated_divide just one variable for ADD

    I.34.8_train-translated_multiply-translated_multiply-translated_divide just one variable for ADD

    I.34.8_train-translated_multiply-translated_multiply-translated_divide just one variable for ADD

    I.34.8_train-translated_multiply-translated_multiply-translated_divide just one variable for ADD

    I.34.8_train-translated_multiply-translated_multiply-translated_divide just one variable for ADD
    I.34.8_train-translated_multiply-translated_multiply-translated_divide just one variable for ADD
    ########################################################################################################################
    {'I.34.8': array([['0.0', '-20.046446431241375', '-20046446.431241374', '0.0',
            '9.234604872781642e-07', '0.000000000000+((x0*(x1*x2))/x3)'],
           ['nan', 'nan', 'nan', '16.194602975157967', 'nan',
            'acos(-x0 - x1 - x2 + 2)'],
           ['0.0', '-inf', '-inf', '16.509775004326936', '0.0',
            'x0*x1*x2/x3']], dtype='<U32')}
                Average error    Cumulative error    Error  Symbolic expression
    --  ----  ---------------  ------------------  -------  ---------------------
     0  -inf             -inf             16.5098        0  x0*x1*x2/x3
    CPU times: user 3h 57min 29s, sys: 23min 49s, total: 4h 21min 19s
    Wall time: 4h 35min 21s

    <__main__.RunAll at 0x7f1bc8accb38>

## Problem: **I.34.8**
Took 4 hours and 35 minute to come up with the correct result:
$$
\omega = \dfrac{x_0 x_1 x_2}{x_3}
$$
And the correct answer is:
$$
\omega = \dfrac{qvB}{p}
$$

## Problem: **III.15.14**
Took more than 5 hours to come up with this result:
$$
m = -\tan{(\dfrac{1}{ \times x_0^{-0.93}\times x_1^{-1.03}\times x_2^{-0.469}} - 1.01)}
$$
While the actual answer is:
$$
m = \dfrac{h^2}{2Ed^2}
$$

Output sample

 Complexity  RMSE  Expression
[24.236446955124386, 32.19379398225521, 'x0*x1 + x0*x2 + x1*x2 - x1 - x2**2 + 1']
[48.33584961180911, 31.9862227670943, '0.001136817047*exp((x1+x0))']
[48.444908703757726, 31.457560514093935, '-0.957879029931+x1']
[48.6933025167606, 31.016339707140748, '0.168570230758*exp(x1)']
[51.261202734823684, 29.67151999967164, '0.999530090276*(x1*x0)']
[62.98013903114244, 29.63651158757859, '0.055232500314+((x0+log(x2))*(x1-1))']
[106.30525426555863, 29.531475422563073, x0*(x1 + log(0.408610771597111*x2)) + 0.525839149951935]
[108.02150104349855, 29.461005247973745, (x0 + log(x2))*(x1 - 0.719529628753662) - 0.0555874854326248]
[153.74798012440982, 29.440090352742136, '0.1*x0*x1*x2 + x0*x1 - 0.285714285714286*x0*x2**2 + 0.142857142857143*x0*x2*x3 + 0.833333333333333*x0*x2 - 0.428571428571429*x0*x3 - 0.4*x0 - 0.125*x1**2*x2 + 0.25*x1**2 - 0.3*x1*x2**2 + 0.25*x1*x2*x3 + x1*x2 - 0.5*x1*x3 - 0.666666666666667*x1 + 0.333333333333333*x2**3 - x2**2 - 0.111111111111111*x2*x3**2 + 0.285714285714286*x2*x3 - 0.428571428571429*x2 + 0.2*x3**2 - 0.2*x3 + 0.784697875310949']
[162.58246431046206, 29.325725950623077, x1*(x0 + 0.556240618228912)*sin(x2**0.482438892126083) - 1.94434630870819]
[200.02103605333068, 28.648861022890436, '0.1*x0*x1*x2 + 0.850311055415562*x0*x1 - 0.285714285714286*x0*x2**2 + 0.142857142857143*x0*x2*x3 + 0.833333333333333*x0*x2 - 0.428571428571429*x0*x3 - 0.4*x0 - 0.125*x1**2*x2 + 0.25*x1**2 - 0.3*x1*x2**2 + 0.25*x1*x2*x3 + x1*x2 - 0.5*x1*x3 - 0.666666666666667*x1 + 0.333333333333333*x2**3 - x2**2 - 0.111111111111111*x2*x3**2 + 0.285714285714286*x2*x3 - 0.428571428571429*x2 + 0.2*x3**2 - 0.2*x3 + 0.784697875310949']
[240.46710529464815, 28.54127970345586, '0.1*x0*x1*x2 + 0.850311055415562*x0*x1 - 0.285714285714286*x0*x2**2 + 0.142857142857143*x0*x2*x3 + 0.833333333333333*x0*x2 - 0.419409322578989*x0*x3 - 0.4*x0 - 0.125*x1**2*x2 + 0.25*x1**2 - 0.3*x1*x2**2 + 0.25*x1*x2*x3 + x1*x2 - 0.5*x1*x3 - 0.666666666666667*x1 + 0.333333333333333*x2**3 - x2**2 - 0.111111111111111*x2*x3**2 + 0.285714285714286*x2*x3 - 0.428571428571429*x2 + 0.2*x3**2 - 0.2*x3 + 0.784697875310949']
[451.0046845634026, 28.311589315571727, '0.1*x0*x1*x2 + 0.850311055415562*x0*x1 - 0.285714285714286*x0*x2**2 + 0.142857142857143*x0*x2*x3 + 0.827047248703045*x0*x2 - 0.419409322578989*x0*x3 - 0.4*x0 - 0.125*x1**2*x2 + 0.25*x1**2 - 0.3*x1*x2**2 + 0.25*x1*x2*x3 + x1*x2 - 0.453915765321264*x1*x3 - 0.666666666666667*x1 + 0.333333333333333*x2**3 - 0.896533056720137*x2**2 - 0.111111111111111*x2*x3**2 + 0.275863468660905*x2*x3 - 0.435642558638502*x2 + 0.2*x3**2 - 0.2*x3 + 0.784697875310949']
[765.2021193259455, 27.68961332841078, '0.0954709145222299*x0*x1*x2 + 0.850311055415562*x0*x1 - 0.281598845270346*x0*x2**2 + 0.142857142857143*x0*x2*x3 + 0.827047248703045*x0*x2 - 0.419409322578989*x0*x3 - 0.393857016024628*x0 - 0.125*x1**2*x2 + 0.25*x1**2 - 0.295615544580811*x1*x2**2 + 0.238779807136057*x1*x2*x3 + 1.08861622104865*x1*x2 - 0.453915765321264*x1*x3 - 0.650985290052454*x1 + 0.333333333333333*x2**3 - 0.0841340395633869*x2**2*x3 - 0.896533056720137*x2**2 - 0.111111111111111*x2*x3**2 + 0.275863468660905*x2*x3 - 0.435642558638502*x2 + 0.2*x3**2 - 0.2*x3 + 0.784697875310949']
[804.4179933090178, 27.670902454575725, '0.0954709145222299*x0*x1*x2 + 0.850311055415562*x0*x1 - 0.281598845270346*x0*x2**2 + 0.142857142857143*x0*x2*x3 + 0.827047248703045*x0*x2 - 0.419409322578989*x0*x3 - 0.393857016024628*x0 - 0.125*x1**2*x2 + 0.25*x1**2 - 0.295615544580811*x1*x2**2 + 0.238779807136057*x1*x2*x3 + 1.08861622104865*x1*x2 - 0.453915765321264*x1*x3 - 0.650985290052454*x1 + 0.333333333333333*x2**3 - 0.0841340395633869*x2**2*x3 - 0.896533056720137*x2**2 - 0.114928272861219*x2*x3**2 + 0.275863468660905*x2*x3 - 0.435642558638502*x2 + 0.2*x3**2 - 0.2*x3 + 0.784697875310949']
[1049.3949821424571, 27.65482709345228, '0.0954709145222299*x0*x1*x2 + 0.850311055415562*x0*x1 - 0.281598845270346*x0*x2**2 + 0.143093568988091*x0*x2*x3 + 0.827047248703045*x0*x2 - 0.419409322578989*x0*x3 - 0.393857016024628*x0 - 0.124525299070793*x1**2*x2 + 0.255889644781202*x1**2 - 0.295615544580811*x1*x2**2 + 0.238779807136057*x1*x2*x3 + 1.08861622104865*x1*x2 - 0.453915765321264*x1*x3 - 0.650985290052454*x1 + 0.332150095352896*x2**3 - 0.0841340395633869*x2**2*x3 - 0.896533056720137*x2**2 - 0.114928272861219*x2*x3**2 + 0.275863468660905*x2*x3 - 0.435642558638502*x2 + 0.19934446687829*x3**2 - 0.198171936948463*x3 + 0.784697875310949']
[1287.6255549331968, 27.57826998133378, '0.0324957167678879*x0*x1**2 + 0.0954709145222299*x0*x1*x2 - 0.0518367881947689*x0*x1*x3 + 0.850311055415562*x0*x1 - 0.281598845270346*x0*x2**2 + 0.142857142857143*x0*x2*x3 + 0.827047248703045*x0*x2 + 0.0195647972984031*x0*x3**2 - 0.419409322578989*x0*x3 - 0.393857016024628*x0 - 0.0325007929091572*x1**3 - 0.124525299070793*x1**2*x2 + 0.0649419539246933*x1**2*x3 + 0.255889644781202*x1**2 - 0.295615544580811*x1*x2**2 + 0.238779807136057*x1*x2*x3 + 1.08861622104865*x1*x2 - 0.0388670663126931*x1*x3**2 - 0.453915765321264*x1*x3 - 0.650985290052454*x1 + 0.332150095352896*x2**3 - 0.0841340395633869*x2**2*x3 - 0.896533056720137*x2**2 - 0.114928272861219*x2*x3**2 + 0.275863468660905*x2*x3 - 0.435642558638502*x2 + 0.00642744864450299*x3**3 + 0.19934446687829*x3**2 - 0.198171936948463*x3 + 0.784697875310949']
[1327.5202240795804, 27.57798240828162, '0.0324957167678879*x0*x1**2 + 0.0954709145222299*x0*x1*x2 - 0.0518367881947689*x0*x1*x3 + 0.850311055415562*x0*x1 - 0.281598845270346*x0*x2**2 + 0.143093568988091*x0*x2*x3 + 0.827047248703045*x0*x2 + 0.0195647972984031*x0*x3**2 - 0.419409322578989*x0*x3 - 0.393857016024628*x0 - 0.0325007929091572*x1**3 - 0.124525299070793*x1**2*x2 + 0.0649419539246933*x1**2*x3 + 0.255889644781202*x1**2 - 0.295615544580811*x1*x2**2 + 0.238779807136057*x1*x2*x3 + 1.08861622104865*x1*x2 - 0.0388670663126931*x1*x3**2 - 0.453915765321264*x1*x3 - 0.650985290052454*x1 + 0.332150095352896*x2**3 - 0.0841340395633869*x2**2*x3 - 0.896533056720137*x2**2 - 0.114928272861219*x2*x3**2 + 0.275863468660905*x2*x3 - 0.435642558638502*x2 + 0.00642744864450299*x3**3 + 0.19934446687829*x3**2 - 0.198171936948463*x3 + 0.784697875310949']
Checking for brute force +

# Run on all files of the dataset

```python
%%time
!parallel --bar --ungroup --joblog ../../log.txt -t -j2 -a files.txt python generate_claimed_results.py --file
```

    Academic tradition requires you to cite works you base your article on.
    When using programs that use GNU Parallel to process data for publication
    please cite:

      O. Tange (2011): GNU Parallel - The Command-Line Power Tool,
      ;login: The USENIX Magazine, February 2011:42-47.

    This helps funding further development; AND IT WON'T COST YOU A CENT.
    If you pay 10000 EUR you should feel free to use GNU Parallel without citing.

    To silence this citation notice: run 'parallel --citation'.

    python generate_claimed_results.py --file II.13.23
    python generate_claimed_results.py --file II.27.16
    0% 0:100=0s II.27.16                                                            Process PID: 8847 ---------------- Number of threads: 1
    Process PID: 8848 ---------------- Number of threads: 1
    0% 0:100=0s II.27.16                                                            Checking for brute force +

    Trying to solve mysteries with brute force...
    Trying to solve /content/Feynman_without_units/II.27.16_train...
    /bin/cp -p /content/Feynman_without_units/II.27.16_train mystery.dat
    Number of variables.....       0
    Functions used..........        +*-/><~\RPSCLE
     Arity            0 : P
     Arity            1 : ><~\RSCLE
     Arity            2 : +*-/
    Loading mystery data....
    0% 0:100=0s II.27.16                                                                 1000000  rows read from file mystery.dat
    Number of examples...... 1000000
     Mystery data has largest magnitude    1.0000000000000000       at j=           1
     Searching for best fit...
          0.000000000000     -2.141592741013                      P               1             0.0000             0.0000             0.0000             0.0000
     All done: results in results.dat
    Checking for brute force *

    Trying to solve mysteries with brute force...
    Trying to solve /content/Feynman_without_units/II.27.16_train...
    /bin/cp -p /content/Feynman_without_units/II.27.16_train mystery.dat
    Number of variables.....       0
    Functions used..........        +*-/><~\RPSCLE
     Arity            0 : P
     Arity            1 : ><~\RSCLE
     Arity            2 : +*-/
    Loading mystery data....
    0% 0:100=0s II.27.16                                                                 1000000  rows read from file mystery.dat
    Number of examples...... 1000000
     Mystery data has largest magnitude    1.0000000000000000       at j=           1
     Searching for best fit...
          0.000000000000      0.318309877326                      P               1             0.0000             0.0000             0.0000             0.0000
     All done: results in results.dat
    Checking polyfit

    0% 0:100=0s II.27.16                                                            Complexity  RMSE  Expression
    0% 0:100=0s II.27.16

# Results

```python
import pprint
import re
results = None
with open("/content/AI-Feynman/output_no_units_parallel.log") as F:
  results = F.readlines()
```

```python
new = str(results).replace('"', "").strip().replace("\n", "").replace("'", "")\
.replace(" ", "").replace("\\n", " ")\
.replace("','", "").replace("asin", "sin").split("INFO:root:")

new = [re.sub(r"(dtype=\WU\d*|dtype=object)", "", item) for item in new]
```

```python
new = [re.sub(r"(I+.\d*.\d*:array)", "", item.replace(" ,", "").replace("{", "")\
             .replace("}", ""))\
             .split(",") for item in new if len(item) > 10]
             #re.sub(r"(I+.\d*.\d*:array)", "", item.replace(" ,", "").replace("{", "")\
            #  .replace("}", "").replace("(", "").replace(")", ""))\
            #  .split(",")
```

```python
import sympy
import matplotlib.pyplot as plt
from sympy import init_printing
from sympy import pprint

init_printing(use_latex=True)

```

```python
results = []
for item in new:
  res = []
  for ex in item:
    if len(ex) > 3:
      tmp.append(ex)
      result.append(ex.replace("]", ""))
  results.append(result[-1])
  pprint(sympy.sympify(result[-1]))
  print("\n", "@" * 60, "\n")
```

    4⋅π⋅x₀

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    x₀ + 1

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    -0.125
    ───────
        2
      x₀

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

     1
     ──
     x₀
    ℯ   - 1

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

                                        0.5
    ⎛  2                               ⎞
    ⎝x₀  - 0.1591549430918953⋅x₀ + 0.01⎠

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

     0.5
    ──────
    x₀ + 1

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    sin(0.785437643527985⋅sin(0.1013211780033⋅cos(x₀)))

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    6.283185307179586⋅x₀
    ────────────────────
             x₁

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

                   0.5
    ⎛  2     2    ⎞
    ⎝x₀  + x₁  + 1⎠

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    1.0⋅x₁
    ──────
      x₀

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    0.168816319869⋅x₂⋅(x₀ + x₁)

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    -4⋅π⋅(cos(x₁ - x₂) - 1)
    ────────────────────────
                     2
         x₀⋅(x₁ - x₂)

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    x₀⋅(x₁⋅cos(x₂) + 1)

     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

```python

```


Realismo local y realismo no local

 Desigualdades de Bell

Para ejemplificar esto, asumamos que se generan parejas de fotones que están máximamente entrelazados en el cristal del centro con frecuencias $\nu_A$ y $\nu_B$ en direcciones opuestas. Éstos, serán detectados por un par de fotodectores frente a los polarizadores mostrados en la figura, los cuales puede discernir entre estados ortogonales. Los analizadores sólo dejan pasar fotones que se alinean con el eje de polarización mostrado en la figura a cada detector.

El estado que se produce en el cristal se puede describir en la base de polarización como sigue
$$
|\Phi_+^{AB}\rangle =\frac{1}{\sqrt{2}} \left(|x,x\rangle +    |y,y\rangle    \right).
$$

El proceso de detección se puede describir con los operadores
$$
E^A (\alpha) = |x^A\rangle \langle x^A| - |y^A \rangle \langle y^A|,\\
E^B (\beta) = |x^B\rangle \langle x^B| - |y^B \rangle \langle y^B|.
$$

$P_{+-}$ es la probabilidad que la polarización $x^A$ se observe en $A$ y $y^B$ en $B$, que corresponde con haber obtenido +1 y -1 y un producto -1.

Para cualquier ángulo de los polarizadores mostrado en la figura, es posible escribir las polarizaciones rotadas en la siguiente forma:
$$
|x^A\rangle = cos\alpha |x \rangle + \sin \alpha |y\rangle, \quad
|y^A\rangle = -sin \alpha |x \rangle + \cos \alpha |y\rangle.
$$

Con lo anterior se pueden obtener las diferentes probabilidades $P_{ij}$, $ij = {=,-}$, por ejemplo $P_{++}= \langle \Phi_+^{AB} |x^A,x^B \rangle \langle x^A,x^B| \Phi_+^{AB}= \frac{1}{2}\cos^2(\beta-\alpha)$.

Ejercicio: calcule las probabilidades restantes.
Asimismo, calcule el coeficiente de correlación $\epsilon ^{AB}(\alpha,\beta):=\langle \Phi_+^{AB}|E^A(\alpha)\otimes E^B(\beta) | \Phi_+{AB}\langle$

Deberá obtener los resultados siguientes:

$$
P_{--}=P_{++}\\
P_{+-} = P_{-+} = \frac{1}{2}\sin^2 (\beta-\alpha)
$$

$$
\epsilon ^{AB}(\alpha,\beta)=P_{++}+P_{--}-P_{+-}-P_{-+}=\cos 2(\beta-\alpha)
$$

```python

```

 Variables ocultas

Un conjunto de variables ocultas se sumarizan en $\lambda$.

* $\lambda \in \Re$.
* Las propiedades de un objeto se pueden describir por cierto conjunto de valores de $\lambda$.
* Se producen partículas con un conjunto de valores $\lambda$ por alguna fuente con una densidad de probabilidad dada por $\rho (\lambda)$, se cumple
    * $\begin{equation}\int \rho (\lambda) d\lambda =1,\tag{1}\end{equation}$
    * $\rho (\lambda)$ es positiva y semidefinida.

Objeto clásico: Un objeto clásico en $A$, caracterizado por $\lambda$ y con un ángulo de rotación $\delta_1$ del analizador en $A$ tiene predeterminado cual polarización será observada ($x^A$ o $y^A$). Por lo tanto existe una función no ambigua $S_A^\lambda (\delta_1)$ con valores +1 o -1.
$$
 S_A^\lambda (\delta_1) = \left \{ \begin{matrix} +1
\\ -1  \end{matrix}\right\},   S_B^\lambda (\delta_2) = \left \{ \begin{matrix} +1
\\ -1  \end{matrix}\right\}.
$$

    Con la correlación clásica
    $$\begin{equation} \epsilon^{cl}(\delta_1,\delta_2) = \int \rho (\lambda) S_A^\lambda (\delta_1) S_B^\lambda (\delta_2) d\lambda.
    \label{eq2}
    \tag{2}
    \end{equation}
    $$

Esto corresponde con una teoría para variables ocultas $\lambda$.

 Desigualdades de Bell

En el caso de analizadores con orientación paralela deberá cumplirse la correlación completa

   $$ \epsilon^{cl}(\delta_1,\delta_2) = \int \rho (\lambda) S_A^\lambda (\delta_1) S_B^\lambda (\delta_2) d\lambda =1
    $$

utilizando (1) y (2), es posible notar que $S_A^\lambda (\delta) = S_B^\lambda (\delta)$

### CASO GENERAL
Se realizarán mediciones utilizando tres orientaciones $\delta_1, \delta_2, \delta_3$. En el orden siguiente $(\delta_1, \delta_2), (\delta_2, \delta_3), (\delta_1, \delta_3)$.

Esto es porque $$ -S^\lambda (\delta_1)S^\lambda (\delta_3) = -S^\lambda (\delta_1)S^\lambda (\delta_2)S^\lambda (\delta_2)S^\lambda (\delta_3)$$.

Ahora agregamos un término nulo al lado izquierdo dado por $S^\lambda (\delta_1)S^\lambda (\delta_2)-S^\lambda (\delta_1)S^\lambda (\delta_2)$

 con lo que se pueden arreglar de la sigueinte manera
$$  S^\lambda (\delta_1)S^\lambda (\delta_2) - S^\lambda (\delta_2)S^\lambda (\delta_3) = S^\lambda (\delta_1)S^\lambda (\delta_2) [1-S^\lambda (\delta_2)S^\lambda (\delta_3)]$$

La integración de la expresión anterior conduce a

$$ \begin{align}
& \left|\int d\lambda \rho (\lambda) [S^\lambda(\delta_1)S^\lambda(\delta_2) - S^\lambda(\delta_1)S^\lambda(\delta_3)]\right| \\
= &\left| \int \rho(\lambda) d\lambda S^\lambda (\delta_1)S^\lambda (\delta_2) [1-S^\lambda (\delta_2)S^\lambda (\delta_3)]   \right|\\
\leq & 1 - \int d\lambda \rho(\lambda) S^\lambda (\delta_2)S^\lambda (\delta_3)]
\end{align}
$$

 Tras lo anterior, podemos escribir la relación para la correlación clásica simplemente como
    $$ \left| \epsilon^{cl} (\delta_1,\delta_2) - \epsilon^{cl} (\delta_2,\delta_3) \right| \leq 1- \epsilon^{cl} (\delta_2,\delta_3) $$

		La cual es la expresión que aparece en el artículo de Bell de 1964
J.S. Bell, On the Einstein-Podolsky-Rosen paradox, Physics 1, 195-200 (1964)

 Desigualdad de Clauser, Horne, Shimony and Holt (CHSH)

Aquí se requieren 2 orientaciones de los analizadores para $A$ y para $B$.

Se medirán $\alpha_1$ y $\alpha_2$ en $A$ y $\beta_1$ y $\beta_2$ en $B$.

Recordar que $S^\lambda_{A,B} = \pm 1$. Con esto se construye la siguiente expresión

$$S_A^\lambda (\alpha_2) [ S_B^\lambda (\beta_1) +S_B^\lambda (\beta_2)]+S_A^\lambda (\alpha_1) [ S_B^\lambda (\beta_1) -S_B^\lambda (\beta_2)]:=\{ \cdots \}
$$

Al expresarla en términos de la variable oculta $\lambda$

$$\left|\int \rho (\lambda) d\lambda \{ \cdots \} \right| \leq 2 \int \rho (\lambda) d\lambda =2 $$

Con esto escribimos la expresión en términos de los coeficientes de correlación
    $$
    S^{cl} = \left| \epsilon^{cl} (\alpha_2,\beta_1) + \epsilon^{cl} (\alpha_2,\beta_2) \epsilon^{cl} (\alpha_1,\beta_1) -\epsilon^{cl} (\alpha_1,\beta_2)      \right| \leq 2
    $$
    Clauser, J.F., Horne, M.A., Shimonu, A., and Holt, R.A., Proposed experimento to test local hidden-variable theories, Phys. Rev. Lett., 23, 880-884 (1969).

Ejemplo de implementación de las desigualdades de Bell con strawberry fields.

Se basan en el estado
$$ | \psi \rangle = \frac{1}{\sqrt{2}} \left( |2\rangle |0\rangle + |0\rangle |2\rangle\right)$$

### Descripción del método híbrido

Pueden medir ya sea N fotones o la cuadratura X, y los resultados análogos a $S^\lambda(\delta)$ se explican como sigue: Alice y Bob pueden obtener los resultados $a,b = \{+1,-1\}$ bajo las siguientes condiciones:
(Se dan para Alice, pero son equivalentes para Bob)
$$
N:  \left \{ \begin{matrix} a = +1, & N>0
\\ a = -1, & N=0  \end{matrix} \right. \quad X:  \left \{ \begin{matrix} a = +1, & x \in \mathcal{A}^+, \mathcal{A}^+\in \Re, \mathcal{A}^+ =[-z,z]
\\ a = -1, & x \in \mathcal{A}^- = \Re \text{\ } \mathcal{A}^+  \end{matrix} \right.
$$

Se utiliza la desigualdad CHSH
    $S= E_{XX}+ E_{XN} +E_{NX} - E_{NN} \leq 2$,
    en donde $E_{jk} = P(a=b|jk) - P(a\neq b | jk)$

Si Alice y Bob seleccionan medir en N, entonces $E_{NN} = -1$, esto se puede resumir en $P(a,b|NN) = (1-ab)/4$.

¿Cómo hacer esta simulación en strawberry fields?

https://peterwittek.com/verifying-cv-bell-correlations.html

```python
import numpy as np
import strawberryfields as sf
from numpy import pi as π
from strawberryfields.ops import Fock, BSgate, MeasureFock, MeasureX
from tqdm import tqdm
np.set_printoptions(suppress=True, precision=3)

def prepare_and_measure(Alice, Bob, q):
    Fock(1) | q[0]
    Fock(1) | q[1]
    BSgate(π/4, π) | (q[0], q[1])
    Alice   | q[0]
    Bob     | q[1]

def postprocess(in_, out, z):
    if in_ == 0:
        if out > 0:
            return 1
        else:
            return 0
    else:
        if out < -z or out > z:
            return 0
        else:
            return 1

def preprocess(in_):
    if in_ == 0:
        return MeasureFock()
    else:
        return MeasureX

```

```python
def do_experiment(x, y, z=40.83):
    Alice = preprocess(x)
    Bob = preprocess(y)
    eng, q = sf.Engine(2)
    with eng:
        prepare_and_measure(Alice, Bob, q)
    eng.run('fock', cutoff_dim=3)
    a = postprocess(x, q[0].val, z)
    b = postprocess(y, q[1].val, z)
    return a, b

n_rounds = 400
N = np.zeros((2, 2, 2, 2))
for _ in tqdm(range(n_rounds)):
    x = np.random.randint(2)
    y = np.random.randint(2)
    a, b = do_experiment(x, y)
    N[a, b, x, y] += 1
def calculate_expectation(N, x, y):
    n = sum(N[a, b, x, y] for a in range(2) for b in range(2))
    return (sum(N[a, b, x, y] for a, b in zip(range(2), range(2))) -
            sum(N[a, b, x, y] for a, b in zip(range(2), range(1, -1,-1))))/n

E_NN = calculate_expectation(N, 0, 0)
E_XN = calculate_expectation(N, 1, 0)
E_NX = calculate_expectation(N, 0, 1)
E_XX = calculate_expectation(N, 1, 1)
print(E_XX + E_XN + E_NX - E_NN)
```

    100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:13<00:00, 30.11it/s]

    2.3338345864661654

## Ejercicio

* Discute la posibilidad de utilizar las desigualdades de Bell para el mismo problema
* Realiza una adaptación del método de Cavalcanti para estados entrelazados en polarización e impleméntala con el simulador. ¿Qué puedes concluir de tus resultados?

```python

```


# Preprocess ICRP-107 to create dataset for radioactivedecay
### Introduction
This notebook creates a decay dataset for `radioactivedecay` from the data in ICRP 107: Nuclear Decay Data for Dosimetric Calculations.

The data is saved into the following files:
- `decay_data.npz`: NumPy arrays containing the strings of the radionuclides in the decay dataset, the half-lives and their time units, the progeny, branching fractions and decay modes of each radionuclide, and the days to year conversion number (NPZ NumPy compressed array format);
- `c_scipy.npz`: pre-calculated SciPy CSR sparse matrix *C* (Amaku et al. (2010)) (NPZ NumPy compressed array format);
- `c_inv_scipy.npz`: pre-calculated SciPy CSR sparse matrix *C-1* (inverse of *C*) (NPZ NumPy compressed array format);
- `c_sympy.pickle`: pre-calculated SymPy sparse matrix *C* for arbitrary-precision calculations (Python pickle format);
- `c_inv_sympy.pickle`: pre-calculated SymPy sparse matrix *C-1* for arbitrary-precision calculations (inverse of *C*) (Python pickle format);
- `decay_consts_sympy.pickle`: SymPy matrix or radionuclide decay constants (s-1) for arbitrary-precision calculations (inverse of *C*) (Python pickle format).
- `year_conversion_sympy.pickle`: SymPy representation of the days to year conversion number (Python pickle format).

### Initial set up and read in ICRP-107 data into a DataFrame
First load the necessary Python modules.

```python
import io, pickle, re, shutil, zipfile
import fortranformat as ff
import numpy as np
import pandas as pd
import requests
from scipy import sparse
from sympy import Integer, S, N, Float, log, Matrix
from sympy.matrices import SparseMatrix
```

Now we need to download and read in the data from the ICRP-07.NDX data file provided as a supplement to ICRP-107. First read a prepared CSV file listing all elements, their symbols and atomic numbers.

```python
elements = pd.read_csv("element_list.csv", index_col="Symbol")[["Element","Z"]]
elements.head()
```

      Element
      Z

      Symbol

      H
      Hydrogen
      1

      He
      Helium
      2

      Li
      Lithium
      3

      Be
      Beryllium
      4

      B
      Boron
      5

Define functions to
* convert half-life in units of μs, ms, m, h, d, y into seconds;
* create a human-readable string of the half-life;
* return atomic number and mass number from a radionuclide string.

```python
year = 365.2422 # number of days in year used for conversion in ICRP-107
                # (see JAERI 1347 & JAEA-Data/Code 2007-021)
num_nuclides = 1252

def convert_half_life(halflife, unit):
    units = {"μs":1.0E-6, "ms":1.0E-3, "s":1.0, "m":60.0, "h":60.0*60.0,
             "d":60.0*60.0*24.0, "y":60.0*60.0*24.0*year}
    return float(halflife)*units[unit]

def readable_half_life(halflife, unit):
    # very hacky code to format some of the half lives in ICRP-107 into more readable time units
    if unit == "s":
        if halflife[-3:] == "E-7":
            halflife = "0." + halflife[:-3].replace(".", "")
            unit = "μs"
        elif halflife[-3:] == "E-6":
            halflife = halflife[:-3]
            unit = "μs"
        elif halflife[-3:] == "E-5":
            if len(halflife[:-3]) == 3:
                halflife = halflife[:-3].replace(".", "")
            else:
                halflife = halflife[:-3].replace(".", "")[:2] + '.' + halflife[:-3].replace(".", "")[2:]
            unit = "μs"
        elif halflife[-3:] == "E-4":
            halflife = "0." + halflife[:-3].replace(".", "")
            unit = "ms"
        elif halflife[-3:] == "E-3":
            halflife = halflife[:-3]
            unit = "ms"
        elif halflife[-3:] == "E-2":
            if len(halflife[:-3]) == 3:
                halflife = halflife[:-3].replace(".", "")
            else:
                halflife = halflife[:-3].replace(".", "")[:2] + '.' + halflife[:-3].replace(".", "")[2:]
            unit = "ms"

    elif unit == "y":
        if halflife[-3:-1] == "E1":
            halflife = halflife[:-2] + "+" + halflife[-2:]

        if halflife[-3:] == "E+3":
            halflife = halflife[:-3]
            unit = "ky"
        elif halflife[-3:] == "E+4":
            if len(halflife[:-3]) == 3:
                halflife = halflife[:-3].replace(".", "")
            else:
                halflife = halflife[:-3].replace(".", "")[:2] + '.' + halflife[:-3].replace(".", "")[2:]
            unit = "ky"
        elif halflife[-3:] == "E+5":
            halflife = "0." + halflife[:-3].replace(".", "")
            unit = "My"
        elif halflife[-3:] == "E+6":
            halflife = halflife[:-3]
            unit = "My"
        elif halflife[-3:] == "E+7":
            if len(halflife[:-3]) == 3:
                halflife = halflife[:-3].replace(".", "")
            else:
                halflife = halflife[:-3].replace(".", "")[:2] + '.' + halflife[:-3].replace(".", "")[2:]
            unit = "My"
        elif halflife[-3:] == "E+8":
            halflife = "0." + halflife[:-3].replace(".", "")
            unit = "By"
        elif halflife[-3:] == "E+9":
            halflife = halflife[:-3]
            unit = "By"
        elif halflife[-4:] == "E+10":
            if len(halflife[:-4]) == 3:
                halflife = halflife[:-4].replace(".", "")
            else:
                halflife = halflife[:-4].replace(".", "")[:2] + '.' + halflife[:-4].replace(".", "")[2:]
            unit = "By"
        elif halflife[-4:] == "E+11":
            halflife = "0." + halflife[:-4].replace(".", "")
            unit = "Ty"
        elif halflife[-4:] == "E+12":
            halflife = halflife[:-4]
            unit = "Ty"
        elif halflife[-4:] == "E+13":
            if len(halflife[:-4]) == 3:
                halflife = halflife[:-4].replace(".", "")
            else:
                halflife = halflife[:-4].replace(".", "")[:2] + '.' + halflife[:-4].replace(".", "")[2:]
            unit = "Ty"
        elif halflife[-4:] == "E+14":
            halflife = "0." + halflife[:-4].replace(".", "")
            unit = "Py"
        elif halflife[-4:] == "E+15":
            halflife = halflife[:-4]
            unit = "Py"
        elif halflife[-4:] == "E+16":
            if len(halflife[:-4]) == 3:
                halflife = halflife[:-4].replace(".", "")
            else:
                halflife = halflife[:-4].replace(".", "")[:2] + '.' + halflife[:-4].replace(".", "")[2:]
            unit = "Py"
        elif halflife[-4:] == "E+17":
            halflife = halflife[:-4].replace(".", "")
            unit = "Py"

    return halflife + " " + unit

def get_Z_A(radionuclide):
    [Z, A] = radionuclide.split("-")
    Z = elements.loc[Z, "Z"]
    if A[-1].isalpha():
        A = A[:-1]
    return Z, int(A)
```

Prepare a pandas DataFrame for the ICRP-107 decay data.

```python
icrp_col_names = ["Radionuclide", "Element", "Z", "A", "Metastable_state",
                  "Half_life", "Half_life_units", "Half_life_s",
                  "Half_life_readable","Num_decay_modes",
                  "Mode_1", "Fraction_1", "Progeny_1",
                  "Mode_2", "Fraction_2", "Progeny_2",
                  "Mode_3", "Fraction_3", "Progeny_3",
                  "Mode_4", "Fraction_4", "Progeny_4"]
icrp = pd.DataFrame(columns=icrp_col_names)
```

Download ICRP-107 Supplemental Material and read data from ICRP-07.NDX file line by line into the DataFrame.

```python
url = "https://journals.sagepub.com/doi/suppl/10.1177/ANIB_38_3/suppl_file/P107JAICRP_38_3_Nuclear_Decay_Data_suppl_data.zip"
r = requests.get(url)
z = zipfile.ZipFile(io.BytesIO(r.content))
z.extractall()

file_NDX = open("P 107 JAICRP 38(3) Nuclear Decay Data for Dosimetric Calculations(supplementary data)/ICRP-07.NDX", "r")
file_NDX.readline()

# fortran format of data in the ICRP-107 Index File (Table 1 footnote, ICRP107)
ffline = ff.FortranRecordReader("(a7,a8,a2,a8,3i7,i6,1x,3(a7,i6,e11.0,1x),a7,i6,e11.0,f7.0,2f8.0,3i4,i5,i4,e11.0,e10.0,e9.0)")
rows = []
for i in range(0, num_nuclides):
    line = ffline.read(file_NDX.readline())
    line = [i.strip() if isinstance(i,str) else i for i in line]
    add = {"Radionuclide": line[0]}
    add["Element"] = add["Radionuclide"].split("-")[0]
    add["Z"], add["A"] = get_Z_A(add["Radionuclide"])
    if add["Radionuclide"][-1].isalpha():
        add["Metastable_state"] = add["Radionuclide"][-1]
    add["Half_life"] = line[1]
    unit = line[2]
    if unit == "us":
        unit = "μs"
    add["Half_life_units"] = unit
    add["Half_life_s"] = convert_half_life(line[1], unit)
    add["Half_life_readable"] = readable_half_life(line[1], unit)

    # parse decay modes and progeny
    modes = re.findall(r"(A|B\-|ECB\+|EC|IT|SF)",line[3])
    j=0
    while j < 4 and line[8+j*3] != "":
        add["Fraction_" + str(j+1)] = str(line[8+2+j*3])
        add["Progeny_" + str(j+1)] = line[8+j*3]
        if add["Progeny_" + str(j+1)] == "SF":
            add["Mode_" + str(j+1)] = "SF"
        else:
            Z, A = get_Z_A(add["Progeny_" + str(j+1)])
            if add["Z"] == Z and add["A"] == A: add["Mode_" + str(j+1)] = "IT"
            elif add["Z"] - 2 == Z and add["A"] - 4 == A: add["Mode_" + str(j+1)] = "α"
            elif add["Z"] + 1 == Z and add["A"] == A: add["Mode_" + str(j+1)] = "β-"
            elif add["Z"] - 1 == Z and add["A"] == A:
                if "EC" in modes: add["Mode_" + str(j+1)] = "EC"
                else: add["Mode_" + str(j+1)] = "β+ & EC"
        j += 1
    add["Num_decay_modes"] = j

    rows.append(add)
icrp = icrp.append(rows, ignore_index=True)
file_NDX.close()

shutil.rmtree("P 107 JAICRP 38(3) Nuclear Decay Data for Dosimetric Calculations(supplementary data)")
```

Remove NaN values, set DataFrame index to the radionuclide string, and check completed DataFrame. Export completed DataFrame to CSV file for analysis elsewhere.

```python
icrp = icrp.replace(np.nan, "", regex=True)
icrp.set_index("Radionuclide", inplace=True)
icrp.to_csv("icrp.csv", index=True)
icrp.head()
```

      Element
      Z
      A
      Metastable_state
      Half_life
      Half_life_units
      Half_life_s
      Half_life_readable
      Num_decay_modes
      Mode_1
      ...
      Progeny_1
      Mode_2
      Fraction_2
      Progeny_2
      Mode_3
      Fraction_3
      Progeny_3
      Mode_4
      Fraction_4
      Progeny_4

      Radionuclide

      Ac-223
      Ac
      89
      223

      2.10
      m
      1.260000e+02
      2.10 m
      1
      α
      ...
      Fr-219

      Ac-224
      Ac
      89
      224

      2.78
      h
      1.000800e+04
      2.78 h
      2
      EC
      ...
      Ra-224
      α
      0.091
      Fr-220

      Ac-225
      Ac
      89
      225

      10.0
      d
      8.640000e+05
      10.0 d
      1
      α
      ...
      Fr-221

      Ac-226
      Ac
      89
      226

      29.37
      h
      1.057320e+05
      29.37 h
      3
      β-
      ...
      Th-226
      EC
      0.17
      Ra-226
      α
      6e-05
      Fr-222

      Ac-227
      Ac
      89
      227

      21.772
      y
      6.870574e+08
      21.772 y
      2
      β-
      ...
      Th-227
      α
      0.0138
      Fr-223

5 rows × 21 columns

### Order ICRP DataFrame so progeny always come below their parent
The radionuclides need to be ordered so that the progeny (daughters) are always lower in the DataFrame than their parent. This is so the subsequent matrices that we create are lower triangular.

To achieve this we first count how many times each radioactive decay process occurs in the ICRP-107 dataset.

```python
print("β+ or electron capture:", icrp.stack().value_counts()["β+ & EC"]
      + icrp.stack().value_counts()["EC"])
print("β-:", icrp.stack().value_counts()["β-"])
print("α:", icrp.stack().value_counts()["α"])
print("Isomeric Transition (IT):", icrp.stack().value_counts()["IT"])
print("Spontaneous Fission (SF):", (icrp.stack().value_counts()["SF"]/2).astype(np.int64))
```

    β+ or electron capture: 684
    β-: 539
    α: 183
    Isomeric Transition (IT): 178
    Spontaneous Fission (SF): 28

The outcomes of these decay processes are as follows:
- β+ or electron capture (EC): $\mathrm{^{A}_{Z}X} \rightarrow \mathrm{^{A}_{Z-1}Y}$
- β- decay: $\mathrm{^{A}_{Z}X} \rightarrow \mathrm{^{A}_{Z+1}Y}$
- α decay: $\mathrm{^{A}_{Z}X} \rightarrow \mathrm{^{A-4}_{Z-2}Y}$
- IT decay: $\mathrm{^{Am}_{Z}X} \rightarrow \mathrm{^{A}_{Z}X}$ or $\mathrm{^{An}_{Z}X} \rightarrow \mathrm{^{A}_{Z}X}$
- SF decay: The ICRP-107 dataset does not contain data for the outcomes (progeny) from spontaneous fission decays

We order by decreasing mass number (A), followed by decreasing atomic number (Z) (as there are more Beta+ and EC decays than Beta- decays), then by decreasing isomer index (n, m, ground state).

```python
icrp.sort_values(by=["A", "Z", "Metastable_state"], inplace=True, ascending=[False, False, False])
icrp.head()
```

      Element
      Z
      A
      Metastable_state
      Half_life
      Half_life_units
      Half_life_s
      Half_life_readable
      Num_decay_modes
      Mode_1
      ...
      Progeny_1
      Mode_2
      Fraction_2
      Progeny_2
      Mode_3
      Fraction_3
      Progeny_3
      Mode_4
      Fraction_4
      Progeny_4

      Radionuclide

      Fm-257
      Fm
      100
      257

      100.5
      d
      8683200.0
      100.5 d
      2
      α
      ...
      Cf-253
      SF
      0.0021
      SF

      Fm-256
      Fm
      100
      256

      157.6
      m
      9456.0
      157.6 m
      2
      α
      ...
      Cf-252
      SF
      0.919
      SF

      Es-256
      Es
      99
      256

      25.4
      m
      1524.0
      25.4 m
      1
      β-
      ...
      Fm-256

      Fm-255
      Fm
      100
      255

      20.07
      h
      72252.0
      20.07 h
      2
      α
      ...
      Cf-251
      SF
      2.3e-07
      SF

      Es-255
      Es
      99
      255

      39.8
      d
      3438720.0
      39.8 d
      3
      β-
      ...
      Fm-255
      α
      0.08
      Bk-251
      SF
      4.5e-05
      SF

5 rows × 21 columns

Now it is necessary to correct the positions of the remaining radionuclides that are still incorrectly ordered. This is achieved by looping over all the radionuclides in the table, and checking if their progeny are located lower in the table or not. If not, the parent and progeny row positions are switched. This takes a few passes until all progeny are correctly located below their parents.

```python
nuclide_list = list(icrp.index)
swapping = 1
while swapping >= 1:
    swaps = 0
    for parent in nuclide_list:
        for i in range(0, icrp.at[parent, "Num_decay_modes"]):
            if (icrp.at[parent, "Mode_" + str(i+1)] in ["stable", "SF"]): continue
            progeny = icrp.at[parent, "Progeny_" + str(i+1)]
            if (progeny not in nuclide_list): continue
            j = nuclide_list.index(parent)
            k = nuclide_list.index(progeny)
            if  j > k:
                nuclide_list[j], nuclide_list[k] = nuclide_list[k], nuclide_list[j]
                icrp = icrp.reindex(index=nuclide_list)
                swaps +=1
    print("Iteration", swapping, "number of swaps:", swaps)
    swapping += 1
    if swaps == 0: swapping = 0
```

    Iteration 1 number of swaps: 265
    Iteration 2 number of swaps: 81
    Iteration 3 number of swaps: 22
    Iteration 4 number of swaps: 4
    Iteration 5 number of swaps: 0

The sorted DataFrame looks like this. Note this is just one of many possible solutions for sorting the DataFrame.

```python
icrp.head()
```

      Element
      Z
      A
      Metastable_state
      Half_life
      Half_life_units
      Half_life_s
      Half_life_readable
      Num_decay_modes
      Mode_1
      ...
      Progeny_1
      Mode_2
      Fraction_2
      Progeny_2
      Mode_3
      Fraction_3
      Progeny_3
      Mode_4
      Fraction_4
      Progeny_4

      Radionuclide

      Fm-257
      Fm
      100
      257

      100.5
      d
      8683200.0
      100.5 d
      2
      α
      ...
      Cf-253
      SF
      0.0021
      SF

      Es-256
      Es
      99
      256

      25.4
      m
      1524.0
      25.4 m
      1
      β-
      ...
      Fm-256

      Fm-256
      Fm
      100
      256

      157.6
      m
      9456.0
      157.6 m
      2
      α
      ...
      Cf-252
      SF
      0.919
      SF

      Cf-255
      Cf
      98
      255

      85
      m
      5100.0
      85 m
      1
      β-
      ...
      Es-255

      Es-255
      Es
      99
      255

      39.8
      d
      3438720.0
      39.8 d
      3
      β-
      ...
      Fm-255
      α
      0.08
      Bk-251
      SF
      4.5e-05
      SF

5 rows × 21 columns

### Make the *Λ* matrix
Now we make the sparse lower triangular matrix *Λ*, which captures the decay pathways and branching relations between the radionuclides. _Λ_ is set up based on Eq. (6) in Amaku et al. (2010). The diagonal elements are all *-λjj*, i.e. negative decay constant for each radionuclide. The off-diagonal elements are all of the form *BFij×λjj* for *i* > *j*, where *BFij* is the branching fraction from parent *j* to progeny *i*. The non-zero elements beneath the *jj*th element in each column are first progeny of radionuclide *j*.

```python
rows = np.array([], dtype=np.int)
cols = np.array([], dtype=np.int)
data = np.array([], dtype=np.float)
ln2 = np.log(2)

for parent in nuclide_list:
    j = nuclide_list.index(parent)
    rows = np.append(rows, [j])
    cols = np.append(cols, [j])
    lambd = ln2/icrp.at[parent, "Half_life_s"]
    data = np.append(data, -lambd)
    for d in range(0, icrp.at[parent, "Num_decay_modes"]):
        if (icrp.at[parent, "Mode_" + str(d+1)] in ["stable", "SF"]): continue
        progeny = icrp.at[parent, "Progeny_" + str(d+1)]
        if (progeny not in nuclide_list): continue
        i = nuclide_list.index(progeny)
        rows = np.append(rows, [i])
        cols = np.append(cols, [j])
        data = np.append(data, [lambd*float(icrp.at[parent, "Fraction_" + str(d+1)])])

lambda_mat = sparse.csc_matrix((data, (rows, cols)))
```

### Calculate the matrices *C* and *C-1*
We now need to make the sparse matrices *C* and *C-1*, which are given by Eqs. (10) and (13) in Amaku et al. (2010), respectively. The diagonal elements of both matrices are 1. *C* and *C-1* differ from *Λ* in that there are non-zero elements beneath the *jj*th element in each column for all progeny of *j*, i.e. everything in its full decay chain, not just the immediate daughters.

Therefore we have to find all the progeny in the decay chain of each radionuclide. We do this by looping backwards over each column in *Λ* to build up lists of the radionuclides in the decay chain of each parent. We then set up the basic structure (i.e. define the non-zero elements) of sparse matrices *C* and *C-1*.

```python
rows_dict = {}
for i in range(num_nuclides-1, -1, -1):
    a,_ = lambda_mat[:,i].nonzero()
    b = a
    for j in a:
        if j > i:
            b = np.unique(np.concatenate((b,rows_dict[j])))
    rows_dict[i] = b

rows_c = np.array([], dtype=np.int)
cols_c = np.array([], dtype=np.int)
for i in range(0, num_nuclides):
    rows_c = np.concatenate((rows_c,rows_dict[i]))
    cols_c = np.concatenate((cols_c,np.array([i]*len(rows_dict[i]))))

c = sparse.csc_matrix((np.array([0.0]*rows_c.size, dtype=np.float64), (rows_c, cols_c)))
c_inv = sparse.csc_matrix((np.array([0.0]*rows_c.size, dtype=np.float64), (rows_c, cols_c)))
```

Now calculate *C* and *C-1*. Note that only the non-zero elements of *Ckj* and *C-1kj*  need to be considered for the sums in Eqs. (10) and (13) of Amaku et al. (2010).

Calculate *C*, and highlight any cases where the relative difference of the decay constants of two radionuclides in the same decay chain is less than 0.001 (as this could lead to numerical precision issues):

```python
for index in range(0, rows_c.size):
    i = rows_c[index]
    j = cols_c[index]
    if i == j: c[i,i] = 1.0
    else:
        sigma = 0.0
        for k in rows_dict[j]:
            if k == i: break
            sigma += lambda_mat[i,k]*c[k,j]
        c[i,j] = sigma/(lambda_mat[j,j]-lambda_mat[i,i])

        if abs((lambda_mat[j,j]-lambda_mat[i,i])/lambda_mat[j,j]) < 1E-3: print(nuclide_list[i], nuclide_list[j])
```

There are no cases where radionuclides in the same decay chain have decay constants that are too similar (for the radionuclides in ICRP-107). Now proceed to calculate *C-1*:

```python
for index in range(0, rows_c.size):
    i = rows_c[index]
    j = cols_c[index]
    if i == j: c_inv[i,i] = 1.0
    else:
        sigma = 0.0
        for k in rows_dict[j]:
            if k == i: break
            sigma -= c[i,k]*c_inv[k,j]
        c_inv[i,j] = sigma
```

### Calculate SymPy versions of the matrices for arbitrary-precision calculations
We now calculate SymPy versions of *C* and *C-1* for arbitrary-precision calculations. First define some functions for processing the data into SymPy objects:

```python
year_sympy = S(3652422)/10000

def to_rational(number):
    """
    Converts string representation of a number to a SymPy object.
    """

    if 'e' in number or 'E' in number:
        if 'e' in number:
            end = number.split('e')[1]
            number = number.split('e')[0]
        else:
            end = number.split('E')[1]
            number = number.split('E')[0]
        parts = number.split('.')
        if len(parts) == 1: parts.append('')
        if end[0] == '+':
            multiply = 1
            factor = S(10**int(end.lstrip('+')))
        else:
            multiply = 0
            factor = S(10**int(end.lstrip('-')))
        denom = S(10**len(parts[1]))
        parts[0] = parts[0].lstrip('0')
        if len(parts[0]) == 0: parts[1] = parts[1].lstrip('0')
        if multiply == 1:
            return S(parts[0]+parts[1])*factor/denom
        else: return S(parts[0]+parts[1])/(denom*factor)
    parts = number.split('.')
    if len(parts) == 1: parts.append('')
    denom = S(10**len(parts[1]))
    parts[0] = parts[0].lstrip('0')
    if len(parts[0]) == 0: parts[1] = parts[1].lstrip('0')
    return S(parts[0]+parts[1])/denom

def convert_half_life_sympy(halflife, unit):
    """
    Conversion of SymPy half-life into seconds.
    """

    units = {'μs':S(1)/1000000,
             'ms':S(1)/1000,
             's':S(1),
             'm':S(60),
             'h':S(3600),
             'd':S(86400),
             'y':S(86400)*year_sympy
            }
    return halflife*units[unit]
```

Now make a SymPy version of the *Λ* matrix:

```python
lambda_mat_sympy = SparseMatrix.zeros(num_nuclides, num_nuclides)
lambdas_sympy = Matrix.zeros(num_nuclides, 1)

for parent in nuclide_list:
    j = nuclide_list.index(parent)
    hl_sympy = convert_half_life_sympy(to_rational(icrp.at[parent, 'Half_life']),
                                       icrp.at[parent, 'Half_life_units'])
    lambd = log(2)/hl_sympy
    lambda_mat_sympy[j, j] = -lambd
    lambdas_sympy[j] = lambd
    for d in range(0, icrp.at[parent, 'Num_decay_modes']):
        if (icrp.at[parent, 'Mode_'+str(d+1)] in ['stable', 'SF']): continue
        progeny = icrp.at[parent, 'Progeny_'+str(d+1)]
        if (progeny not in nuclide_list): continue
        i = nuclide_list.index(progeny)
        lambda_mat_sympy[i, j] = lambd*to_rational(icrp.at[parent, 'Fraction_'+str(d+1)])
```

Now make a SymPy version of the *C* and *C-1* matrix:

```python
c_sympy = SparseMatrix.zeros(num_nuclides, num_nuclides)
c_inv_sympy = SparseMatrix.zeros(num_nuclides, num_nuclides)

for index in range(0, rows_c.size):
    i = rows_c[index]
    j = cols_c[index]
    if i == j: c_sympy[i,i] = Integer(1)
    else:
        sigma = Integer(0)
        for k in rows_dict[j]:
            if k == i: break
            sigma += lambda_mat_sympy[i,k]*c_sympy[k,j]
        c_sympy[i,j] = sigma/(lambda_mat_sympy[j,j]-lambda_mat_sympy[i,i])

for index in range(0, rows_c.size):
    i = rows_c[index]
    j = cols_c[index]
    if i == j: c_inv_sympy[i,i] = Integer(1)
    else:
        sigma = Integer(0)
        for k in rows_dict[j]:
            if k == i: break
            sigma -= c_sympy[i,k]*c_inv_sympy[k,j]
        c_inv_sympy[i,j] = sigma
```

### Save the outputs
Write out file containing NumPy arrays with the radionuclide names, the half-lives, their time units, human-readable half-life strings, the progeny, branching fractions and decay modes of each radionuclide, and the days to year conversion number. Write output files containing *C* and *C-1* in the SciPy and SymPy sparse formats. Write out the SymPy versions of the decay constants.

```python
hldata = np.array([(np.float64(a),b,c) for a, b, c in zip(icrp["Half_life"], icrp["Half_life_units"], icrp["Half_life_readable"])], dtype=object)

prog_bfs_modes = np.array([{}]*len(nuclide_list))
for i in range(0, len(nuclide_list)):
    bfs = {}
    modes = {}
    for d in range(0, icrp.at[nuclide_list[i], "Num_decay_modes"]):
        progeny = icrp.at[nuclide_list[i], "Progeny_" + str(d+1)]
        bfs[progeny] = float(icrp.at[nuclide_list[i], "Fraction_" + str(d+1)])
        modes[progeny] = icrp.at[nuclide_list[i], "Mode_" + str(d+1)]
    bfs = {key: value for key, value in sorted(bfs.items(), key=lambda x: x[1], reverse=True)}

    prog_bfs_modes[i] = {progeny: [bf, modes[progeny]] for progeny, bf in bfs.items()}

np.savez_compressed("./decay_data.npz", radionuclides=np.array(nuclide_list),
                    hldata=hldata, prog_bfs_modes=prog_bfs_modes,
                    year_conv=year)

# Write out SciPy sparse matrices (convert to CSR format)
sparse.save_npz("./c_scipy.npz", c.tocsr())
sparse.save_npz("./c_inv_scipy.npz", c_inv.tocsr())

# Write out SymPy objects to pickle files
with open("c_sympy.pickle", "wb") as outfile:
    outfile.write(pickle.dumps(c_sympy))
with open("c_inv_sympy.pickle", "wb") as outfile:
    outfile.write(pickle.dumps(c_inv_sympy))
with open("decay_consts_sympy.pickle", "wb") as outfile:
    outfile.write(pickle.dumps(lambdas_sympy))
with open("year_conversion_sympy.pickle", "wb") as outfile:
    outfile.write(pickle.dumps(year_sympy))
```