Skip to content

Commit

Permalink
Fix pretty print issues (#29)
Browse files Browse the repository at this point in the history
It turns out that the subscripting is not working because it's supposed
to be square brackets in the input expression to make it through mathjs
parse to the MathJax pretty printer. 🤦🏻

Also fixed issue where symbol strings that automatically get replaced
for pretty print (e.g. Delta) were not being interpreted correctly when
immediately followed by a symbol, e.g. Delta(3) would stay as input
instead of converting the "Delta" portion to a Unicode character.

Added names of constants to dictionary in case we want to display names
on hover as a nice-to-have later.
  • Loading branch information
krachwal committed Feb 9, 2024
2 parents 11ac0a3 + 31178a8 commit d4b0b54
Show file tree
Hide file tree
Showing 11 changed files with 465 additions and 330 deletions.
11 changes: 9 additions & 2 deletions react-frontend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
{
"settings":{
"react": {
"version": "detect"
}
},
"env": {
"browser": true,
"es2021": true
},
"extends": ["eslint:recommended", "plugin:react/recommended"],
"rules": {
"no-unused-vars": ["warn", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }]
"no-unused-vars": ["warn", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }],
"key-spacing": ["error", { "afterColon": true }],
"@stylistic/js/indent": ["error", 4]
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["react"]
"plugins": ["react", "@stylistic/js"]
}
19 changes: 19 additions & 0 deletions react-frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions react-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
]
},
"devDependencies": {
"@stylistic/eslint-plugin-js": "^1.6.1",
"@vitejs/plugin-react": "^4.2.0",
"cypress": "^13.6.1",
"eslint": "^8.54.0",
Expand Down
20 changes: 10 additions & 10 deletions react-frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import './App.css';
import Form from './components/Form';

function App() {
return (
<div className="app-root">
<div className="header">
return (
<div className="app-root">
<div className="header">
The Ramanujan Machine
<div className="subheading">using algorithms to discover new mathematics</div>
</div>
<div className="body">
<Form></Form>
</div>
</div>
);
<div className="subheading">using algorithms to discover new mathematics</div>
</div>
<div className="body">
<Form></Form>
</div>
</div>
);
}

export default App;
176 changes: 95 additions & 81 deletions react-frontend/src/components/Charts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react';
import { MathJax, MathJaxContext } from 'better-react-mathjax';
import {parse} from 'mathjs';
import ScatterPlot from './ScatterPlot';
import constants from '../lib/constants';

interface ChartProps {
results: any;
Expand All @@ -16,101 +17,114 @@ type WolframResult = {

function Charts({ results = {}, toggleDisplay }: ChartProps) {

const [wolframResults, setWolframResults] = useState<WolframResult[]>([]);
const config = {
tex: {
inlineMath: [["$", "$"]],
displayMath: [["$$", "$$"]]
}
};
const [wolframResults, setWolframResults] = useState<WolframResult[]>([]);
const config = {
tex: {
inlineMath: [["$", "$"]],
displayMath: [["$$", "$$"]]
}
};

useEffect(() => {
verify();
}, [results]);
useEffect(() => {
verify();
}, [results]);

const computeValue = () => {
// we are replacing the exponent operator from python to js syntax
// we are also replacing the parentheses with the precision at the end of the expression returned from identify
const input = JSON.parse(results.converges_to).replaceAll('**','^').replace(' = 0','').replace(/\s\([0-9]+\)$/,'');
try {
const mathy = parse(input).toTex();
return `$$${mathy}$$`;
} catch(e) {
console.log(`failed to parse ${input}`);
return '(unparseable result)';
}
};
const computeValue = () => {
// we are replacing the exponent operator from python to js syntax
// we are also replacing the parentheses with the precision at the end of the expression returned from identify
const input = convertConstants(JSON.parse(results.converges_to)
.replaceAll('**','^')
.replace(' = 0','')
.replace(/\s\([0-9]+\)$/,'')
);

const wolframValue = (input: string) => {
// wolfram regurgitates the value provided with an approx symbol - truncating
const cleanInput = input.indexOf('≈') >= 0 ? input.substring(0, input.indexOf('≈')) : input;
try {
const mathy = parse(cleanInput).toTex();
return `$$${mathy}$$`;
} catch(e) {
console.log(`failed to parse ${cleanInput}`);
return '(unparseable result)';
}
};
try {
const mathy = parse(input).toTex();
return `$$${mathy}$$`;
} catch(e) {
console.log(`failed to parse ${input}`);
return '(unparseable result)';
}
};

const trimLimit = () => {
const decimalPosition = results.limit.indexOf('.');
return JSON.parse(results.limit).substring(0, 30 + decimalPosition + 1);
};
const convertConstants = (input: string) => {
let cleanString = input;
for(const c in constants){
if(constants[c].replacement) cleanString = cleanString.replaceAll(c, constants[c].replacement!!);
}
return cleanString;
};

const computePairs = (dataset: string) => {
return JSON.parse(results[dataset]);
};
const wolframValue = (input: string) => {
// wolfram regurgitates the value provided with an approx symbol - truncating
const cleanInput = input.indexOf('≈') >= 0 ? input.substring(0, input.indexOf('≈')) : input;
try {
const mathy = parse(cleanInput).toTex();
return `$$${mathy}$$`;
} catch(e) {
console.log(`failed to parse ${cleanInput}`);
return '(unparseable result)';
}
};

const verify = () => {
axios.post('/verify', {expression: results.limit})
.then((response) => {
if (response.status != 200) {
console.warn(response.data.error);
}
setWolframResults(response.data.wolfram_says);
})
.catch((error) => console.log(error));
}
const trimLimit = () => {
const decimalPosition = results.limit.indexOf('.');
return JSON.parse(results.limit).substring(0, 30 + decimalPosition + 1);
};

return (
<div className="chart-container">
<MathJaxContext config={config} src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
<p>This is the value of the Polynomial Continued Fraction:</p>
<p className="center-text">{trimLimit()}</p>
<p>It seems to converge to:<br/><br/> <MathJax inline dynamic>{computeValue()}</MathJax></p>
{ wolframResults && wolframResults.length > 0 ? (
<div>
<p className="center-text"><i>or</i></p>
<p><MathJax inline dynamic>{wolframValue(wolframResults[0].plaintext)}</MathJax></p>
</div>
):''}
</MathJaxContext>
<i>
<sub>
const computePairs = (dataset: string) => {
return JSON.parse(results[dataset]);
};

const verify = () => {
axios.post('/verify', {expression: results.limit})
.then((response) => {
if (response.status != 200) {
console.warn(response.data.error);
}
setWolframResults(response.data.wolfram_says);
})
.catch((error) => console.log(error));
}

return (
<div className="chart-container">
<MathJaxContext config={config} src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
<p>This is the value of the Polynomial Continued Fraction:</p>
<p className="center-text">{trimLimit()}</p>
<p>It seems to converge to:<br/><br/> <MathJax inline dynamic>{computeValue()}</MathJax></p>
{ wolframResults && wolframResults.length > 0 ? (
<div>
<p className="center-text"><i>or</i></p>
<p><MathJax inline dynamic>{wolframValue(wolframResults[0].plaintext)}</MathJax></p>
</div>
):''}
</MathJaxContext>
<i>
<sub>
Note: the limit is estimated to high confidence using a PSLQ algorithm, but this is not a
proof.
</sub>
</i>
<p>The rate of convergence for this Polynomial Continued Fraction (in digits per step): </p>
<ScatterPlot id="error_chart" data={computePairs('error_deriv')} />
<p>
</sub>
</i>
<p>The rate of convergence for this Polynomial Continued Fraction (in digits per step): </p>
<ScatterPlot id="error_chart" data={computePairs('error_deriv')} />
<p>
Delta is a measure of the irrationality of a number (read more about it{' '}
<a href="https://www.ramanujanmachine.com/the-mathematics-of-polynomial-continued-fractions/irrationality-testing/">
<a href="https://www.ramanujanmachine.com/the-mathematics-of-polynomial-continued-fractions/irrationality-testing/">
here
</a>
</a>
). The given Polynomial Continued Fraction produces the following finite-depth estimations
for Delta:
</p>
<ScatterPlot id="delta_chart" data={computePairs('delta')} />
<button
onClick={() => {
toggleDisplay();
}}>
</p>
<ScatterPlot id="delta_chart" data={computePairs('delta')} />
<button
onClick={() => {
toggleDisplay();
}}>
Modify
</button>
</div>
);
</button>
</div>
);
}

export default Charts;
Loading

0 comments on commit d4b0b54

Please sign in to comment.