Skip to main content

Find closed-form expressions for numerical values

Project description

find-closed-form

find-closed-form PyPI version Python

A Python port of the Wolfram Language resource function FindClosedForm, contributed by the same author.

find_closed_form helps solve the fundamental problem of number recognition, by searching for a possible closed-form formula for a given number y, in terms of arbitrary combinations of elementary and higher mathematical functions.

The fundamental strategy is that, given a callable f, progressively more complex rational arguments are tried, until a numerical match with the given value y is found. By default, this match is searched up to linear combinations with algebraic numbers (rationals or roots).

When no functional form is specified, for each round of argument search, a further search goes through the following common mathematical functions: sin, cos, tan, asin, acos, atan, acot, log, exp, sinh, cosh, tanh, asinh, acosh, atanh, acoth, zeta, gamma, polygamma, erf, erfinv, elliptic_k, elliptic_e, airyai, airybi. In addition, find_closed_form searches among algebraic combinations of the following mathematical constants: pi, EulerGamma, Catalan, GoldenRatio.

Installation

pip install find-closed-form

Quick start

Find a possible mathematical function for a number:

from find_closed_form import find_closed_form

find_closed_form(0.405465)          # log(3/2)

Find possible closed forms in terms of common mathematical functions:

find_closed_form(3.792277)          # 1/6 + gamma(1/4)

Find formulae in terms of mathematical constants:

find_closed_form(1.044866)          # 1/sqrt(Catalan)

Specify the functional form as a callable:

from sympy import zeta

find_closed_form(1.85653, functions=lambda x: 1/zeta(x)**2)
# zeta(1/5)**(-2)

Scope

The numerical match with the functional form is searched up to addition or multiplication by an algebraic number (that is, a rational or root):

from sympy import asinh, log, exp

find_closed_form(0.780653, functions=lambda x: asinh(x))
# sqrt(5)*asinh(4)/6

find_closed_form(7.443967, functions=lambda x: log(1 + exp(x)))
# 10*log(1 + exp(1/10))

Multi-argument functions are supported:

from sympy import gamma, log

find_closed_form(6.263643,
    functions=lambda x, y: log(x)*log(y),
    search_range="Integer")
# 2*log(5)*log(7)

find_closed_form(14.911818,
    functions=lambda x, y: gamma(x)*gamma(y),
    search_range="Plain")
# gamma(1/6)*gamma(1/3)

Search through a list of functional forms:

from sympy import sinh, cosh, sech, csch

find_closed_form(5.550045, functions=[
    lambda x: sinh(x), lambda x: cosh(x),
    lambda x: sech(x), lambda x: csch(x),
])
# 6*sech(2/5)

Multiple results can be requested through max_results:

find_closed_form(0.405465, functions=lambda x: log(x), max_results=10)
# returns multiple results, first = log(3/2)

Options

algebraic_add

Setting algebraic_add=False restricts the search to the specified functional form up to multiplication (but not addition) by an algebraic number. This can speed up the search, since special range properties are exploited for certain known functions:

from sympy import gamma

find_closed_form(0.1013578,
    functions=lambda x, y: 1/(gamma(x)*gamma(y)),
    algebraic_add=False)
# 1/(sqrt(pi)*gamma(1/6))

algebraic_factor

Setting algebraic_factor=False restricts the search to the specified functional form up to addition (but not multiplication) of an algebraic number.

If both algebraic_add and algebraic_factor are set to False, the search can be faster but may miss linear combinations of the functional form.

formula_complexity_threshold

If not enough digits are specified, a careful balance between precision and complexity of the result should be reached through formula_complexity_threshold. Often the desired formula is the simplest. For example:

from sympy import gamma

find_closed_form(38.94017, functions=lambda x: gamma(x),
    formula_complexity_threshold=15)
# 2*gamma(1/20)

The formula complexity is a positive real value which ranks complexity as follows: take all integers appearing in the formula (expanding rationals, roots, etc.); for each integer, compute the mean among the square root of its absolute value, its digit sum, and 5 times its number of digits; then take the total of these means.

max_search_rounds

The maximum number of argument search rounds is 50 by default. This also determines the largest integer argument and rational denominator reachable:

from sympy import gamma

find_closed_form(49.44221, functions=lambda x: gamma(x),
    algebraic_add=False, algebraic_factor=False, search_range="Plain")
# gamma(1/50)

By default, larger arguments are not reachable:

find_closed_form(59.43902, functions=lambda x: gamma(x),
    algebraic_add=False, algebraic_factor=False, search_range="Plain")
# None

Changing the value of max_search_rounds allows a solution to be found:

find_closed_form(59.43902, functions=lambda x: gamma(x),
    max_search_rounds=100, algebraic_add=False, algebraic_factor=False,
    search_range="Plain")
