Giter Site home page Giter Site logo

ramanujanmachine's Introduction

MasseyRamanujan

The Ramanujan Machine is an algorithmic approach to discover new mathematical conjectures. For the time being, the project is focused in number theory, specifically on finding formulas relating fundamental constants like pi, e, and the Riemann zeta function values to various continued fractions.

For more information, please go to RamanujanMachine.com.

Installation

Clone the repo and install the package. If you have pip, it can be done by running

pip install -e .

under the same folder as setup.py. That's it, you are now ready to discover new conjectures.

The MITM_RF algorithm:

The MITM algorithm will "mine" new Continued Fraction conjectures of the type: LHS_RHS This project lets you control the equation space scanned by the algorithm.

Running the code

To start a new execution, you'll need to configure three parts:

  1. What LHS do you wish to scan
  2. What structure does an and bn take, and what range do you wish to scan for each coefficient
  3. How to decide if there was a match (precission wise)

you can see examples under scripts/ folder

Left Hand Side Hash Table (LHSHashTable)

This is a data structure that holds expressions made from the required constant. To create a LHS object, you'll need to choose a constant, and a range for all coefficients in the expression. The values generated are saved to a file to reduce execution time.

For example, the following code will generate all Mobius transforms of e, with coefficients between -5 and 5. The generated domain is saved to e_lhs_dept5

 from ramanujan.LHSHashTable import LHSHashTable
 from ramanujan.constants import g_const_dict

 saved_hash = 'e_lhs_dept5'
 lhs_coefs_range = 5
 lhs = LHSHashTable(
    saved_hash,
    lhs_coefs_range,
    [g_const_dict['e']])

an and bn Structures (any class under poly_domains)

An objects that generates pairs of an and bn series.

The simplest structure you can choose will be Xn = c0 * n^k + c1 * n^(k-1) + ... + ck for both an and bn (with the matching degree for each), when coefficient is independent of the rest.

This type of domain can be defined as follows:

 from ramanujan.poly_domains.CartesianProductPolyDomain import CartesianProductPolyDomain
 
 poly_search_domain = CartesianProductPolyDomain(
   2, [-5, 5], # an coefs
   2, [-5, 5]) # bn coefs

In this example, we've chosen both an and bn to be of degree 2, and the coefficients are integers that range from -5 to 5. All combination of coefficients under those restriction will be generated.

To create more intricate structures, you may create a class that extents CartesianProductPolyDomain or AbstractPolyDomains. You can take a look at ExampleDomain or Zeta3Domain1 as an example that expand this logic.

The Enumerator (any class under enumerators)

Last but not least, you'll need to choose an algorithm that compares the two.

The simplest, and fastest approach is implemented under EfficentGCFEnumerator. It follows a two-step process:

  1. For any pair an and bn calculate the GCF to a dept of 30. Compare each result to values in LHSHashTable, using low precision and store matches.
  2. The matches are re-evaluated to a dept of 1000, and compared again for higher precision, thus eliminating false positives. The final results are then presented as new conjectures.

For farther information regarding this algorithm, please refer to our paper 'the Ramanujan machine' under the 'MITM-RF algorithm' chapter, or visit our website RamanujanMachine.com.

For example, creating EfficientGCFEnumerator using the LHSHashTable and poly_domain defined above:

from ramanujan.enumerators.EfficientGCFEnumerator import EfficientGCFEnumerator

enumerator = EfficientGCFEnumerator(
    lhs,
    poly_search_domain,
    [g_const_dict['e']]
    )

And thats it! start your execution by running:

results = enumerator.full_execution()

and print your results by running:

enumerator.print_results(results)

Cool examples

Examples for conjectures can be found under scripts/paper_results. Just run every script there and start finding conjectures!

Tweaking the search parameters

Now that you've seen how to run the basic code, you can tweak the search parameters and find new conjectures of your own.

If you wish to change the searched series, you can create a new class that extends CartesianProductPolyDomain, and defines your new polynomial families. Please see poly_domains\ExampleDomain for a detailed example.

ramanujanmachine's People

Contributors

fix27 avatar leonardo-coder avatar rotelimelech avatar ruddek avatar shahargottlieb avatar yoavharris avatar yoharris avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ramanujanmachine's Issues

custom LHS constant

Background -

