Skip to content

Commit 4746879

Browse files
Merge pull request #51 from ForeverHaibara/setup
Setup
2 parents 2c6d0ba + 84f2ff8 commit 4746879

File tree

12 files changed

+786
-318
lines changed

12 files changed

+786
-318
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ __pycache__/
77
.trae/
88
.benchmarks/
99
*.log
10-
.coverage
10+
.coverage
11+
12+
build/
13+
dist/
14+
*.egg-info/

LICENSE

Lines changed: 617 additions & 282 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Triples
22

3+
[![PyPI version](https://img.shields.io/pypi/v/triples.svg)](https://pypi.org/project/triples/)
4+
35
Triples 是由 forever豪3 开发的基于 Python 的 SymPy 库的多项式不等式自动证明程序。其专注于通过配方法生成不等式的可读证明。它同时提供直观的图形界面与代码接口,助力代数不等式的探索。
46

57
Triples is an automatic inequality proving software developed by ForeverHaibara, based on the Python SymPy library. It focuses on generating readable proofs of inequalities through sum of squares (SOS). The program offers both a graphical user interface and a code interface to facilitate the exploration of Olympiad-level algebraic inequalities.
@@ -43,13 +45,10 @@ Triples is an automatic inequality proving software developed by ForeverHaibara,
4345

4446
See more in the Jupyter notebook: [notebooks/examples.ipynb](notebooks/examples.ipynb)
4547

46-
Ensure "triples" is in the directory or the system path.
48+
Triples has hard dependencies on Python>=3.6, SymPy>=1.9, NumPy, SciPy, and an SDP solver, e.g., Clarabel. It can now be installed via pip:
4749

4850
```
49-
pip install sympy
50-
pip install numpy
51-
pip install scipy
52-
pip install clarabel
51+
pip install triples
5352
```
5453

5554
```py
@@ -60,7 +59,7 @@ a, b, c, x, y, z = sp.symbols("a b c x y z")
6059

6160
### Sum of Squares
6261

63-
Given a sympy polynomial, the `sum_of_squares` solver will return a Solution-class object if it succeeds. It returns None if it fails (but it does not mean the polynomial is not a sum of squares or positive semidefinite).
62+
Given a sympy expression, the `sum_of_squares` solver will return a Solution-class object if it succeeds. It returns None if it fails (but it does not mean the expression is not a sum of squares or positive semidefinite).
6463

6564
**Example 1** $a,b,c\in\mathbb{R}$, prove: $\left(a^2+b^2+c^2\right)^2\geq 3\left(a^3b+b^3c+c^3a\right)$.
6665

@@ -74,7 +73,7 @@ Given a sympy polynomial, the `sum_of_squares` solver will return a Solution-cl
7473

7574
<br>
7675

77-
If there are inequality or equality constraints, send them as a list of sympy expressions to `ineq_constraints` and `eq_constraints`.
76+
If there are inequality or equality constraints, send them as a list of sympy expressions to `ineq_constraints` and `eq_constraints`. (These are the second and third arguments of the `sum_of_squares` function.)
7877

7978
**Example 2** $a,b,c\in\mathbb{R}_+$, prove: $a(a-b)(a-c)+b(b-c)(b-a)+c(c-a)(c-b)\geq 0$.
8079

@@ -105,19 +104,15 @@ x*(Σ(2*F(a) + 13))/6 + Σ(a - b)**2*F(c) + (Σ(a - 1)**2*F(b)*F(c))/6 + 5*(Σ(a
105104

106105
## 图形化界面 Graphic User Interface
107106

108-
本程序图形化界面有两种启动方式: Flask 与 Gradio.
107+
本程序图形化界面有两种启动方式: Flask 与 Gradio. 使用图形化界面必须下载完整的仓库, 而非使用 pip 安装.
109108

110-
Two graphical backends are supported: Flask and Gradio.
109+
Two graphical backends are supported: Flask and Gradio. To use the graphical interface, you need to download the full repository instead of installing via pip.
111110

112111
### Flask 启动
113112

114113
1. 安装依赖: Install Dependencies
115114

116115
```
117-
pip install sympy
118-
pip install numpy
119-
pip install scipy
120-
pip install clarabel
121116
pip install flask
122117
pip install flask_cors
123118
pip install flask_socketio
@@ -131,12 +126,7 @@ pip install flask_socketio
131126
1. 安装依赖: Install Dependencies
132127

133128
```
134-
pip install sympy
135-
pip install numpy
136-
pip install scipy
137-
pip install clarabel
138129
pip install gradio>=5.0
139-
pip install pillow
140130
```
141131

142132
1. 控制台中运行 `python gradio.app.py` 启动后端. Run `python gradio.app.py` to launch the backend.

notebooks/README_pypi.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Triples
2+
3+
Triples is an automatic inequality proving software developed by ForeverHaibara, based on the Python SymPy library. It focuses on generating readable proofs of inequalities through sum of squares (SOS). The program offers both a graphical user interface and a code interface to facilitate the exploration of Olympiad-level algebraic inequalities.
4+
5+
Homepage: [https://github.com/ForeverHaibara/Triple-SOS](https://github.com/ForeverHaibara/Triple-SOS)
6+
7+
To install, use:
8+
```
9+
pip install triples
10+
```
11+
12+
## Code Usage
13+
14+
```py
15+
from triples import sum_of_squares
16+
import sympy as sp
17+
a, b, c, x, y, z = sp.symbols("a b c x y z")
18+
```
19+
20+
### Sum of Squares
21+
22+
Given a sympy polynomial, the `sum_of_squares` solver will return a Solution-class object if it succeeds. It returns None if it fails (but it does not mean the polynomial is not a sum of squares or positive semidefinite).
23+
24+
**Example 1** $a,b,c\in\mathbb{R}$, prove: $\left(a^2+b^2+c^2\right)^2\geq 3\left(a^3b+b^3c+c^3a\right)$.
25+
26+
```py
27+
>>> sol = sum_of_squares((a**2 + b**2 + c**2)**2 - 3*(a**3*b + b**3*c + c**3*a))
28+
>>> sol.solution # this should be a sympy expression
29+
(Σ(a**2 - a*b - a*c - b**2 + 2*b*c)**2)/2
30+
>>> sol.solution.doit() # this expands the cyclic sums
31+
(-a**2 + 2*a*b - a*c - b*c + c**2)**2/2 + (a**2 - a*b - a*c - b**2 + 2*b*c)**2/2 + (-a*b + 2*a*c + b**2 - b*c - c**2)**2/2
32+
```
33+
34+
<br>
35+
36+
If there are inequality or equality constraints, send them as a list of sympy expressions to `ineq_constraints` and `eq_constraints`.
37+
38+
**Example 2** $a,b,c\in\mathbb{R}_+$, prove: $a(a-b)(a-c)+b(b-c)(b-a)+c(c-a)(c-b)\geq 0$.
39+
40+
```py
41+
>>> sol = sum_of_squares(a*(a-b)*(a-c) + b*(b-c)*(b-a) + c*(c-a)*(c-b), ineq_constraints = [a,b,c])
42+
>>> sol.solution
43+
((Σ(a - b)**2*(a + b - c)**2)/2 + Σa*b*(a - b)**2)/(Σa)
44+
```
45+
46+
<br>
47+
48+
If you want to track the inequality and equality constraints, you can send in a dict containing the alias of the constraints.
49+
50+
**Example 3** $a,b,c\in\mathbb{R}_+$ and $abc=1$, prove: $\sum \frac{a^2}{2+a}\geq 1$.
51+
52+
```py
53+
>>> sol = sum_of_squares(((a+2)*(b+2)*(c+2)*(a**2/(2+a)+b**2/(2+b)+c**2/(2+c)-1)).cancel(), ineq_constraints=[a,b,c], eq_constraints={a*b*c-1:x})
54+
>>> sol.solution
55+
x*(Σ(2*a + 13))/6 + Σa*(b - c)**2 + (Σa*b*(c - 1)**2)/6 + 5*(Σ(a - 1)**2)/6 + 7*(Σ(a - b)**2)/12
56+
>>> sol.solution.doit()
57+
a*b*(c - 1)**2/3 + a*c*(b - 1)**2/3 + a*(-b + c)**2 + a*(b - c)**2 + b*c*(a - 1)**2/3 + b*(-a + c)**2 + b*(a - c)**2 + c*(-a + b)**2 + c*(a - b)**2 + x*(4*a + 4*b + 4*c + 78)/6 + 7*(-a + b)**2/12 + 7*(-a + c)**2/12 + 5*(a - 1)**2/3 + 7*(a - b)**2/12 + 7*(a - c)**2/12 + 7*(-b + c)**2/12 + 5*(b - 1)**2/3 + 7*(b - c)**2/12 + 5*(c - 1)**2/3
58+
>>> F = sp.Function("F")
59+
>>> sol = sum_of_squares(((a+2)*(b+2)*(c+2)*(a**2/(2+a)+b**2/(2+b)+c**2/(2+c)-1)).cancel(), {a: F(a), b: F(b), c: F(c)}, {a*b*c-1:x})
60+
>>> sol.solution
61+
x*(Σ(2*F(a) + 13))/6 + Σ(a - b)**2*F(c) + (Σ(a - 1)**2*F(b)*F(c))/6 + 5*(Σ(a - 1)**2)/6 + 7*(Σ(a - b)**2)/12
62+
```
63+
64+
65+
## Warnings
66+
67+
* The `triples` package uses dynamic patches to fix some known bugs in the SymPy library for older versions of SymPy, and may slightly affect the behaviour of SymPy. This includes a fix for `radsimp` at [https://github.com/sympy/sympy/pull/26720](https://github.com/sympy/sympy/pull/26720) and setting `CRootOf.is_algebraic = True` at [https://github.com/sympy/sympy/pull/26806](https://github.com/sympy/sympy/pull/26806).

pyproject.toml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[build-system]
2+
requires = ["setuptools>=61.0", "wheel"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "triples"
7+
version = "0.1.0"
8+
description = "Automatic sum-of-squares proofs for algebraic inequalities"
9+
readme = "notebooks/README_pypi.md"
10+
license = {file = "LICENSE"}
11+
authors = [
12+
{name = "ForeverHaibara", email = "1378855363@qq.com" },
13+
]
14+
requires-python = ">=3.6"
15+
dependencies = [
16+
"numpy",
17+
"scipy",
18+
"sympy>=1.9",
19+
"clarabel; python_version >= '3.7'",
20+
"cvxopt; python_version < '3.7'",
21+
]
22+
keywords = ["sum-of-squares", "SOS", "inequality", "solver", "optimization"]
23+
classifiers = [
24+
"Development Status :: 4 - Beta",
25+
"Intended Audience :: Science/Research",
26+
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
27+
"Programming Language :: Python :: 3",
28+
"Programming Language :: Python :: 3.6",
29+
"Programming Language :: Python :: 3.7",
30+
"Programming Language :: Python :: 3.8",
31+
"Programming Language :: Python :: 3.9",
32+
"Programming Language :: Python :: 3.10",
33+
"Programming Language :: Python :: 3.11",
34+
"Programming Language :: Python :: 3.12",
35+
"Programming Language :: Python :: 3.13",
36+
"Topic :: Scientific/Engineering :: Mathematics",
37+
]
38+
39+
[project.urls]
40+
"Homepage" = "https://github.com/ForeverHaibara/Triple-SOS"
41+
42+
[tool.setuptools.packages.find]
43+
where = ["."]
44+
include = ["triples*"]
45+
46+
[tool.setuptools.package-data]
47+
triples = ["**/*.npz"]

triples/__init__.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
from .utils import pl, CyclicSum, CyclicProduct
2-
from .core import sum_of_squares
1+
from .utils import pl, CyclicSum, CyclicProduct, generate_monoms
2+
3+
from .core import sum_of_squares, StructuralSOS, LinearSOS, SDPSOS, SOSPoly
4+
5+
from .sdp import SDPProblem, congruence
6+
7+
__version__ = "0.1.0"
38

49
__all__ = [
5-
'pl', 'CyclicSum', 'CyclicProduct',
6-
'sum_of_squares'
10+
'__version__',
11+
12+
'pl', 'CyclicSum', 'CyclicProduct', 'generate_monoms',
13+
'sum_of_squares', 'StructuralSOS', 'LinearSOS', 'SDPSOS', 'SOSPoly',
14+
'SDPProblem', 'congruence'
715
]

triples/core/__init__.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,40 @@
66
sum_of_squares, sum_of_squares_multiple
77
)
88

9+
from .preprocess import (
10+
ReformulateAlgebraic, CancelDenominator, SolveMul, SolvePolynomial
11+
)
12+
913
from .linsos import (
10-
LinearSOS,
14+
LinearSOS, LinearSOSSolver
1115
)
1216

1317
from .structsos import (
14-
StructuralSOS, prove_univariate
18+
StructuralSOS, StructuralSOSSolver, prove_univariate
1519
)
1620

1721
from ..utils import pqr_sym, pqr_cyc, pqr_ker
1822

1923
from .symsos import (
20-
SymmetricSOS, sym_representation, sym_representation_inv,
24+
SymmetricSOS, SymmetricSubstitution, sym_representation, sym_representation_inv,
25+
2126
)
2227

2328
from .sdpsos import (
24-
SDPSOS, SDPProblem, JointSOSElement, SOSPoly, SOHSPoly
29+
SDPSOS, SDPSOSSolver, SDPProblem,
30+
JointSOSElement, SOSPoly, SOHSPoly, SOSMomentPoly,
2531
)
2632

2733
__all__ = [
2834
'ProofNode', 'ProofTree',
2935
'InequalityProblem',
3036
'Solution',
3137
'sum_of_squares', 'sum_of_squares_multiple',
32-
'LinearSOS',
33-
'StructuralSOS',
34-
'prove_univariate',
38+
'ReformulateAlgebraic', 'CancelDenominator', 'SolveMul', 'SolvePolynomial',
39+
'LinearSOS', 'LinearSOSSolver',
40+
'StructuralSOS', 'StructuralSOSSolver', 'prove_univariate',
3541
'pqr_sym', 'pqr_cyc', 'pqr_ker',
36-
'SymmetricSOS', 'sym_representation', 'sym_representation_inv',
37-
'SDPSOS', 'SDPProblem', 'JointSOSElement', 'SOSPoly', 'SOHSPoly'
38-
42+
'SymmetricSOS', 'SymmetricSubstitution', 'sym_representation', 'sym_representation_inv',
43+
'SDPSOS', 'SDPSOSSolver', 'SDPProblem',
44+
'JointSOSElement', 'SOSPoly', 'SOHSPoly', 'SOSMomentPoly',
3945
]

triples/core/preprocess/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@
55

66
from ..node import ProofNode, ProofTree
77
from .features import get_features
8+
from .modeling import ReformulateAlgebraic
9+
from .algebraic import CancelDenominator, SolveMul
810
from .polynomial import SolvePolynomial
911
from .reparam import Reparametrization
1012
from .signs import sign_sos, get_symbol_signs
1113

1214
__all__ = [
1315
'ProofNode', 'ProofTree',
14-
'get_features', 'SolvePolynomial', 'Reparametrization',
16+
'get_features',
17+
'ReformulateAlgebraic',
18+
'CancelDenominator', 'SolveMul',
19+
'SolvePolynomial',
20+
'Reparametrization',
1521
'sign_sos', 'get_symbol_signs',
1622
]

triples/core/preprocess/polynomial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def get_polynomial_solvers(self, configs):
4343
]
4444
return solvers
4545

46-
def explore(self, configs):
46+
def explore(self, configs):
4747
if self.state != 0 and len(self.children) == 0:
4848
# all children failed
4949
self.finished = True

triples/core/shared.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
"""
2+
To be deprecated. Do not use this file.
3+
"""
14
from typing import Tuple, Dict, List, Union, Optional
25

36
import sympy as sp

0 commit comments

Comments
 (0)