# gamma(1/60)

rational_solutions

By default, simple rational solutions are not returned, and more sophisticated solutions are searched for. If rational_solutions=True, simple exact rational solutions are allowed:

from sympy import sin, pi

find_closed_form(0.25, functions=lambda x: sin(pi*x),
    rational_solutions=True, algebraic_add=False)
# 1/4

If the functional form is the identity, there is no need for this option:

find_closed_form(0.25, functions=lambda x: x)
# 1/4

search_arguments

Through search_arguments you can specify each particular argument to be tried:

from sympy import gamma
from fractions import Fraction

find_closed_form(4.678938, functions=lambda x: gamma(x),
    search_arguments=[Fraction(3), Fraction(1), Fraction(1, 3)])
# 2 + gamma(1/3)

This can speed up the search and serves as a debugging tool.

search_range

By default, for each search round the arguments span the Farey range farey_range(-round, round, round), which consists of rationals of uniform complexity. The following values are supported:

Value Range per round
"Farey" farey_range(-cut, cut, cut) — a rational Farey range
"Plain" range(-cut, cut, 1/cut) — the shorter rational range
"Integer" range(-cut, cut) — purely integer arguments
from sympy import log

find_closed_form(6.263643,
    functions=lambda x, y: log(x)*log(y),
    search_range="Integer")
# 2*log(5)*log(7)

search_range_fn

It is possible to specify a custom range function of the search round number:

from sympy import log
from fractions import Fraction

find_closed_form(13.165149, functions=lambda x: log(x),
    search_range_fn=lambda cut: [Fraction(i) for i in range(0, 100*cut+1, 25)])
# sqrt(3)*log(2000)

significant_digits

The precision of the numerical match is automatically set to the number of significant digits in the given number. If you want to ignore some numerical error, you can specify a lower value:

from sympy import zeta

find_closed_form(0.81248057539,
    functions=lambda x: 1/zeta(x)**2,
    significant_digits=7)
# zeta(11/3)**(-2)

search_time_limit

The maximum time in seconds spent by the search algorithm. Default is 3600.

Summary table

Parameter Default Description
functions None Functional forms to search; None uses ~29 common functions.
max_results 1 Number of results to return.
significant_digits Auto Precision target; auto-detected from input digits.
formula_complexity_threshold Auto Maximum formula complexity; auto-scaled per round.
algebraic_factor True Search up to multiplication by algebraic numbers.
algebraic_add True Search up to addition of algebraic numbers.
rational_solutions False Allow simple rational solutions.
max_search_rounds 50 Maximum argument-range expansion rounds.
search_range "Farey" Argument range type: "Farey", "Plain", or "Integer".
search_range_fn None Custom f(cut) → list for argument generation.
search_arguments None Fixed argument list (bypasses auto ranges).
search_time_limit 3600 Maximum seconds for the search.

Properties and relations

find_closed_form with the identity function generalizes rationalization and works with fewer digits:

find_closed_form(0.666, functions=lambda x: x)   # 2/3

When the given number approximates a simple root, it also generalizes root approximation:

find_closed_form(4.243, functions=lambda x: x)    # 3*sqrt(2)
find_closed_form(0.5848, functions=lambda x: x)   # 5**(-1/3)

Auxiliary functions

The formula_complexity function is also exported and can be used directly to compute the complexity of any sympy expression:

from find_closed_form import formula_complexity
from sympy import Rational

formula_complexity(2*gamma(Rational(1, 20)))

The farey_range function generates Farey-based argument ranges:

from find_closed_form import farey_range

farey_range(-3, 3, 3)
# [-3, -8/3, -5/2, ..., 5/2, 8/3, 3]

Dependencies

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

find_closed_form-0.4.0.tar.gz (18.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

find_closed_form-0.4.0-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file find_closed_form-0.4.0.tar.gz.

File metadata

  • Download URL: find_closed_form-0.4.0.tar.gz
  • Upload date:
  • Size: 18.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for find_closed_form-0.4.0.tar.gz
Algorithm Hash digest
SHA256 8a90e04fd120959a3e86379c358d6d51c3326d7941739cf83d6123031edf0ecb
MD5 51694906d5b092b4fb47c8ab4bfc2b27
BLAKE2b-256 1ac0137c5f97c61fb73536901d9ec758a747f60b09469202e07e78095490e3d3

See more details on using hashes here.

File details

Details for the file find_closed_form-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for find_closed_form-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d1f1f98acccd7e205e83eb34965a1b3d35970618850b12148b15ca3c98cc0e39
MD5 7c18fd492b6ebbf669d55725640b62ea
BLAKE2b-256 2a4af0e7d971cb3d1d205afcfc5e41b7f9c0478ce69f72c3df64f3caf54ede49

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page