In MITM-RF we build a hash table for LHS permutations in advance. later we search for hits in this LHS hash table when enumerating over RHS permutations.
currently the LHS is built using linear rational functions of a given constant.
for example, is API arguments:
lhs_constant = 'pi'
lhs_limit = 2

then the values in the LHS hash table will be all irational values of:
image

so that:
image

currently the LHS constant is excepted as a string, and the possibilities for this argument are in g_const_dict in main.py.

Task

We would like to be able to use various lhs constants, from string arguments.

  • implement a parser from API string argument to sympy exspression
  • allow usage of sympy defined functions, and make sure the sympy expression obtained doesn't include any symbols (or else we can't evaluate it)
  • write proper documentation and examples of expressions that can be used.
  • add unit-test for this feature

examples:

when if we could have lhs_constant = 'E**2' (or 'exp(2)')
we could obtain the following result:
image

when inserting lhs_constant = 'exp(pi)'
we could obtain:
image

https://docs.sympy.org/latest/modules/parsing.html may be useful for this issue

Accelerating continued fraction calculation using tail approximations

The goal

This issue requires adding code to RelativeGCFEnumerator to take into account the tail of the continued fraction, which will provide a better approximation for finite $n$ and thus increase the convergence rate

Details

Currently, we calculate the continued fraction at a finite $n$ by truncating the calculation on $a_n$ and $b_n$. This method assumes that the tail of the continued fraction $t_n$ is zero:

$$PCF_n = a_0 + \cfrac{b_1}{ a_1 + \cfrac{ b_1 }{\ddots + \cfrac{b_n}{a_n + t_{n+1}}} }$$

Generally, the tail is the effect of the elements $n+1$ to $\infty$ on the continued fraction's value. In a case of balanced degrees (when the degree of $b_n$ is twice the degree of $b_n$) we can approximate $t_n$ in $O(1)$ giving us a much better approximation for the true value of the continued fraction with little effort!

For large enough $n$, we can approximate the sequences $a_n$ and $b_n$ using only the term with the largest degree of $n$ in them:
$$a_n \approx \alpha n^d ; b_n \approx \beta n^{2d}$$
then, we can write the tail the following way:

$$t_n \approx \frac{\beta n^{2d}}{ \alpha n^d + \frac{\beta (n+1)^{2d}}{ \alpha (n+1)^d + \frac{\beta (n+2)^{2d}}{ \alpha (n+2)^{2d} + \ddots} } } = \alpha n^d \left( \frac{\beta n^{2d} / (\alpha n^d)}{ \alpha n^d + \frac{\beta (n+1)^{2d}}{ \alpha (n+1)^d + \frac{\beta (n+2)^{2d}}{ \alpha (n+2)^{2d} + \ddots} } } \right) = \alpha n^d \left( \frac{\beta n^{2d} / (\alpha^2 n^{2d})}{ 1 + \frac{\beta (n+1)^{2d}/(\alpha n^d)}{ \alpha (n+1)^d + \frac{\beta (n+2)^{2d}}{ \alpha (n+2)^{2d} + \ddots} } } \right) = \alpha n^d \left( \frac{\beta n^{2d} / (\alpha^2 n^{2d})}{ 1 + \frac{\beta (n+1)^{2d}/(\alpha^2 (n+1)^d n^d)}{ 1 + \frac{\beta (n+2)^{2d}/\alpha (n+1)^d }{ \alpha (n+2)^{2d} + \ddots} } } \right)$$

Finally we attain:
$$\Rightarrow t_n \approx \alpha n^d \left( \frac{\beta / \alpha^2}{ 1 + \frac{\beta/ \alpha^2}{ 1 + \frac{\beta/ \alpha^2 }{ 1 + \ddots} } } \right) $$
We've got a continued fraction with constant $a_n$ and $b_n$!

This continued fraction can be calculated in O(1):
$$x = \frac{\beta / \alpha^2}{ 1 + \frac{\beta/ \alpha^2}{ 1 + \frac{\beta/ \alpha^2 }{ 1 + \ddots} } } = \frac{\beta / \alpha^2}{ 1 + x}$$
$$x^2 + x - \beta/\alpha^2 =0 \Rightarrow x = -\frac{1}{2} \pm \frac{1}{2} \sqrt{1+4\frac{\beta}{\alpha^2}} $$
Notice that if $\beta/\alpha^2 > 0$ then $x>0$ and we must choose the $+$ solution. If $\beta/\alpha^2<-\frac{1}{4}$ then the continued fraction doesn't converge. It can be shown that also for the case where $0>\beta/\alpha^2>-\frac{1}{4}$ we need to choose the $+$ sign.

i or number 9 theory - CONNECTION THEORY

If we count each number composed by 315, 3+1+5 we get 9. If we double it to 630, 6+3, we also get 9. If double it again, 1260, we get 9. 2520, 9. 5040, 9. And so on....

This is a connection theory. i vocal is the number 9th letter in the alphabet. It’s the connection letter, that’s why we say AI or iPhone or iPad, or IT, etc.

This may be useful to Ramanujuan Machine, to make a combination between letters and formulas. Hope so!

thanks
Lautaro
I’m from Argentina and my English it’s not the best.

Create Alternating-Series generators

Background:

In the MITM-RF algorithm (enumerate over gcf) we iterate over combinations of integers to enumerate over a GCF space.
LHS_RHS

The {a_n} series is built by the series generators in series_generators.py.
a series generator is a function that accepts 2 arguments:
coef_list - list of integers that define the output series
n - length of series to be built.

the coef list passed to the generator is a permutation of the values in poly_a argument of multi_core_enumeration_wrapper function, which is a list of lists of positive integers.
for example,
if poly_a = [[1,2,3],[2,4],[1]]
then series generator will be called 3X2X1=6 times with:
coef_list = { [1,2,1] ; [1,4,1] ; [2, 2, 1] ; [2,4,1] ; [3,2,1] ; [3,4,1] }.

for the {b_n} series the same applies, with a small change - also negative permutations are counted. meaning that the series generator will be called 12 times with the values:
{ [1,2,1] ; [1,4,1] ; [2, 2, 1] ; [2,4,1] ; [3,2,1] ; [3,4,1] ; [-1,-2,-1] ; [-1,-4,-1] ; [-2, -2, -1] ; [-2,-4,-1] ; [-3,-2,-1] ; [-3,-4,-1]}.

for more on our enumeration technique look up documentation/enumerate_over_gcf.pdf

The Task:

  • think about a way to create a series generator for alternating series (a series that consists of 2 sub-series - 1 for odd indices and another for even indices).
  • implement that series generator, have it inherit from "SeriesGeneratorClass" abstract class.
  • connect it to the API (get_custom_generator in main.py)
  • write a unit-test with that series and add it to tests/APITesting.py.

example of a result that could be found with this generator:
image

Check for Möbius equivalence

The Möbius transformation of a continued fraction is also a continued fraction. As a result, whenever the LHS in the conjecture is a Möbius transformation of the constant, operating with a Möbius transformation on both sides of the equation gives us a new conjecture of the same form.

The goal of this issue is to check equivalences of conjectures by such Möbius transformations, and thus remove redundancies.

sympy ImportError: cannot import name 'with_metaclass' from 'sympy.core.compatibility'

Which version of sympy has to be used? I am getting the following error while trying to run scripts/paper_results/e_results:

The sympy.core.compatibility submodule is deprecated.

This module was only ever intended for internal use. Some of the functions
that were in this module are available from the top-level SymPy namespace,
i.e.,

    from sympy import ordered, default_sort_key

The remaining were only intended for internal SymPy use and should not be used
by user code.

See https://docs.sympy.org/latest/explanation/active-deprecations.html#deprecated-sympy-core-compatibility
for details.

This has been deprecated since SymPy version 1.10. It
will be removed in a future version of SymPy.

  from sympy.core.compatibility import with_metaclass
Traceback (most recent call last):
  File "/Users/arnedecadt/Documents/func/e_results.py", line 1, in <module>
    from ramanujan.LHSHashTable import LHSHashTable
  File "/Users/arnedecadt/Documents/func/RamanujanMachine/ramanujan/LHSHashTable.py", line 12, in <module>
    from ramanujan.constants import g_N_initial_search_dps
  File "/Users/arnedecadt/Documents/func/RamanujanMachine/ramanujan/constants.py", line 2, in <module>
    from sympy.core.compatibility import with_metaclass
ImportError: cannot import name 'with_metaclass' from 'sympy.core.compatibility' (/Users/arnedecadt/micromamba/lib/python3.9/site-packages/sympy/core/compatibility.py)
[Finished in 1.2s with exit code 1]

Add time estimation

Have the code generates a time estimation including:

  • How long the code been running
  • How long it's roughly estimated to run (at least for the parts for which it's possible)

Faster LHS checking - lattice problems

Hi, I think you could speed up your LHS checking through lattice algorithms. This isn't a novel idea of mine, but seems applicable here. After realizing it could be applied here, I googled it and found other people talking about the same trick, e.g. https://wstein.org/books/ant/ant/node15.html

The idea is that you have some mysterious real number from your RHS gcf -- say, 2.2959862202 -- and I want to look for a rational expression (that includes other irrational quantities, of course) that equals this. Call the real number x. I'm looking for any equation of the form (say),

(p1 + p2 * e + p3 * pi) / (q1 + q2 * e + q3 * pi) = x.

Where p's and q's are the unknowns that I'm searching for. Multiply through by the denominator, and subtract the RHS from both sides:

p1 + p2 * e + p3 * pi + q1 * (-x) + q2 * (-ex) + q3 * (-pix) = 0

so that it's now a problem about finding a linear dependence over Q (or equivalently, over Z) of the numbers {1, e, pi, x, ex, pix}. The reals can be viewed as a 1D vector space, and we're looking for a "very short" vector. To turn this into a workable algorithm, you want your lattice to have at least the same dimension in space as the number of basis vectors, so you add one dimension for each quantity. Then you scale up the "error" coordinate to penalize it a lot. Here, I will multiply by some larger number M. The new vectors are:

v1=(M*1, 1,0,0,0,0,0)
v2=(M*e, 0,1,0,0,0,0)
v3=(M*pi, 0,0,1,0,0,0)
v4=(M*x, 0,0,0,1,0,0)
v5=(M*e*x, 0,0,0,0,1,0)
v6=(M*pi*x, 0,0,0,0,0,1)

This set of 6 vectors generates a subspace of R^7. Now set, say, M=10000, and you look for the shortest vector. A short vector will necessarily have a very small "error coordinate". If you use x=2.2959862202, you'll find for instance that the vector

V = 2*v1 + v2 + v3 - 3 v4 + v5 - v6

is very short! Even though all the input vectors (v1 ... v6) had length at least 10000, the vector V is just

(0.000000000001, 2, 1, 1, -3, 1, -1)

and so has a length of just 4.12. Reading off the coefficients of V, we find that x = (2+e+pi)/(3-e+pi).

Thankfully, there are standard algorithms such as LLL which enable this kind of shortest vector discovery. They're not guaranteed to find short vectors, but in a large fraction of cases they do very well. In the case where they fail to find a solution, randomly permuting the vectors and trying again several times (say, 10 times) will often help. For instance, here is Mathematica code to solve this problem:

x = 2.295986220225457575964614984963958313;
M = 1000000;
v1 = {M*1, 1, 0, 0, 0, 0, 0};
v2 = {M*E, 0, 1, 0, 0, 0, 0};
v3 = {M*Pi, 0, 0, 1, 0, 0, 0};
v4 = {M*x, 0, 0, 0, 1, 0, 0};
v5 = {M*E*x, 0, 0, 0, 0, 1, 0};
v6 = {M*Pi*x, 0, 0, 0, 0, 0, 1};

LatticeReduce[Round[{v1, v2, v3, v4, v5, v6}]][[1]]

The "Round" here is because Mathematica's LatticeReduce algorithm only accepts integers, so I use a large "M" value and then round the irrational numbers (like ME, Mx) off to their nearest integers. This spits out "{-2, -2, -1, -1, 3, -1, 1}" instantly, which gives the solution.

As noted also in that link above, this technique can be extended to finding not just rational functions of x, but also algebraic equations involving x. For instance, you're very unlikely to recognize the number 1.35048396195 on its own, but it turns out to be the solution to the quintic x^5 - x = pi. If you search using the "vectors" {1, Pi, x, x^2, x^3, x^4, x^5}, you'll quickly find this solution. There are known continued fractions to produce e.g. any rational root of a rational number, I believe there are also continued fractions for quantities like the roots of x^3 - x - 1. So I would expect this technique to be somewhat fruitful too.

I believe with high confidence that this is the same kind of algorithm that Wolfram|Alpha uses to find its "closed form approximations" to numbers, and indeed dropping 2.29598622022 it finds the rational function of E and Pi quickly, and it regularly suggests algebraic roots as well.

This would be a welcome alternative to hashmap-based LHS searching! :) Please contact me if you want to discuss this more.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.