├── .github └── workflows │ ├── build.yml │ └── upgrade_lean.yml ├── .gitignore ├── .gitpod.yml ├── .vscode ├── copyright.code-snippets └── settings.json ├── README.md ├── blueprint ├── .gitignore ├── src │ ├── basic.tex │ ├── content.tex │ ├── defs.tex │ ├── fix_mathjax.sh │ ├── fourier.log │ ├── fourier.tex │ ├── introduction.tex │ ├── latexmkrc │ ├── macros_common.tex │ ├── macros_print.tex │ ├── macros_web.tex │ ├── plastex.cfg │ ├── print.tex │ ├── stylecours.css │ ├── tech.tex │ ├── techlemmas.tex │ ├── techprop.tex │ └── web.tex └── tasks.py ├── docs ├── _config.yml ├── blueprint.pdf ├── blueprint │ ├── chap-basic.html │ ├── chap-def.html │ ├── chap-fourier.html │ ├── chap-tech.html │ ├── chap-techlemmas.html │ ├── chap-techprop.html │ ├── coverage.html │ ├── dep_graph_document.html │ ├── index.html │ ├── js │ │ ├── coverage.js │ │ ├── d3-graphviz.js │ │ ├── d3.min.js │ │ ├── expatlib.wasm │ │ ├── graphvizlib.wasm │ │ ├── hpcc.min.js │ │ ├── jquery.min.js │ │ ├── js.cookie.min.js │ │ ├── plastex.js │ │ ├── showmore.js │ │ └── svgxuse.js │ ├── sect0001.html │ ├── styles │ │ ├── amsthm.css │ │ ├── dep_graph.css │ │ ├── showmore.css │ │ ├── style_coverage.css │ │ ├── stylecours.css │ │ ├── theme-blue.css │ │ ├── theme-green.css │ │ └── theme-white.css │ └── symbol-defs.svg ├── index.html ├── pygments.css └── style.css ├── docs_src ├── index.md └── template.html ├── leanpkg.toml ├── scripts ├── count_sorry.sh ├── detect_errors.py ├── lean_version.lean ├── lint_project.lean ├── mk_all.sh └── update_nolints.sh ├── src ├── aux_lemmas.lean ├── defs.lean ├── final_results.lean ├── for_mathlib │ ├── basic_estimates.lean │ ├── integral_rpow.lean │ └── misc.lean ├── fourier.lean └── main_results.lean └── tasks.py /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: continuous integration 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | update_lean_xyz_branch_and_build: 8 | runs-on: ubuntu-latest 9 | name: Update lean-x.y.z branch and build project 10 | steps: 11 | 12 | - name: checkout project 13 | uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: update branch 18 | if: github.ref == 'refs/heads/master' 19 | uses: leanprover-contrib/update-versions-action@master 20 | 21 | - name: install elan 22 | run: | 23 | set -o pipefail 24 | curl https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -sSf | sh -s -- --default-toolchain none -y 25 | ~/.elan/bin/lean --version 26 | echo "$HOME/.elan/bin" >> $GITHUB_PATH 27 | 28 | - name: install python 29 | uses: actions/setup-python@v3 30 | with: 31 | python-version: 3.9 32 | 33 | - name: blueprint deps 34 | run: | 35 | sudo apt-get update 36 | sudo apt install graphviz libgraphviz-dev pandoc texlive-full texlive-xetex 37 | pip install invoke 38 | git clone https://github.com/plastex/plastex.git 39 | pip install ./plastex 40 | git clone https://github.com/PatrickMassot/leanblueprint.git 41 | pip install ./leanblueprint 42 | 43 | - name: build project 44 | run: | 45 | leanproject get-mathlib-cache 46 | lean --make src 47 | 48 | - name: build blueprint 49 | run: | 50 | inv all html 51 | 52 | - name: deploy 53 | uses: JamesIves/github-pages-deploy-action@v4 54 | with: 55 | SINGLE_COMMIT: true 56 | BRANCH: gh-pages # The branch the action should deploy to. 57 | FOLDER: docs/ 58 | 59 | -------------------------------------------------------------------------------- /.github/workflows/upgrade_lean.yml: -------------------------------------------------------------------------------- 1 | on: 2 | schedule: 3 | - cron: '0 */3 * * *' # once a day at 2am UTC 4 | 5 | jobs: 6 | upgrade_lean: 7 | runs-on: ubuntu-latest 8 | name: Bump Lean and dependency versions 9 | steps: 10 | - name: checkout project 11 | uses: actions/checkout@v2 12 | - name: upgrade Lean and dependencies 13 | uses: leanprover-contrib/lean-upgrade-action@master 14 | with: 15 | repo: ${{ github.repository }} 16 | access-token: ${{ secrets.GITHUB_TOKEN }} 17 | - name: update version branches 18 | uses: leanprover-contrib/update-versions-action@master 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.olean 2 | /_target 3 | /leanpkg.path 4 | src/all.lean 5 | decls.yaml 6 | decls.pickle 7 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: leanprovercommunity/mathlib:gitpod 2 | 3 | vscode: 4 | extensions: 5 | - jroesch.lean 6 | 7 | tasks: 8 | - command: . /home/gitpod/.profile && scripts/get-cache.sh 9 | -------------------------------------------------------------------------------- /.vscode/copyright.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "Copyright header for mathlib": { 3 | "scope": "lean", 4 | "prefix": "copyright", 5 | "body": [ 6 | "/-", 7 | "Copyright (c) ${CURRENT_YEAR} $1. All rights reserved.", 8 | "Released under Apache 2.0 license as described in the file LICENSE.", 9 | "Authors: $1", 10 | "-/" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.insertSpaces": true, 3 | "editor.tabSize": 2, 4 | "editor.rulers" : [100], 5 | "files.encoding": "utf8", 6 | "files.eol": "\n", 7 | "files.insertFinalNewline": true, 8 | "files.trimFinalNewlines": true, 9 | "files.trimTrailingWhitespace": true, 10 | "search.usePCRE2": true, 11 | "workbench.startupEditor": "none", 12 | "editor.hover.delay": 2000, 13 | "yaml.schemas": { 14 | "https://json.schemastore.org/github-workflow.json": "file:///workspace/unit-fractions/.github/workflows/build.yml" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unit fractions 2 | 3 | This project contains a formalized version of the proof of result on unit fractions, proved by Bloom in the preprint available [here](https://arxiv.org/abs/2112.03726): any set of integers of positive density contains a solution to $1=1/n_1+\cdots+1/n_k$ where the $n_1,\ldots,n_k$ are distinct denominators from the set. This proves a conjecture of Erdos and Graham. Details can be found on the [project website](https://b-mehta.github.io/unit-fractions/). 4 | 5 | Much of the project infrastructure has been adapted from the [sphere eversion project](https://leanprover-community.github.io/sphere-eversion/) and the [liquid tensor experiment](https://leanprover-community.github.io/lean-liquid/). 6 | 7 | # Build the Lean files 8 | 9 | To build the Lean files of this project, you need to have a working version of Lean. 10 | See [the installation instructions](https://leanprover-community.github.io/get_started.html) (under Regular install). 11 | 12 | To obtain this repo, run `leanproject get https://github.com/b-mehta/unit-fractions`. If you already have the repo, you can 13 | update it with `git pull` followed by `leanproject get-mathlib-cache`. 14 | 15 | To build the repo, run `leanproject build`. 16 | 17 | # Build the blueprint 18 | 19 | To build the web version of the blue print, you need a working LaTeX installation. 20 | Furthermore, you need some packages: 21 | ``` 22 | sudo apt install graphviz libgraphviz-dev 23 | pip3 install invoke pandoc 24 | cd .. # go to folder where you are happy clone git repos 25 | git clone git@github.com:plastex/plastex 26 | pip3 install ./plastex 27 | git clone git@github.com:PatrickMassot/leanblueprint 28 | pip3 install ./leanblueprint 29 | cd unit-fractions 30 | ``` 31 | 32 | To actually build the blueprint, run 33 | ``` 34 | leanproject get-mathlib-cache 35 | leanproject build 36 | inv all 37 | ``` 38 | 39 | To view the web-version of the blueprint locally, run `inv serve` and navigate to 40 | `http://localhost:8000/` in your favorite browser. 41 | -------------------------------------------------------------------------------- /blueprint/.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | *.paux 3 | *.aux 4 | print 5 | web 6 | __pycache__ 7 | *.fdb_latexmk 8 | 9 | -------------------------------------------------------------------------------- /blueprint/src/basic.tex: -------------------------------------------------------------------------------- 1 | \chapter{Basic Estimates} 2 | \label{chap:basic} 3 | 4 | This section contains standard estimates from analytic number theory that will be required. 5 | 6 | \begin{lemma}\label{lem:omegasum} 7 | \leanok 8 | For any $X\geq 3$ 9 | \[\sum_{n\leq X}\omega(n) = X\log\log X+O(X).\] 10 | \end{lemma} 11 | \begin{proof}\uses{lem:mertensprimes} 12 | \leanok 13 | Since $\omega(n) = \sum_{p\leq n}1_{p\mid n}$, the left-hand side equals, after a change in the order of summation, 14 | \[\sum_{p\leq X}\sum_{n\leq X}1_{p\mid n} = \sum_{p\leq X}\left\lfloor\frac{X}{p}\right\rfloor.\] 15 | Since $\lfloor x\rfloor=x+O(1)$, this is equal to 16 | \[X\sum_{p\leq X}\frac{1}{p} +O(\pi(X)) = X\log\log X+O(X),\] 17 | using Lemma~\ref{lem:mertensprimes} and the trivial estimate $\pi(X)\ll X$. 18 | \end{proof} 19 | 20 | \begin{lemma}\label{lem:omegasquaredsum} 21 | \leanok 22 | For any $X\geq 3$ 23 | \[\sum_{n\leq X}\omega(n)^2 \leq X(\log\log X)^2+O(X\log\log X).\] 24 | \end{lemma} 25 | \begin{proof}\uses{lem:mertensprimes} 26 | \leanok 27 | Since $\omega(n) = \sum_{p\leq n}1_{p\mid n}$, the left-hand side is equal to, after expanding the sum and rearranging, 28 | \[\sum_{p,q\leq X}\sum_{n\leq X}1_{p\mid n}1_{q\mid n}.\] 29 | The part of the sum where $p=q$ is 30 | \[\sum_{p\leq X}\sum_{n\leq X}\lfloor X/p\rfloor = X\log\log X+O(X),\] 31 | as in the proof of Lemma~\ref{lem:omegasum}. If $p\neq q$, then $p\mid n$ and $q\mid n$ if and only if $pq\mid n$, and so the sum over $n$ is bounded above by 32 | \[\sum_{n\leq X}1_{pq\mid n}= \lfloor X/pq\rfloor \leq X/pq.\] 33 | Therefore 34 | \[\sum_{\substack{p,q\leq X\\ p\neq q}}\sum_{n\leq X}1_{p\mid n}1_{q\mid n}\leq X\sum_{\substack{p,q\leq X\\ p\neq q}}\frac{1}{pq}\leq X\sum_{p,q\leq X}\frac{1}{pq}\leq X\brac{\sum_{p\leq X}\frac{1}{p}}^2.\] 35 | By Lemma~\ref{lem:mertensprimes} this is $X(\log\log X+O(1))^2 = X(\log\log X)^2+O(X\log\log X)$. The lemma follows by combining the estimates on the two parts of the sum. 36 | \end{proof} 37 | 38 | \begin{lemma}[Tur\'{a}n's estimate]\label{lem:turan} 39 | \leanok 40 | \lean{turan_primes_estimate} 41 | For any $X\geq 3$ 42 | \[\sum_{n\leq X}(\omega(n) - \log\log X)^2 \ll X\log\log X.\] 43 | \end{lemma} 44 | \begin{proof}\uses{lem:omegasum,lem:omegasquaredsum} 45 | \leanok 46 | The left-hand side equals 47 | \[\sum_{n\leq X}\omega(n)^2 - 2\log\log X\sum_{n\leq X}\omega(n)+\lfloor X\rfloor (\log\log X)^2.\] 48 | The first summand is at most, by Lemma~\ref{lem:omegasquaredsum}, 49 | \[X(\log\log X)^2 +O(X\log\log X).\] 50 | The second summand is equal to, by Lemma~\ref{lem:omegasum}, 51 | \[-2\log\log X(X\log\log X+O(X)) = -2X(\log\log X)^2 +O(X\log\log X).\] 52 | The third summand is equal to 53 | \[(X+O(1))(\log\log X)^2 = X(\log\log X)^2 + O(X\log\log X).\] 54 | Therefore the main terms cancel, and 55 | \[\sum_{n\leq X}(\omega(n) - \log\log X)^2\leq O(X\log\log X)\] 56 | as required. 57 | \end{proof} 58 | 59 | \begin{lemma}[Chebyshevs' estimate]\label{lem:chebyshev} 60 | \leanok 61 | \lean{is_O_prime_counting_div_log} 62 | For any $X\geq 3$ 63 | \[\pi(X) \ll \frac{X}{\log X}.\] 64 | \end{lemma} 65 | \begin{proof} 66 | \leanok 67 | \end{proof} 68 | 69 | \begin{lemma}[Divisor bound]{\label{lem:divisor_bound}} 70 | \leanok 71 | \lean{divisor_bound} 72 | For any $\epsilon$ such that $0<\epsilon\leq 1$, if $n$ is sufficiently large depending on $\epsilon$, then 73 | \[\tau(n) \leq n^{(1+\epsilon)\frac{\log 2}{\log\log n}}.\] 74 | \end{lemma} 75 | \begin{proof} 76 | \leanok 77 | We first show that, for any real $K\geq 2$, 78 | \[\tau(n) \leq n^{1/K}K^{2^K}.\] 79 | Write $n$ as the product of unique prime powers $n=p_1^{k_1}\cdots p_r^{k_r}$, so that 80 | \[\frac{\tau(n)}{n^{1/K}} = \frac{\prod_{i=1}^r (k_i+1)}{\prod_{i=1}^r p_i^{k_i/K}} = \prod_{i=1}^r \frac{k_i+1}{p_i^{k_i/K}}.\] 81 | If $p_i>2^K$ then 82 | \[\frac{k_i+1}{p_i^{k_i/K}}\leq \frac{k_i+1}{2^{k_i}}\leq 1,\] 83 | since $1+k \leq 2^k$ for all integer $k\geq 0$ by Bernoulli's inequality. Therefore 84 | \[ \prod_{i=1}^r \frac{k_i+1}{p_i^{k_i/K}} \leq \prod_{\substack{1\leq i\leq r\\ p_i<2^K}}\frac{k_i+1}{p_i^{k_i/K}}.\] 85 | If $p_i<2^K$ then, since $p_i\geq 2$, 86 | \[\frac{k_i+1}{p^{k_i/K}}\leq \frac{k_i+1}{2^{k_i/K}}\leq \frac{k_i+1}{k_i/K+1/2},\] 87 | using the fact that $x+1/2\leq 2^x$ for all $x\geq 0$. Since $K\geq 2$ the denominator here is $\geq (1+k_i)/K$, and so $\frac{k_i+1}{p^{k_i/K}}\leq K$. Therefore 88 | \[\frac{\tau(n)}{n^{1/K}}\leq \prod_{\substack{1\leq i\leq r\\ p_i<2^K}} K\leq K^{\pi(2^K)}\leq K^{2^K},\] 89 | as required. 90 | 91 | The second part of the proof is to apply the first part with 92 | \[K=\brac{1+\epsilon/2}^{-1}\frac{\log\log n}{\log 2}.\] 93 | (The right-hand side tends to $\infty$ as $n\to\infty$, so for sufficiently large $n$ we have $K\geq 2$ as required.) 94 | 95 | Note that $2^K= (\log n)^{\frac{2}{2+\epsilon}}\leq (\log n)^{1-\epsilon}$ (since $1-\epsilon>\frac{2}{2+\epsilon}$, since $\epsilon\leq 1$) and 96 | \[\log K \leq \log\log\log n.\] 97 | Taking logarithms of the inequality in the first part, 98 | \[\log \tau(n) \leq \frac{\log n}{K}+2^K\log K\leq \log n\brac{\frac{1}{K}+\frac{\log\log\log n}{(\log n)^\epsilon}}\] 99 | \[= \log n\frac{\log 2}{\log\log n}\brac{1+\epsilon/2+\frac{(\log\log\log n)(\log\log n)}{(\log 2)(\log n)^{\epsilon}}}.\] 100 | For any fixed $\epsilon>0$, the function $\frac{(\log\log\log n)(\log\log n)}{(\log 2)(\log n)^{\epsilon}}\to 0$ as $n\to \infty$, so for sufficiently large $n$ it is $\leq \epsilon/2$, and hence 101 | \[\log \tau(n) \leq \log n\frac{\log 2}{\log\log n}(1+\epsilon)\] 102 | as required. 103 | 104 | \end{proof} 105 | 106 | \begin{lemma}[Mertens' estimate]\label{lem:mertens1} 107 | \leanok 108 | \lean{prime_power_reciprocal} 109 | There exists a constant $c$ such that 110 | \[\sum_{q\leq X}\frac{1}{q} = \log\log X+c+O(1/\log X),\] 111 | where the sum is restricted to prime powers. 112 | \end{lemma} 113 | \begin{proof} 114 | \leanok 115 | \uses{lem:mertensprimes} 116 | 117 | \end{proof} 118 | 119 | \begin{lemma}[Mertens' estimate, just for primes]\label{lem:mertensprimes} 120 | \leanok 121 | \lean{prime_reciprocal} 122 | There exists a constant $c$ such that 123 | \[\sum_{p\leq X}\frac{1}{p} = \log\log X+c+O(1/\log X),\] 124 | where the sum is restricted to primes. 125 | \end{lemma} 126 | \begin{proof} 127 | \leanok 128 | 129 | \end{proof} 130 | 131 | \begin{lemma}[Mertens' product estimate]\label{lem:mertens2} 132 | \leanok 133 | \lean{mertens_third} 134 | For any $X\geq 2$, 135 | \[\prod_{p\leq X}\brac{1-\frac{1}{p}}^{-1}\asymp \log X.\] 136 | \end{lemma} 137 | \begin{proof}\uses{lem:mertens1} 138 | \leanok 139 | 140 | \end{proof} 141 | 142 | \begin{lemma}[Sieve of Eratosthenes-Legendre]\label{lem:sieve_eratosthenes} 143 | \leanok 144 | \lean{sieve_eratosthenes} 145 | For any $x,y\geq 0$ and $u\geq v\geq 1$ 146 | \[\#\{ n\in (x,x+y] : p\mid n\implies p\not\in [u,v]\} = y\prod_{u\leq p\leq v}\brac{1-\frac{1}{p}}+O(2^v).\] 147 | \end{lemma} 148 | \begin{proof} 149 | \leanok 150 | Let $P = \prod_{u\leq p\leq v}p$. The left-hand side of the estimate in the lemma can be written as 151 | \[\sum_{x\leq n0$. Let $y=C_1/\delta$ and $z=\delta^{-C_2\delta^{-2}}$, where $C_1,C_2$ are two absolute constants to be determined later. It suffices to show that there is some $d\in [y,z]$ and finite $S\subset A$ such that $R(S)=1/d$. Indeed, given such an $S$ we can remove it from $A$ and still have an infinite set of upper density $\delta$, so we can find another $S'\subset A\backslash S$ with $R(S')=1/d'$ for some $d'\in [y,z]$, and so on. After repeating this process at least $\lceil z-y\rceil^2$ times there must be some $d\in [y,z]$ with at least $d$ disjoint $S_1,\ldots,S_d\subset A$ with $R(S_i)=1/d$. Taking $S=S_1\cup\cdots \cup S_d$ yields $R(S)=1$ as required. 14 | 15 | By definition of the upper density, there exist arbitrarily large $N$ such that $\abs{A\cap [1,N]}\geq \frac{\delta}{2}N$. The number of $n\in [1,N]$ divisible by some prime power $q\geq N^{1-6/\log\log N}$ is 16 | \[\ll N \sum_{N^{1-6/\log\log N}0$, we have that $R(A_N)\geq 4/y$, say. All of the conditions of Proposition~\ref{prop:techmain} are now satisfied (provided $N$ is chosen sufficiently large in terms of $\delta$), and hence there is some $S\subset A_N\subset A$ such that $R(S)=1/d$ for some $d\in [y,z]$, which suffices as discussed above. 28 | \end{proof} 29 | 30 | \begin{theorem}[Solution in sets of positive logarithmic density, quantitative version]\label{th:log_density_theorem} 31 | \leanok 32 | \lean{unit_fractions_upper_log_density} 33 | There is a constant $C>0$ such that the following holds. If $A\subset \{1,\ldots,N\}$ and 34 | \[\sum_{n\in A}\frac{1}{n}\geq C \frac{\log \log\log N}{\log\log N}\log N\] 35 | then there is an $S\subset A$ such that $\sum_{n\in S}\frac{1}{n}=1$. 36 | \end{theorem} 37 | \begin{proof} 38 | \leanok 39 | \uses{lem:sieve1,cor:tech_cor,lem:turan} 40 | Let $C\geq 2$ be an absolute constant to be chosen shortly, and for brevity let $\epsilon = \log\log\log N/\log\log N$, so that we may assume that $R(A)\geq C\epsilon \log N$. Since $\sum_{n\leq X}\frac{1}{n}\ll \log X$, if $A'=A\cap [N^\epsilon,N]$ we have (assuming $C$ is sufficiently large) $R(A')\geq \frac{C}{2}\epsilon\log N$. 41 | 42 | Let $X$ be those integers $n\in [1,N]$ not divisible by any prime $p\in [5,(\log N)^{1/1200}]$. Lemma~\ref{lem:sieve1} implies that, for any $x\geq \exp(\sqrt{\log N})$, 43 | \[\abs{X\cap[x,2x)}\ll \frac{x}{\log\log N}\] 44 | and hence, by partial summation, 45 | \[\sum_{\substack{n\in X\\ n\in [\exp(\sqrt{\log N}),N]}}\frac{1}{n}\ll \frac{\log N}{\log\log N}.\] 46 | Similarly, if $Y$ is the set of those $N\in [1,N]$ such that $\omega(n) <\frac{99}{100}\log\log N$ or $\omega(n)\geq \frac{101}{100}\log\log N$ then Tur\'{a}n's estimate Lemma~\ref{lem:turan} 47 | \[\sum_{n\leq x}(\omega(n)-\log\log n)^2\ll x\log\log x\] 48 | implies that $\abs{Y\cap [x,2x)}\ll x/\log\log N$ for any $N\geq x\geq \exp(\sqrt{\log N})$, and so 49 | \[\sum_{\substack{n\in Y\\ n\in [\exp(\sqrt{\log N}),N]}}\frac{1}{n}\ll \frac{\log N}{\log\log N}.\] 50 | In particular, provided we take $C$ sufficiently large, we can assume that $R(A'\backslash (X\cup Y))\geq \frac{C}{4}\epsilon \log N$, say. 51 | 52 | Let $\delta=1-1/\log\log N$, and let $N_i=N^{\delta^i}$, and $A_i=(A'\backslash (X\cup Y))\cap [N_{i+1},N_i]$. Since $N_i\leq N^{e^{-i/\log\log N}}$ and $A'$ is supported on $n\geq N^\epsilon$, the set $A_i$ is empty for $i> \log(1/\epsilon)\log\log N$, and hence by the pigeonhole principle there is some $i$ such that 53 | \[R(A_i)\geq \frac{C}{8}\frac{\epsilon\log N}{(\log\log N)\log(1/\epsilon)}.\] 54 | By construction, $A_i\subset [N_{i+1},N_i]\subset [N_i^{1-1/\log\log N_i},N_i]$, and every $n\in A_i$ is divisible by some prime $p$ with $5\leq p\leq (\log N)^{1/1200}\leq (\log N_i)^{1/500}$. Furthermore, every $n\in A_i$ satisfies $\omega(n)\geq \frac{99}{100}\log\log N\geq \frac{99}{100}\log\log N_i$ and $\omega(n)\leq \frac{101}{99}\log\log N\leq 2\log\log N_i$. 55 | 56 | Finally, it remains to discard the contribution of those $n\in A_i$ divisible by some large prime power $q> N_i^{1-6/\log\log N_i}$. The contribution to $R(A_i)$ of all such $n$ is at most 57 | \[ 58 | \sum_{N_i^{1-6/\log\log N_i}< q\leq N_i}\sum_{\substack{n\leq N_i\\ q\mid n}}\frac{1}{n} 59 | \ll \sum_{N_i^{1-6/\log\log N_i}< q\leq N_i}\frac{\log(N_i/q)}{q}\] 60 | \[\ll \frac{\log N_i}{\log\log N_i}\sum_{N_i^{1-6/\log\log N_i}y\geq 3$. If $X$ is the set of all those integers not divisible by any prime in $p\in [y,z]$ then 94 | \[\abs{ X\cap [N,2N)}\ll \frac{\log y}{\log z}N.\] 95 | \end{lemma} 96 | \begin{proof}\uses{lem:sieve_eratosthenes,lem:mertens2} 97 | \leanok 98 | Lemma~\ref{lem:sieve_eratosthenes} yields 99 | \[\abs{X\cap [N,2N)} = \prod_{y\leq p\leq z}\brac{1-\frac{1}{p}}N+ O(2^z).\] 100 | Mertens' estimate \ref{lem:mertens2} yields 101 | \[\prod_{p\leq z}\brac{1-\frac{1}{p}}^{-1} \gg \log z\] 102 | and 103 | \[\prod_{p\leq y}\brac{1-\frac{1}{p}}^{-1} \ll \log y,\] 104 | whence 105 | \[\prod_{y\leq p\leq z}\brac{1-\frac{1}{p}}^{-1}\gg \frac{\log z}{\log y},\] 106 | and hence 107 | \[ \prod_{y\leq p\leq z}\brac{1-\frac{1}{p}}\ll \frac{\log y}{\log z}.\] 108 | Therefore the first term above is $\ll \frac{\log y}{\log z}N$. The second term is 109 | \[\ll 2^z \leq 2^{\log N}=N^{\log 2}\ll \frac{N}{\log N}\ll \frac{\log y}{\log z}N,\] 110 | and the result follows. 111 | \end{proof} 112 | 113 | 114 | \begin{lemma}[Sieve Estimate 2]\label{lem:sieve2} 115 | \leanok 116 | \lean{sieve_lemma_two} 117 | Let $N$ be sufficiently large and $z,y$ be two parameters such that $(\log N)^{1/2}\geq z>4y\geq 8$. If $Y\subset [1,N]$ is the set of all those integers divisible by at least two distinct primes $p_1,p_2\in [y,z]$ where $4p_1\epsilon>0$ and $N$ be sufficiently large, depending on $\epsilon$. If $A$ is a finite set of integers such that $R(A)\geq (\log N)^{-\epsilon/2}$ and $(1-\epsilon)\log\log N\leq \omega(n)\leq 2\log\log N$ for all $n\in A$ then 24 | \[\sum_{q\in\mathcal{Q}_A}\frac{1}{q} \geq (1-2\epsilon)e^{-1}\log\log N.\] 25 | \leanok 26 | \lean{rec_qsum_lower_bound} 27 | \end{lemma} 28 | \begin{proof} 29 | \leanok 30 | Since, by definition, every integer $n\in A$ can be written uniquely as $q_1\cdots q_t$ for $q_i\in \mathcal{Q}_A$ for some $t\in I = [(1-\epsilon)\log\log N, 2\log\log N]$, we have that, since $t!\geq (t/e)^t$, 31 | \[R(A)\leq \sum_{t\in I}\frac{\brac{\sum_{q\in \mathcal{Q}_A}\frac{1}{q}}^t}{t!}\leq \sum_{t\in I}\brac{\frac{e}{t}\sum_{q\in \mathcal{Q}_A}\frac{1}{q}}^t.\] 32 | Since $(ex/t)^t$ is decreasing in $t$ for $x0$ such that the following holds. Let $00$, since the product converges. Similarly, 55 | \[\prod_{y0$ such that the following holds. Let $N\geq M\geq N^{1/2}$ be sufficiently large, and suppose that $k$ is a real number such that $1\leq k \leq c\log\log N$. Suppose that $A\subset [M,N]$ is a set of integers such that $\omega(n)\leq (\log N)^{1/k}$ for all $n\in A$. 65 | 66 | For all $q$ such that $R(A;q)\geq 1/\log N$ there exists $d$ such that 67 | \begin{enumerate} 68 | \item $qd > M\exp(-(\log N)^{1-1/k})$, 69 | \item $\omega(d)\leq \tfrac{5}{\log k}\log\log N$, and 70 | \item \[\sum_{\substack{n\in A_q\\qd\mid n\\ (qd,n/qd)=1}}\frac{qd}{n}\gg \frac{R(A;q)}{(\log N)^{2/k}}.\] 71 | \end{enumerate} 72 | \end{lemma} 73 | \begin{proof}\uses{lem:smoothsum} 74 | \leanok 75 | Fix some $q$ with $R(A;q)\geq (\log N)^{-1/2}$. Let $y=\exp((\log N)^{1-2/k})$. Let $D$ be the set of all $d$ such that if $r$ is a prime power such that $r\mid d$ and $(r,d/r)=1$ then $yy\}.\] 79 | We let $d=\prod_{r\in Q_n'}r$. We need to check that $d\in D$ and $qd\mid n$. It is immediate from the definitions that if a prime power $r$ divides $d$ with $(r,d/r)=1$ then $r\in Q_n'$, whence $r>y$. It is also straightforward to check, by comparing prime powers, that $qd\mid n$, and hence $qd\leq n\leq N$. Furthermore, 80 | \[\frac{n}{qd}=\prod_{r\in Q_n\backslash Q_n'\cup\{q\}}r\leq y^{\abs{Q_n}}=y^{\omega(n)}\leq \exp((\log N)^{1-1/k}),\] 81 | by definition of $y$ and the hypothesis that $\omega(n)\leq (\log N)^{1/k}$. It follows that $d\in D$ as required. 82 | 83 | If we let $A_q(d)=\{ n \in A_q : qd\mid n\textrm{ and }(qd,n/qd)=1\}$ then we have shown that $A_q\subseteq \bigcup_{d\in D}A_q(d)$. Therefore 84 | \[R(A;q) = \sum_{n\in A_q}\frac{q}{n}\leq \sum_{d\in D}\sum_{n\in A_q(d)}\frac{q}{n}.\] 85 | 86 | We will control the contribution from those $d$ with $\omega(d)>\omega_0= \frac{5}{\log k}\log\log N$ with the trivial bound 87 | \[\sum_{A_q(d)}\frac{q}{n} \leq \sum_{\substack{n\leq N\\ qd\mid n}}\frac{q}{n}\leq \sum_{m\leq N}\frac{q}{dqm}\leq 2\frac{\log N}{d},\] 88 | using the harmonic sum bound $\sum_{m\leq N}\frac{1}{m}\leq \log N+1\leq 2\log N$. 89 | Therefore 90 | \[ 91 | \sum_{\substack{d\in D\\ \omega(d)>\omega_0}}\sum_{n\in A_q(d)}\frac{q}{n} 92 | \leq 2\log N\sum_{\substack{d\in D\\ \omega(d)> \omega_0}} \frac{1}{d}\] 93 | \[\leq 2k^{-\omega_0}\log N\sum_{d\in D} \frac{k^{\omega(d)}}{d}.\] 94 | By \ref{lem:smoothsum} we have 95 | \[\sum_{d\in D}\frac{k^{\omega(d)}}{d}\leq \left(C\frac{\log N}{\log y}\right)^k.\] 96 | and therefore 97 | \[\sum_{\substack{d\in D\\ \omega(d)>\omega_0}}\sum_{n\in A_q(d)}\frac{q}{n}\leq 2k^{-\omega_0}\log N \left(C\frac{\log N}{\log y}\right)^k.\] 98 | Recalling $\omega_0=\frac{5}{\log k}\log\log N$ and $y=\exp((\log N)^{1-2/k})$ the right-hand side here is at most 99 | \[2(\log N)^{-5}C^k\leq 1/2\log N\leq \tfrac{1}{2}R(A;q),\] 100 | for sufficiently large $N$, assuming $k\leq c\log\log N$ for sufficiently small $c$. 101 | 102 | It follows that 103 | \[\tfrac{1}{2}R(A;q)\leq \sum_{\substack{d\in D\\ \omega(d)\leq \omega_0}}\sum_{d\in D}\frac{q}{n} .\] 104 | The result follows by averaging, since by \ref{lem:smoothsum} 105 | \[\sum_{d\in D}\frac{1}{d} \ll \frac{\log N}{\log y}\ll (\log N)^{2/k}.\] 106 | \end{proof} 107 | 108 | \begin{lemma}\label{lem:pisqa} 109 | \leanok 110 | \lean{pruning_lemma_one} 111 | \uses{def:rec_sum,def:rec_sum_local} 112 | Let $N$ be sufficiently large, and let $\epsilon>0$ and $A\subset[1,N]$. There exists $B\subset A$ such that 113 | \[R(B)\geq R(A)-2\epsilon\log\log N\] 114 | and $\epsilon < R(B;q)$ for all $q\in \mathcal{Q}_B$. 115 | \end{lemma} 116 | \begin{proof} 117 | \leanok 118 | We will prove the following claim, valid for any finite set $A\subset \mathbb{N}$ with $0\not\in A$ and $\epsilon>0$, via induction: for all $i\geq 0$ there exists $A_i\subseteq A$ and $Q_i\subseteq \mathcal{Q}_A$ such that 119 | \begin{enumerate} 120 | \item the sets $\mathcal{Q}_{A_i}$ and $Q_i$ are disjoint, 121 | \item $R(A_i)\geq R(A)- \epsilon\sum_{q\in Q_i}\frac{1}{q}$, 122 | \item either $i\leq \abs{A\backslash A_i}$ or, for all $q'\in \mathcal{Q}_{A_i}$, $\epsilon < R(A_i;q')$. 123 | \end{enumerate} 124 | 125 | Given this claim, the stated lemma follows by choosing $B=A_{\abs{A}+1}$, noting that in the 5th point above the first alternative cannot hold, and furthermore 126 | \[\epsilon \sum_{q\in Q_{\abs{A}+1}}\frac{1}{q}\leq \epsilon \sum_{q\leq N}\frac{1}{q}\leq 2\epsilon \log\log N,\] 127 | by Lemma~\ref{lem:mertens1}, assuming $N$ is sufficiently large. 128 | 129 | To prove the inductive claim, we begin by choosing $Q_0=\emptyset$, and $A_0=A$. All of the properties are trivial to verify. 130 | 131 | Suppose the proposition is true for $i\geq 0$, with associated $A_i,Q_i$. We will now prove it for $i+1$. If it is true that, for all $q'\in\mathcal{Q}_{A_i}$, we have $\epsilon M$. Let $\epsilon,\alpha$ be reals such that $\alpha > 4\epsilon\log\log N$ and $A\subset [M,N]$ be a set of integers such that 152 | \[R(A) \geq \alpha+2\epsilon\log\log N\] 153 | and if $q\in\mathcal{Q}_A$ then $q\leq \epsilon M$. 154 | 155 | There is a subset $B\subset A$ such that $R(B)\in [\alpha-1/M,\alpha)$ and, for all $q\in \mathcal{Q}_B$, we have $\epsilon < R(B;q)$. 156 | \end{lemma} 157 | \begin{proof} 158 | \uses{lem:pisqa} 159 | \leanok 160 | We will prove the following, for all $N$ sufficiently large, real $00$ and $\alpha > 4\epsilon\log\log N$ and finite sets $A\subseteq [M,N]$ such that $R(A)\geq \alpha$ and $R(A;q)> \epsilon$ for all $q\in\mathcal{Q}_A$, by induction: for all $i\geq 0$ there exists $A_i\subseteq A$ such that 161 | \begin{enumerate} 162 | \item $R(A_i)\geq \alpha-1/M$, 163 | \item $R(A_i;q) > \epsilon$ for all $q\in\mathcal{Q}_{A_i}$, and 164 | \item either $i\leq \abs{A\backslash A_i}$ or $R(A_i)<\alpha$. 165 | \end{enumerate} 166 | 167 | Given this claim, we prove the lemma as follows. Let $A'\subseteq A$ be as given by Lemma~\ref{lem:pisqa}, so that the hypotheses of the inductive claim are satisfied for $A'$. We now apply the inductive claim, and choose $B=A_{\abs{A}+1}$, noting that the first alternative of point (3) cannot hold. 168 | 169 | It remains to prove the inductive claim. The base case $i=0$ is immediate by hypotheses, choosing $A_0=A$. 170 | 171 | We now fix some $i\geq 0$, with associated $A_i$ as above, and prove the claim for $i+1$. If $R(A_i)<\alpha$ then we set $A_{i+1}=A_i$. Otherwise, we have $R(A_i)\geq \alpha$. By Lemma~\ref{lem:pisqa} there exists $B\subset A_i$ such that 172 | \[R(B)\geq R(A_i)-4\epsilon\log\log N\geq \alpha - 4\epsilon\log\log N>0\] 173 | and $2\epsilon < R(B;q)$ for all $q\in \mathcal{Q}_B$. In particular, since $R(B)>0$, the set $B$ is not empty. Let $x\in B$ be arbitrary, and set $A_{i+1}=A_i\backslash \{x\}$. 174 | 175 | We note that since $x\in B\subseteq A$, we have $x\geq M$, and hence $R(A_{i+1})=R(A_i)-1/x\geq \alpha-1/M$, so point (1) is satisfied. Furthermore, since $R(A_i)\geq \alpha$, we have $i\leq \abs{A\backslash A_i}$, and hence $i+1 \leq \abs{A\backslash A_{i+1}}$ and point (3) is satisfied. 176 | 177 | For point (2), let $q\in \mathcal{Q}_{A_{i+1}}\subseteq \mathcal{Q}_{A_i}$. If it is not true that $q\mid x$ and $(q,x/q)=1$ then 178 | \[R(A_{i+1};q) = R(A_i; q)>\epsilon.\] 179 | Otherwise, if $q\mid x$ and $(q,x/q)=1$, then $q\in\mathcal{Q}_B$. It follows that, since $B\subseteq A_i$, we have 180 | \[R(A_{i+1};q)\geq R(B;q)-\frac{q}{x}>2\epsilon -\frac{q}{M}\geq \epsilon,\] 181 | since $q\leq \epsilon M$. The inductive claim now follows. 182 | \end{proof} 183 | -------------------------------------------------------------------------------- /blueprint/src/techprop.tex: -------------------------------------------------------------------------------- 1 | \chapter{Deduction of main technical proposition} 2 | \label{chap:techprop} 3 | 4 | \begin{lemma}\label{lem:find_multiples} 5 | \leanok 6 | \lean{find_good_x} 7 | \uses{def:interval_rare_ppowers} 8 | Suppose $N$ is sufficiently large and $N\geq M\geq N^{1/2}$, and suppose that $A\subset [M,N]$ is a set of integers such that 9 | \[\tfrac{99}{100}\log\log N\leq \omega(n)\leq 2\log\log N\quad\textrm{for all}\quad n\in A.\] 10 | Then for any interval of length $\leq MN^{-2/(\log \log N)}$, if $A_I$ is the set of those $n\in A$ which divide some element of $I$, for all $q\in\mathcal{Q}_A$ such that $R(A_I;q)> 1/2(\log N)^{1/100}$ there exists some integer $x_q\in I$ such that $q\mid x_q$ and 11 | \[\sum_{\substack{r\mid x_q\\ r\in \mathcal{Q}_A}}\frac{1}{r}\geq 0.35\log\log N.\] 12 | \end{lemma} 13 | \begin{proof} 14 | \uses{lem:usingq,lem:rtop} 15 | \leanok 16 | Let $I$ be any interval of length $\leq MN^{-2/(\log\log N)}$, and let $q\in\mathcal{Q}_A$ such that $R(A_I;q)> 1/2(\log N)^{1/100}$. 17 | 18 | Apply Lemma~\ref{lem:usingq} with $A$ replaced by $A_I$, and $k=\frac{\log\log N}{\log 2+\log\log\log N}$, so that $(\log N)^{1/k}=2\log\log N$. We choose $N$ large enough such that $k\leq c\log\log N$ (where $c$ is the constant in the statement of Lemma~\ref{lem:usingq}) and such that $\log k\geq 5000$. 19 | 20 | This produces some $d_q$ such that $qd_q>\abs{I}$ and $\omega(d_q)<\tfrac{1}{1000}\log\log N$, and 21 | \[\sum_{\substack{n\in A_I\\ qd_q\mid n\\ (qd_q,n/qd_q)=1}}\frac{qd_q}{n}\gg \frac{1}{(\log N)^{1/100}(\log\log N)^2}\geq \frac{1}{(\log N)^{1/99}},\] 22 | assuming $N$ is sufficiently large. Let 23 | \[A_I^{(q)}=\{ n/qd_q : n\in A_I\textrm{ with }qd_q\mid n\textrm{ and }(qd_q,n/qd_q)=1\}\] 24 | so that, the above inequality states that $R(A_I^{(q)})\geq (\log N)^{-1/99}$. 25 | 26 | We now claim that $2\log\log N\geq \omega(m) \geq \tfrac{97}{99}\log\log N$ for all $m\in A_I^{(q)}$. This follows from the trivial $\omega(mqd_q)\geq \omega(m)\geq \omega(mqd_q)-\omega(qd_q)$, and that $2\log\log N\geq \omega(mqd_q)\geq \frac{99}{100}\log\log N$ (since $mqd_q\in A$) and $\omega(qd_q)\leq 1+\omega(d_q)<\frac{1}{500}\log\log N$. 27 | 28 | We now apply Lemma~\ref{lem:rtop} with $\epsilon=2/99$. This implies that 29 | \[\sum_{r\in \mathcal{Q}_{A_I^{(q)}}}\frac{1}{r}\geq \frac{95}{99}e^{-1}\log\log N\geq 0.35\log\log N.\] 30 | 31 | 32 | By definition of $A_I$, every $n\in A_I$ with $qd_q\mid n$ must divide some $x\in I$, say $x(n)$. We claim that $x(n)=x(m)$ for all $n,m\in A_I$ with $qd_q\mid n$ and $qd_q\mid m$. Otherwise $\abs{x(q,n)-x(q,m)}$ is a non-zero multiple of $qd_q$, so $\abs{I} \delta.\] 49 | \end{lemma} 50 | \begin{proof} 51 | \leanok 52 | For every $q\in \mathcal{D}_I(A;\delta M)$, by definition, 53 | \[\#\{ n\in A_q : n\not\in A_I\} < \frac{\delta M}{q}.\] 54 | Therefore 55 | \[R(A_I;q) = \sum_{\substack{n \in A_q\\n\in A_I}}\frac{q}{n}> \sum_{n \in A_q}\frac{q}{n}-\frac{q}{M}\brac{\frac{\delta M}{q}}.\] 56 | \[=R(A;q) - \delta \geq \delta.\] 57 | \end{proof} 58 | 59 | 60 | \begin{proposition}\label{prop:tech_iterative} 61 | \leanok 62 | \lean{force_good_properties} 63 | Suppose $N$ is sufficiently large and $N\geq M\geq N^{1/2}$, and suppose that $A\subset [M,N]$ is a set of integers such that 64 | \[\tfrac{99}{100}\log\log N\leq \omega(n)\leq 2\log\log N\quad\textrm{for all}\quad n\in A,\] 65 | \[R(A)\geq (\log N)^{-1/101}\] 66 | and, for all $q\in \mathcal{Q}_A$, 67 | \[R(A;q) \geq (\log N)^{-1/100}.\] 68 | Then either 69 | \begin{enumerate} 70 | \item there is some $B\subset A$ such that $R(B)\geq \tfrac{1}{3}R(A)$ and 71 | \[\sum_{q\in \mathcal{Q}_{B}}\frac{1}{q}\leq \frac{2}{3}\log\log N,\] 72 | or 73 | \item for any interval of length $\leq MN^{-2/(\log \log N)}$, either 74 | \begin{enumerate} 75 | \item \[\# \{ n\in A : \textrm{no element of }I\textrm{ is divisible by }n\}\geq M/\log N,\] 76 | or 77 | \item there is some $x\in I$ divisible by all $q\in\mathcal{D}_I(A;M/2(\log N)^{1/100})$. 78 | \end{enumerate} 79 | \end{enumerate} 80 | \end{proposition} 81 | \begin{proof} 82 | \leanok 83 | \uses{lem:find_multiples,lem:good_d,lem:basic,lem:divisor_bound} 84 | Let $I$ be any interval of length $\leq MN^{-2/(\log\log N)}$, and let $A_I$ be those $n\in A$ that divide some element of $I$, and $\mathcal{D}=\mathcal{D}_I(A;M/2(\log N)^{1/100})$. We may assume that $\abs{A\backslash A_I}< M/\log N$. 85 | 86 | Let $\mathcal{E}$ be the set of those $q\in\mathcal{Q}_A$ such that $R(A_I;q)> 1/2(\log N)^{1/100}$, so that by Lemma~\ref{lem:good_d} we have $\mathcal{D}\subset \mathcal{E}$. By Lemma~\ref{lem:find_multiples} for each $q\in\mathcal{E}$ there exists $x_q\in I$ such that $q\mid x_q$ and 87 | \[\sum_{\substack{r\mid x_q\\ r\in \mathcal{Q}_A}}\frac{1}{r}\geq 0.35\log\log N.\] 88 | 89 | 90 | Let $X=\{x_q : q\in \mathcal{E}\}$. Suppose that $\abs{X}\geq 3$, and say $x,y,z\in X$ are three distinct elements. Then 91 | \[\sum_{q\in\mathcal{Q}_A}\frac{1}{q}\geq \sum_{\substack{q\mid x\\ q\in \mathcal{Q}_A}}\frac{1}{q}+\sum_{\substack{q\mid y\\ q\in \mathcal{Q}_A}}\frac{1}{q}+\sum_{\substack{q\mid z\\ q\in \mathcal{Q}_A}}\frac{1}{q}-\sum_{q\mid (x,y)}\frac{1}{q}-\sum_{q\mid (y,z)}\frac{1}{q}-\sum_{q\mid (x,z)}\frac{1}{q},\] 92 | where the last three sums are restricted to prime powers. 93 | 94 | Since $\sum_{q\in\mathcal{Q}_A}\frac{1}{q}\leq (1+o(1))\log\log N\leq 1.01\log\log N$, say, by Lemma~\ref{lem:mertens1}, it follows that 95 | \[\sum_{q\mid (x,y)}\frac{1}{q}+\sum_{q\mid (y,z)}\frac{1}{q}+\sum_{q\mid (x,z)}\frac{1}{q}\geq 0.04\log\log N.\] 96 | 97 | But since $x,y\in I$ we have, by Lemma~\ref{lem:basic}, 98 | \[\sum_{q\mid (x,y)}\frac{1}{q}\ll \log\log\log N,\] 99 | and similarly for the other sums, and so the left-hand side is $O(\log\log\log N)$, which is a contradiction for large enough $N$. 100 | 101 | Therefore $\abs{X}\leq 2$. If $\mathcal{D}$ is empty the second conclusion trivially holds, and therefore we may assume there is some $q\in \mathcal{E}$ and hence some $x_q\in X$, so $\abs{X}\geq 1$. If $\abs{X}=1$ then we are in the second conclusion, letting $x$ be the unique element of $X$, since by construction $x=x_q$ for all $q\in \mathcal{D}$, and hence in particular $q\mid x$ for all $q\in \mathcal{D}_I$ as required. 102 | 103 | Finally, we deal with the case $\abs{X}=2$. Say $X=\{w_1,w_2\}$ with $w_1\neq w_2$ (and both are elements of $I$). Let $A^{(i)}=\{n\in A: n\mid w_i\}$ and $A^{(0)}=A\backslash (A^{(1)}\cup A^{(2)})$. Without loss of generality, label the $w_i$ such that $R(A^{(1)})\geq R(A^{(2)})$. Suppose first that $R(A^{(0)})\epsilon$, and there is a multiple of $d$ in $A'$, and there are no multiples of any $m\in [y,d)$ in $A$. 172 | \end{lemma} 173 | \begin{proof} 174 | \leanok 175 | \uses{lem:pisq} 176 | In the proof below, we write $t_i=\min(\lceil y\rceil +i, \lfloor w\rfloor)$ for all integer $i\geq 0$ for simplicity. It is convenient to note at the outset that $t_0=\lceil y\rceil$, $t_i\leq w$ for all $i$, for all $i\geq 0$ we have $t_{i+1}\in [t_i,t_i+1]$, and if $t_i< \lfloor w\rfloor$ then $t_{i+1}=t_i+1$. Furthermore, if $i\geq \lfloor w\rfloor -\lceil y\rceil$, then $t_i=\lfloor w\rfloor$. 177 | 178 | We will prove by induction on $i$ that, under the same hypotheses as in the lemma, for all $0\leq i$ there exists $ A_i\subseteq A$ and integer $d_i$ with $y\leq d_i\leq t_i$ such that 179 | \begin{enumerate} 180 | \item $R(A_i) \in [2/d_i-1/M, 2/d_i)$, 181 | \item for all $q\in \mathcal{Q}_{A_i}$ we have $R(A_i;q)> \epsilon$, 182 | \item there are no multiples of any $m\in [y,d_i)$ in $A$, and 183 | \item either there exists a multiple of $d_i$ in $A_i$, or nothing in $A_i$ is divisible by any $d\in [y,t_i]$. 184 | \end{enumerate} 185 | 186 | Given this inductive claim, the lemma follows by letting $A' = A_{\lfloor w\rfloor -\lceil y\rceil}$ and $d=d_{\lfloor w\rfloor -\lceil y\rceil}$, so that then $t_{\lfloor w\rfloor -\lceil y\rceil}=\lfloor w\rfloor$, noting that the assumptions imply that $2/d-1/M\geq 2/w-1/M>0$ and hence $R(A')>0$ and so $A'\neq\emptyset$, and furthermore by assumption the second alternative of point (3) cannot hold. It remains to prove the inductive claim. 187 | 188 | For the base case $i=0$, we set $d_0=\lceil y\rceil$ and apply Lemma~\ref{lem:pisq} with $\alpha=2/d_0$ to find some $A_0\subseteq A$ such that $R(A_0)\in[2/d_0-1/M,2/d_0)$ and for all $q\in \mathcal{Q}_{A_0}$ we have $\epsilon < R(A_0;q)$. (To see that point (4) holds, note that $d_0$ is the unique integer in $[y,t_0]$.) 189 | 190 | For the inductive step, suppose that $A_i,d_i$ are as given for $i\geq 0$. If there exists a multiple of $d_i$ in $A_i$, then we set $d_{i+1}=d_i$ and $A_{i+1}=A_i$. 191 | 192 | If not, then nothing in $A_i$ is divisible by any $d\in [y,t_i]$. We now set $d_{i+1}=t_{i+1}$ and apply Lemma~\ref{lem:pisq} to $A_i$ with $\alpha=2/d_{i+1}$. To be able to apply this, we need to verify that 193 | \[\alpha=2/d_{i+1}> 4\epsilon\log\log N\] 194 | and 195 | \[R(A_i)\geq \alpha+2\epsilon\log\log N= 2/d_{i+1}+2\epsilon\log\log N.\] 196 | For the first, we note that $d_{i+1}\leq w$, and hence we are done since $2/w>4/w^2\geq 6\epsilon\log\log N$. 197 | 198 | For the second, we note that by assumption, every $n\in A$ is divisible by some $d\in [y,w]$, and hence since we are assuming that nothing in $A_i$ is divisible by any $d\in [y,t_i]$, we must have $t_i<\lfloor w\rfloor$, and hence $d_{i+1}=t_{i+1}=t_i+1\geq d_i+1$. Therefore 199 | \[R(A_i)\geq \frac{2}{d_i}-\frac{1}{M}\geq \frac{2}{d_{i+1}-1}-\frac{1}{M}\geq \frac{2}{d_{i+1}-1}-\epsilon\log\log N,\] 200 | since $1/M \leq \epsilon\log\log N$, and furthermore 201 | \[\frac{2}{d_{i+1}-1}-\frac{2}{d_{i+1}}=\frac{2}{d_{i+1}(d_{i+1}-1)}\geq \frac{2}{d_{i+1}^2}\geq \frac{2}{w^2}\geq 3\epsilon\log\log N,\] 202 | and hence $R(A_i)\geq \alpha+2\epsilon\log\log N$ as required. 203 | 204 | Thus we can apply Lemma~\ref{lem:pisq}, to produce some $A_{i+1}\subseteq A_i$ such that $R(A_{i+1})\in [2/d_{i+1}-1/M,2/d_{i+1})$, such that for all $q\in \mathcal{Q}_{A_{i+1}}$ we have $R(A_{i+1};q)>\epsilon$. Furthermore, if there is something in $A_{i+1}$ divisible by some $d\in [y,t_{i+1}]$, then since $A_{i+1}\subseteq A_i$ there must be something in $A_{i+1}$ divisible by some $d\in [y,t_{i+1}]\backslash [y,t_i]$. Since $t_{i+1}\in [t_i,t_i+1]$, the only integer that could be in $[y,t_{i+1}]\backslash [y,t_i]$ is $t_{i+1}=d_{i+1}$, and the proof is complete. 205 | \end{proof} 206 | 207 | \begin{proposition}[Main Technical Proposition]\label{prop:techmain} 208 | \leanok 209 | \lean{technical_prop} 210 | Let $N$ be sufficiently large. Suppose $A\subset [N^{1-1/\log\log N},N]$ and $1\leq y\leq z\leq (\log N)^{1/500}$ are such that 211 | \begin{enumerate} 212 | \item $R(A)\geq 2/y+(\log N)^{-1/200}$, 213 | \item every $n\in A$ is divisible by some $d_1$ and $d_2$ where $y\leq d_1$ and $4d_1\leq d_2\leq z$, 214 | \item every prime power $q$ dividing some $n\in A$ satisfies $q\leq N^{1-6/\log\log N}$, and 215 | \item every $n\in A$ satisfies 216 | \[\tfrac{99}{100}\log\log N\leq \omega(n) \leq 2\log\log N.\] 217 | \end{enumerate} 218 | There is some $S\subset A$ such that $R(S)=1/d$ for some $d\in [y,z]$. 219 | \end{proposition} 220 | \begin{proof} 221 | \leanok 222 | \uses{prop:tech_iterative,lem:techmainprec,prop:fourier,prop:tech_iterative2} 223 | Let $M=N^{1-1/\log\log N}$. Apply Lemma~\ref{lem:techmainprec} with $w=z/4$ and $\epsilon=N^{-5/\log\log N}$ to find some corresponding $A'$ and $d$. 224 | 225 | Suppose first that case (2) of Proposition~\ref{prop:tech_iterative} holds for $A'$. The hypotheses of Proposition~\ref{prop:fourier} are now met with $k=d$, $\eta=1/2(\log N)^{1/100}$, and $K=MN^{-2/\log \log N}$. This yields some $S\subset A'\subset A$ such that $R(S)=1/d_j$ as required. 226 | 227 | Otherwise, Proposition~\ref{prop:tech_iterative} yields some $B\subset A'$ such that 228 | \[R(B)\geq 2/3d_j-1/M\geq 1/2d_j+(\log N)^{-1/200}\] 229 | and where $\sum_{q\in\mathcal{Q}_B}\frac{1}{q}\leq \frac{2}{3}\log\log N$. 230 | 231 | We apply Lemma~\ref{lem:techmainprec} again, with $y=4d$ and $w=z$, to produce some corresponding $B'\subset B$ and $d'\in [4d,z]$. Since $\sum_{q\in \mathcal{Q}_{B'}}\frac{1}{q}\leq \sum_{q\in\mathcal{Q}_B}\frac{1}{q}\leq \frac{2}{3}\log\log N$ we can apply Proposition~\ref{prop:tech_iterative2}. The hypotheses of Proposition~\ref{prop:fourier} are now met with $k=d'$ and $\eta,K$ as above, and thus there is some $S\subset B'\subset A$ such that $R(S)=1/d'$ as required. 232 | \end{proof} 233 | -------------------------------------------------------------------------------- /blueprint/src/web.tex: -------------------------------------------------------------------------------- 1 | \documentclass{report} 2 | 3 | \usepackage{amsmath,amsfonts,amsthm,amssymb} 4 | \usepackage{hyperref} 5 | \usepackage{graphicx} 6 | \DeclareGraphicsExtensions{.svg,.png,.jpg} 7 | \usepackage[capitalize]{cleveref} 8 | \usepackage[showmore, dep_graph, coverage, project=../../]{blueprint} 9 | 10 | \usepackage{tikz-cd} 11 | \usepackage{tikz} 12 | 13 | \input{macros_common} 14 | \input{macros_web} 15 | 16 | \home{https://b-mehta.github.io/unit-fractions/} 17 | \github{https://github.com/b-mehta/unit-fractions/} 18 | 19 | \title{Unit Fractions} 20 | \author{Thomas F. Bloom and Bhavik Mehta} 21 | 22 | \begin{document} 23 | \maketitle 24 | \input{content} 25 | \end{document} 26 | -------------------------------------------------------------------------------- /blueprint/tasks.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | import http.server 4 | import socketserver 5 | 6 | from invoke import run, task 7 | 8 | BP_DIR = Path(__file__).parent 9 | 10 | @task 11 | def print(ctx): 12 | cwd = os.getcwd() 13 | os.chdir(BP_DIR) 14 | run('mkdir -p print && cd src && xelatex -output-directory=../print print.tex') 15 | os.chdir(cwd) 16 | 17 | @task 18 | def bp(ctx): 19 | cwd = os.getcwd() 20 | os.chdir(BP_DIR) 21 | run('mkdir -p print && cd src && xelatex -output-directory=../print print.tex') 22 | run('cd src && xelatex -output-directory=../print print.tex') 23 | os.chdir(cwd) 24 | 25 | 26 | @task 27 | def web(ctx): 28 | cwd = os.getcwd() 29 | os.chdir(BP_DIR/'src') 30 | run('plastex -c plastex.cfg web.tex') 31 | os.chdir(cwd) 32 | 33 | @task 34 | def serve(ctx): 35 | cwd = os.getcwd() 36 | os.chdir(BP_DIR/'web') 37 | Handler = http.server.SimpleHTTPRequestHandler 38 | httpd = socketserver.TCPServer(("", 8000), Handler) 39 | httpd.serve_forever() 40 | os.chdir(cwd) 41 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /docs/blueprint.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b-mehta/unit-fractions/10ef71a300cf29e5f19beb2bbc723a035a0678de/docs/blueprint.pdf -------------------------------------------------------------------------------- /docs/blueprint/chap-def.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 12 | 13 | 14 | 15 | Definitions 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |

Unit Fractions

29 |
30 | 31 |
32 | 78 | 79 |
80 |
81 | 82 | 83 |
84 |

1 Definitions

85 | 86 |

Some definitions, local to this paper, that occur frequently.

87 |

88 |
89 | 90 | Definition 91 | 92 | 1.1 93 | ✓ 94 |
95 | # 96 | 97 | 110 | 111 |
112 |
113 |
114 |

For any finite \(A\subset \mathbb {N}\)

115 |
116 | \[ R(A)=\sum _{n\in A}\frac{1}{n}. \] 117 |
118 | 119 |
120 |

121 |

122 |
123 | 124 | Definition 125 | 126 | 1.2 127 | ✓ 128 |
129 | # 130 | 131 | 144 | 145 |
146 |
147 |
148 |

For any finite \(A\subset \mathbb {N}\) and prime power \(q\) we define

149 |
150 | \[ A_q = \{ n\in A : q\mid n\textrm{ and }(q,n/q)=1\} \] 151 |
152 |

and let \(\mathcal{Q}_A\) be the set of all prime powers \(q\) such that \(A_q\) is non-empty (i.e. those \(p^r\) such that \(p^r\| n\) for some \(n\in A\)).

153 | 154 |
155 |

156 |

157 |
158 | 159 | Definition 160 | 161 | 1.3 162 | ✓ 163 |
164 | # 165 | 167 | 180 | 181 | 194 | 195 |
196 |
197 |
198 |

For any finite \(A\subset \mathbb {N}\) and prime power \(q\in \mathcal{Q}_A\) we define

199 |
200 | \[ R(A;q) = \sum _{n\in A_q}\frac{q}{n}. \] 201 |
202 | 203 |
204 |

205 |

206 |
207 | 208 | Definition 209 | 210 | 1.4 211 | ✓ 212 |
213 | # 214 | 216 | 229 | 230 | 243 | 244 |
245 |
246 |
247 |

For any finite set \(A\subset \mathbb {N}\), \(K\in \mathbb {R}\) and interval \(I\), we define \(\mathcal{D}_I(A;K)\) to be the set of those \(q\in \mathcal{Q}_A\) such that

248 |
249 | \[ \# \{ n\in A_q: \textrm{no element of }I\textrm{ is divisible by }n\} \ {\lt}\ K / q. \] 250 |
251 | 252 |
253 |

254 | 255 |
256 |
257 |
258 |
259 | 260 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | -------------------------------------------------------------------------------- /docs/blueprint/coverage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 16 | 17 | Formalization status 18 | 19 | 20 | 21 |
22 |
23 | Home 24 |

Formalization status

25 |
26 | 27 |
28 | 29 |

Completion report

30 | 31 | Click chapter titles to see missing items. 32 | 33 | 34 |
35 |

Introduction 100%

36 | 37 |
38 | 39 |
40 |

1 Definitions 100%

41 | 42 |
43 | 44 |
45 |

2 Basic Estimates 100%

46 | 47 |
48 | 49 |
50 |

3 Deduction of the main results 80%

51 | 52 |
    53 | 54 | 55 | 56 | 57 |
  • 58 |
    Theorem 3.2 (th:log_density_theorem)
    59 |

    There is a constant \(C{\gt}0\) such that the following holds. If \(A\subset \{ 1,\ldots ,N\} \) and

    60 |
    61 | \[ \sum _{n\in A}\frac{1}{n}\geq C \frac{\log \log \log N}{\log \log N}\log N \] 62 |
    63 |

    then there is an \(S\subset A\) such that \(\sum _{n\in S}\frac{1}{n}=1\).

    64 |
    65 |
  • 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
75 | 76 |
77 | 78 |
79 |

4 Fourier Analysis 100%

80 | 81 |
82 | 83 |
84 |

5 Technical Lemmas 100%

85 | 86 |
87 | 88 |
89 |

6 Deduction of main technical proposition 100%

90 | 91 |
92 | 93 | 94 |

What to define next?

95 | 96 | 97 |
98 | 99 |
100 | 101 |
102 | 103 |
104 | 105 |
106 | 107 |
108 | 109 |
110 | 111 |
112 | 113 |
114 | 115 |
116 | 117 |
118 | 119 |
120 | 121 |
122 | 123 |
124 | 125 | 126 |

What to state next?

127 | 128 | 129 |
130 | 131 |
132 | 133 |
134 | 135 |
136 | 137 |
138 | 139 |
140 | 141 |
142 | 143 |
144 | 145 |
146 | 147 |
148 | 149 |
150 | 151 |
152 | 153 |
154 | 155 |
156 | 157 | 158 |

What to prove next?

159 | 160 | 161 |
162 | 163 |
164 | 165 |
166 | 167 |
168 | 169 |
170 | 171 |
172 | 173 |
174 | 175 |

3 Deduction of the main results

176 |
    177 | 178 |
  • 179 |
    Theorem 3.2 (th:log_density_theorem)
    180 |

    There is a constant \(C{\gt}0\) such that the following holds. If \(A\subset \{ 1,\ldots ,N\} \) and

    181 |
    182 | \[ \sum _{n\in A}\frac{1}{n}\geq C \frac{\log \log \log N}{\log \log N}\log N \] 183 |
    184 |

    then there is an \(S\subset A\) such that \(\sum _{n\in S}\frac{1}{n}=1\).

    185 |
    186 |
  • 187 | 188 |
189 | 190 |
191 | 192 |
193 | 194 |
195 | 196 |
197 | 198 |
199 | 200 |
201 | 202 |
203 | 204 | 205 |
206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /docs/blueprint/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 12 | 13 | 14 | 15 | Unit Fractions 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 |
27 | 28 |
29 | 75 | 76 |
77 |
78 | 79 | 80 |
81 |
82 |

Unit Fractions

83 |

84 | Thomas F. Bloom and Bhavik Mehta 85 |

86 |
87 |
88 | 131 |
132 |
133 |
134 | 135 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /docs/blueprint/js/coverage.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $("div.thm_thmheading").click( 3 | function() { 4 | $(this).siblings("div.thm_thm_content").slideToggle() 5 | }) 6 | $("section h3").click( 7 | function() { 8 | $(this).siblings("ul.coverage").slideToggle() 9 | }) 10 | }); 11 | 12 | -------------------------------------------------------------------------------- /docs/blueprint/js/expatlib.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b-mehta/unit-fractions/10ef71a300cf29e5f19beb2bbc723a035a0678de/docs/blueprint/js/expatlib.wasm -------------------------------------------------------------------------------- /docs/blueprint/js/graphvizlib.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b-mehta/unit-fractions/10ef71a300cf29e5f19beb2bbc723a035a0678de/docs/blueprint/js/graphvizlib.wasm -------------------------------------------------------------------------------- /docs/blueprint/js/js.cookie.min.js: -------------------------------------------------------------------------------- 1 | /*! js-cookie v3.0.1 | MIT */ 2 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self,function(){var n=e.Cookies,o=e.Cookies=t();o.noConflict=function(){return e.Cookies=n,o}}())}(this,(function(){"use strict";function e(e){for(var t=1;t' 10 | }; 11 | 12 | $("#toc-toggle").click(function() { 13 | $("nav.toc").toggle() 14 | }); 15 | 16 | $("nav.toc").on("click", "span.expand-toc", 17 | function() { 18 | $(this).siblings("ul").slideToggle('fast'); 19 | 20 | if ($(this).html() == "▼") { 21 | $(this).html("▶"); 22 | } else { 23 | $(this).html("▼"); 24 | }; 25 | 26 | }) 27 | 28 | 29 | $("div.proof_content p:last").append('') 30 | 31 | $("div.proof_heading").click( 32 | function() { 33 | var expand_span = $(this).children('span.expand-proof'); 34 | if ($(expand_span).html() == "▼") { 35 | $(expand_span).html("▶"); 36 | } else { 37 | $(expand_span).html("▼"); 38 | }; 39 | 40 | $(this).siblings("div.proof_content").slideToggle() 41 | }) 42 | 43 | $("a.proof").click( 44 | function() { 45 | var ref= $(this).attr('href').split('#')[1]; 46 | var proof = $('#'+ref) 47 | proof.show() 48 | proof.children('.proof_content').each( 49 | function() { 50 | var proof_content = $(this) 51 | proof_content.show().addClass('hilite') 52 | setTimeout(function(){ 53 | proof_content.removeClass('hilite') 54 | }, 1000); 55 | }) 56 | var expand_icon = proof.find('svg.expand-proof'); 57 | expand_icon.replaceWith(icon('cross', 'expand-proof')); 58 | }) 59 | 60 | 61 | $("button.modal").click( 62 | function() { 63 | $(this).next("div.modal-container").css('display', 'flex'); 64 | }) 65 | $("button.closebtn").click( 66 | function() { 67 | $(this).parent().parent().parent().hide(); 68 | }) 69 | }); 70 | -------------------------------------------------------------------------------- /docs/blueprint/js/showmore.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | showmore_update = function(showmore_level) { 3 | Cookies.set('showmore_level', showmore_level, { expires : 10, SameSite: "Lax" }); 4 | console.log('update', showmore_level); 5 | switch(showmore_level) { 6 | case 0: 7 | $("svg#showmore-minus").hide(); 8 | $("figure").hide(); 9 | $("svg#showmore-plus").show(); 10 | $("div.main-text > p").each( 11 | function(){ 12 | $(this).hide(); 13 | }); 14 | $("div.proof_wrapper").each( 15 | function(){ 16 | $(this).hide(); 17 | }); 18 | $("footer").hide(); 19 | break; 20 | case 1: 21 | $("svg#showmore-minus").show(); 22 | $("figure").show(); 23 | $("div.proof_wrapper").each( 24 | function(){ 25 | $(this).show(); 26 | }); 27 | $("svg#showmore-plus").show(); 28 | $("div.main-text > p").each( 29 | function(){ 30 | $(this).show(); 31 | }); 32 | $("div.proof_content").each( 33 | function(){ 34 | $(this).hide(); 35 | }); 36 | $("svg.expand-proof").show(); 37 | $("footer").show(); 38 | break; 39 | case 2: 40 | $("svg#showmore-minus").show(); 41 | $("svg#showmore-plus").hide(); 42 | $("div.main-text > p").each( 43 | function(){ 44 | $(this).show(); 45 | }); 46 | $("div.proof_wrapper").each( 47 | function(){ 48 | $(this).show(); 49 | }); 50 | $("div.proof_content").each( 51 | function(){ 52 | $(this).show(); 53 | }); 54 | $("svg.expand-proof").hide(); 55 | } 56 | }; 57 | 58 | cookie_level = function(){ 59 | var showmore_level = parseInt(Cookies.get('showmore_level')); 60 | 61 | if (isNaN(showmore_level)) { 62 | return 1; 63 | } else { 64 | return showmore_level; 65 | } 66 | }; 67 | showmore_update(cookie_level()); 68 | 69 | $("svg#showmore-minus").click( 70 | function() { 71 | var showmore_level = cookie_level(); 72 | console.log('click ', showmore_level); 73 | if (showmore_level > 0) { 74 | showmore_level -= 1; 75 | showmore_update(showmore_level); 76 | } 77 | }) 78 | 79 | $("svg#showmore-plus").click( 80 | function() { 81 | var showmore_level = cookie_level(); 82 | console.log('click ', showmore_level); 83 | if (showmore_level < 2) { 84 | showmore_level += 1; 85 | showmore_update(showmore_level); 86 | } 87 | }) 88 | }) 89 | -------------------------------------------------------------------------------- /docs/blueprint/js/svgxuse.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * @copyright Copyright (c) 2016 IcoMoon.io 3 | * @license Licensed under MIT license 4 | * See https://github.com/Keyamoon/svgxuse 5 | * @version 1.1.20 6 | */ 7 | /*jslint browser: true */ 8 | /*global XDomainRequest, MutationObserver, window */ 9 | (function () { 10 | 'use strict'; 11 | if (window && window.addEventListener) { 12 | var cache = Object.create(null); // holds xhr objects to prevent multiple requests 13 | var checkUseElems; 14 | var tid; // timeout id 15 | var debouncedCheck = function () { 16 | clearTimeout(tid); 17 | tid = setTimeout(checkUseElems, 100); 18 | }; 19 | var unobserveChanges = function () { 20 | return; 21 | }; 22 | var observeChanges = function () { 23 | var observer; 24 | window.addEventListener('resize', debouncedCheck, false); 25 | window.addEventListener('orientationchange', debouncedCheck, false); 26 | if (window.MutationObserver) { 27 | observer = new MutationObserver(debouncedCheck); 28 | observer.observe(document.documentElement, { 29 | childList: true, 30 | subtree: true, 31 | attributes: true 32 | }); 33 | unobserveChanges = function () { 34 | try { 35 | observer.disconnect(); 36 | window.removeEventListener('resize', debouncedCheck, false); 37 | window.removeEventListener('orientationchange', debouncedCheck, false); 38 | } catch (ignore) {} 39 | }; 40 | } else { 41 | document.documentElement.addEventListener('DOMSubtreeModified', debouncedCheck, false); 42 | unobserveChanges = function () { 43 | document.documentElement.removeEventListener('DOMSubtreeModified', debouncedCheck, false); 44 | window.removeEventListener('resize', debouncedCheck, false); 45 | window.removeEventListener('orientationchange', debouncedCheck, false); 46 | }; 47 | } 48 | }; 49 | var createRequest = function (url) { 50 | // In IE 9, cross domain requests can only be sent using XDomainRequest. 51 | // XDomainRequest would fail if CORS headers are not set. 52 | // Therefore, XDomainRequest should only be used with cross domain requests. 53 | function getHostname(href) { 54 | var a = document.createElement('a'); 55 | a.href = href; 56 | return a.hostname; 57 | } 58 | var Request; 59 | var hname = location.hostname; 60 | var hname2; 61 | if (window.XMLHttpRequest) { 62 | Request = new XMLHttpRequest(); 63 | hname2 = getHostname(url); 64 | if (Request.withCredentials === undefined && hname2 !== '' && hname2 !== hname) { 65 | Request = XDomainRequest || undefined; 66 | } else { 67 | Request = XMLHttpRequest; 68 | } 69 | } 70 | return Request; 71 | }; 72 | var xlinkNS = 'http://www.w3.org/1999/xlink'; 73 | checkUseElems = function () { 74 | var base; 75 | var bcr; 76 | var fallback = ''; // optional fallback URL in case no base path to SVG file was given and no symbol definition was found. 77 | var hash; 78 | var i; 79 | var inProgressCount = 0; 80 | var isHidden; 81 | var Request; 82 | var url; 83 | var uses; 84 | var xhr; 85 | function observeIfDone() { 86 | // If done with making changes, start watching for chagnes in DOM again 87 | inProgressCount -= 1; 88 | if (inProgressCount === 0) { // if all xhrs were resolved 89 | unobserveChanges(); // make sure to remove old handlers 90 | observeChanges(); // watch for changes to DOM 91 | } 92 | } 93 | function attrUpdateFunc(spec) { 94 | return function () { 95 | if (cache[spec.base] !== true) { 96 | spec.useEl.setAttributeNS(xlinkNS, 'xlink:href', '#' + spec.hash); 97 | } 98 | }; 99 | } 100 | function onloadFunc(xhr) { 101 | return function () { 102 | var body = document.body; 103 | var x = document.createElement('x'); 104 | var svg; 105 | xhr.onload = null; 106 | x.innerHTML = xhr.responseText; 107 | svg = x.getElementsByTagName('svg')[0]; 108 | if (svg) { 109 | svg.setAttribute('aria-hidden', 'true'); 110 | svg.style.position = 'absolute'; 111 | svg.style.width = 0; 112 | svg.style.height = 0; 113 | svg.style.overflow = 'hidden'; 114 | body.insertBefore(svg, body.firstChild); 115 | } 116 | observeIfDone(); 117 | }; 118 | } 119 | function onErrorTimeout(xhr) { 120 | return function () { 121 | xhr.onerror = null; 122 | xhr.ontimeout = null; 123 | observeIfDone(); 124 | }; 125 | } 126 | unobserveChanges(); // stop watching for changes to DOM 127 | // find all use elements 128 | uses = document.getElementsByTagName('use'); 129 | for (i = 0; i < uses.length; i += 1) { 130 | try { 131 | bcr = uses[i].getBoundingClientRect(); 132 | } catch (ignore) { 133 | // failed to get bounding rectangle of the use element 134 | bcr = false; 135 | } 136 | url = uses[i].getAttributeNS(xlinkNS, 'href').split('#'); 137 | base = url[0]; 138 | hash = url[1]; 139 | isHidden = bcr && bcr.left === 0 && bcr.right === 0 && bcr.top === 0 && bcr.bottom === 0; 140 | if (bcr && bcr.width === 0 && bcr.height === 0 && !isHidden) { 141 | // the use element is empty 142 | // if there is a reference to an external SVG, try to fetch it 143 | // use the optional fallback URL if there is no reference to an external SVG 144 | if (fallback && !base.length && hash && !document.getElementById(hash)) { 145 | base = fallback; 146 | } 147 | if (base.length) { 148 | // schedule updating xlink:href 149 | xhr = cache[base]; 150 | if (xhr !== true) { 151 | // true signifies that prepending the SVG was not required 152 | setTimeout(attrUpdateFunc({ 153 | useEl: uses[i], 154 | base: base, 155 | hash: hash 156 | }), 0); 157 | } 158 | if (xhr === undefined) { 159 | Request = createRequest(base); 160 | if (Request !== undefined) { 161 | xhr = new Request(); 162 | cache[base] = xhr; 163 | xhr.onload = onloadFunc(xhr); 164 | xhr.onerror = onErrorTimeout(xhr); 165 | xhr.ontimeout = onErrorTimeout(xhr); 166 | xhr.open('GET', base); 167 | xhr.send(); 168 | inProgressCount += 1; 169 | } 170 | } 171 | } 172 | } else { 173 | if (!isHidden) { 174 | if (cache[base] === undefined) { 175 | // remember this URL if the use element was not empty and no request was sent 176 | cache[base] = true; 177 | } else if (cache[base].onload) { 178 | // if it turns out that prepending the SVG is not necessary, 179 | // abort the in-progress xhr. 180 | cache[base].abort(); 181 | delete cache[base].onload; 182 | cache[base] = true; 183 | } 184 | } else if (base.length && cache[base]) { 185 | attrUpdateFunc({ 186 | useEl: uses[i], 187 | base: base, 188 | hash: hash 189 | })(); 190 | } 191 | } 192 | } 193 | uses = ''; 194 | inProgressCount += 1; 195 | observeIfDone(); 196 | }; 197 | // The load event fires when all resources have finished loading, which allows detecting whether SVG use elements are empty. 198 | window.addEventListener('load', function winLoad() { 199 | window.removeEventListener('load', winLoad, false); // to prevent memory leaks 200 | tid = setTimeout(checkUseElems, 0); 201 | }, false); 202 | } 203 | }()); 204 | -------------------------------------------------------------------------------- /docs/blueprint/sect0001.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 12 | 13 | 14 | 15 | Introduction 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |

Unit Fractions

29 |
30 | 31 |
32 | 78 | 79 |
80 |
81 | 82 | 83 |
84 |

Introduction

85 | 86 |

This is an interactive blueprint to help with the formalisation of the main result of (https://arxiv.org/abs/2112.03726): that if \(A\subset \mathbb {N}\) has positive density then there are distinct \(n_1,\ldots ,n_k\in A\) such that \(\frac{1}{n_1}+\cdots +\frac{1}{n_k}=1\).

87 |

(And other more precise results formulated in that paper.) For context, background, references, and so on, we refer to the original paper (https://arxiv.org/abs/2112.03726). This blueprint will (once finished) be a complete mathematical guide to the entire proof, and indeed the proofs will be in many places expanded and explained more fully, to help the formalisation process.

88 |

Nonetheless, we will be sparing with non-mathematical remarks, and will not usually trouble to explain the context of a particular lemma, or what it’s ‘really saying’, and so on – we will present everything necessary to formalise the proof in Lean, no more and no less.

89 |

The actual Lean code can be found at (https://github.com/leanprover-community/mathlib/blob/unit-fractions/src/number_theory/unit_fractions.lean). If you’d like to contribute in any way, or have any questions about this project, please email me at bloom@maths.ox.ac.uk.

90 |

This blueprint is adapted from the blueprint created by Patrick Massot for the Sphere Eversion project (https://github.com/leanprover-community/sphere-eversion).

91 |

This blueprint uses Patrick Massot’s leanblueprint plugin (https://github.com/PatrickMassot/leanblueprint) for plasTeX (http://plastex.github.io/plastex/).

92 | 93 |
94 |
95 |
96 |
97 | 98 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /docs/blueprint/styles/amsthm.css: -------------------------------------------------------------------------------- 1 | 2 | span[class$='_thmlabel'] 3 | { 4 | margin-left: .5rem; 5 | } 6 | 7 | div.theorem-style-plain div[class$='_thmheading'] { 8 | font-style: normal; 9 | font-weight: bold; 10 | 11 | } 12 | div.theorem-style-plain span[class$='_thmlabel']::after 13 | { 14 | content: '.'; 15 | } 16 | div.theorem-style-plain div[class$='_thmcontent'] { 17 | font-style: italic; 18 | font-weight: normal; 19 | 20 | } 21 | 22 | div.theorem-style-definition div[class$='_thmheading'] { 23 | font-style: normal; 24 | font-weight: bold; 25 | 26 | } 27 | div.theorem-style-definition span[class$='_thmlabel']::after 28 | { 29 | content: '.'; 30 | } 31 | div.theorem-style-remark div[class$='_thmheading'] { 32 | font-style: normal; 33 | font-weight: bold; 34 | 35 | } 36 | div.theorem-style-remark span[class$='_thmlabel']::after 37 | { 38 | content: '.'; 39 | } -------------------------------------------------------------------------------- /docs/blueprint/styles/dep_graph.css: -------------------------------------------------------------------------------- 1 | header { 2 | height: 3rem; 3 | justify-content: center; 4 | display: flex; 5 | } 6 | 7 | header a { 8 | margin-right: auto; 9 | text-decoration: none; 10 | color: inherit; 11 | } 12 | 13 | header a:visited { 14 | color: inherit; 15 | } 16 | 17 | header h1 { 18 | position: absolute; 19 | } 20 | 21 | div#graph { 22 | width: 100%; 23 | height: 90vh; 24 | resize: both; 25 | overflow: hidden; } 26 | 27 | 28 | div#statements { 29 | display: none; 30 | position: absolute; 31 | bottom: 0; 32 | width: 100%; 33 | background-color: #e8e8e8; /* FIXME: use sass */ 34 | } 35 | 36 | #Legend span.title { 37 | font-size: 150%; 38 | font-weight: bold; 39 | display: flex; 40 | margin-right: 2rem; 41 | cursor: pointer; 42 | } 43 | 44 | #Legend dl { 45 | position: absolute; 46 | top: 6rem; 47 | left:1.5rem; 48 | font-size: 120%; 49 | display: none; 50 | max-width: 30%; 51 | background: white 52 | } 53 | 54 | #Legend div.btn { 55 | margin-left: .5rem; 56 | margin-top: .1rem; 57 | } 58 | 59 | #Legend dt { 60 | font-weight: bold; 61 | } 62 | 63 | #Legend dt::after { 64 | content: ":"; 65 | } 66 | 67 | #Legend dd { 68 | margin-left: .5rem; 69 | margin-right: 1rem; 70 | display: inline; 71 | } 72 | 73 | 74 | div.bar { 75 | display: block; 76 | width: 22px; 77 | height: 3px; 78 | border-radius: 1px; 79 | margin-top: 2px; 80 | margin-bot: 2px; 81 | background: black; 82 | } 83 | 84 | 85 | button.dep-closebtn 86 | { 87 | position: absolute; 88 | top: 1rem; 89 | right: 1rem; 90 | font-size: 100%; 91 | font-weight: bold; 92 | 93 | background: Transparent; 94 | border: none; 95 | 96 | text-decoration: none; 97 | 98 | /* color: #fff;*/ 99 | cursor: pointer; 100 | } 101 | 102 | div.dep-modal-container { 103 | position: fixed; 104 | z-index: $modal-z-index; 105 | top: 0; 106 | left: 0; 107 | 108 | display: none; 109 | 110 | width: 90vw; 111 | margin-top: 4rem; 112 | margin-left: 5vw; 113 | margin-right: 5vw; 114 | } 115 | div.dep-modal-content { 116 | font-weight: normal; 117 | 118 | overflow: auto; 119 | 120 | margin: auto; 121 | 122 | vertical-align: middle; 123 | 124 | border: 1px solid #497da5; /* FIXME use sass, compare main modals */ 125 | border-radius: 5px; 126 | background-color: white; 127 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19); 128 | padding: .5rem 1rem .2rem 1rem; 129 | } 130 | 131 | div.dep-modal-content a { 132 | color: inherit; 133 | text-decoration: none; 134 | } 135 | 136 | div.thm_icons .icon { 137 | width: .7rem; 138 | height: .7rem; 139 | } 140 | 141 | a.latex_link, a.lean_link { 142 | font-weight: normal; 143 | font-size: 90%; 144 | font-style: italic; 145 | } 146 | 147 | a.latex_link { 148 | padding-left: 1rem; 149 | } 150 | 151 | a.lean_link { 152 | padding-left: .5rem; 153 | } 154 | 155 | /* Tooltip container */ 156 | .tooltip { 157 | font-weight: normal; 158 | margin-left: .5rem; 159 | position: relative; 160 | display: inline-block; 161 | } 162 | 163 | /* Tooltip text */ 164 | .tooltip .tooltip_list { 165 | visibility: hidden; 166 | text-align: center; 167 | border-radius: 6px; 168 | 169 | position: absolute; 170 | z-index: 1; 171 | top: 100%; 172 | } 173 | 174 | ul.tooltip_list { 175 | list-style-type: none; 176 | padding-left: 0; 177 | border: 1px solid #497da5; /* FIXME use sass, compare main modals */ 178 | border-radius: 5px; 179 | background-color: white; 180 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19); 181 | } 182 | 183 | ul.tooltip_list li { 184 | padding: .1rem .5rem; 185 | } 186 | 187 | /* Show the tooltip text when you mouse over the tooltip container */ 188 | .tooltip:hover .tooltip_list { 189 | visibility: visible; 190 | } 191 | 192 | .node { 193 | cursor: pointer; 194 | } 195 | -------------------------------------------------------------------------------- /docs/blueprint/styles/showmore.css: -------------------------------------------------------------------------------- 1 | p.hidden { 2 | display: none; 3 | } 4 | 5 | svg.showmore { 6 | font-size: 150%; 7 | margin: auto; 8 | min-width: 2rem; 9 | text-decoration: none; 10 | color: white; 11 | text-shadow: 1px 2px 0 rgba(0, 0, 0, 0.8); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /docs/blueprint/styles/style_coverage.css: -------------------------------------------------------------------------------- 1 | header { 2 | height: 3rem; 3 | } 4 | 5 | header a { 6 | margin-right: auto; 7 | text-decoration: none; 8 | color: white; 9 | } 10 | 11 | header h1 { 12 | position: absolute; 13 | } 14 | 15 | section h2 { 16 | margin: .5rem; 17 | cursor : pointer; 18 | } 19 | 20 | ul.coverage { 21 | display: none; 22 | } 23 | 24 | ul.coverage li { 25 | margin: 1rem; 26 | } 27 | 28 | div.thm_thm_content { 29 | display: none; 30 | } 31 | 32 | span.ok { 33 | color: green; 34 | } 35 | 36 | span.partial { 37 | color: orange; 38 | } 39 | 40 | span.void { 41 | color: red; 42 | } 43 | 44 | div.thm_thmheading { 45 | cursor : pointer; 46 | margin-bottom: .5rem; 47 | } 48 | -------------------------------------------------------------------------------- /docs/blueprint/styles/stylecours.css: -------------------------------------------------------------------------------- 1 | div.theorem_thmcontent { 2 | border-left: .15rem solid black; 3 | } 4 | 5 | div.proposition_thmcontent { 6 | border-left: .15rem solid black; 7 | } 8 | 9 | div.lemma_thmcontent { 10 | border-left: .1rem solid black; 11 | } 12 | 13 | div.corollary_thmcontent { 14 | border-left: .1rem solid black; 15 | } 16 | 17 | div.proof_content { 18 | border-left: .08rem solid grey; 19 | } 20 | 21 | figure.subfloat span.subref { 22 | display: none; 23 | } 24 | 25 | nav.local_toc ul { 26 | font-size: 1.2rem; 27 | } 28 | 29 | @media (min-width:1024px) { 30 | nav.toc { 31 | width: 25vw; 32 | } 33 | } 34 | 35 | @media (min-width:1024px) { 36 | div.with-toc { 37 | margin-left:25vw; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/blueprint/styles/theme-blue.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{font:inherit;font-size:100%;margin:0;padding:0;border:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1;overflow-x:hidden;background:#f4f4f4}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}table{border-spacing:0;border-collapse:collapse}.clear:after{font-size:0;display:block;visibility:hidden;clear:both;height:0;content:" "}.clear{display:inline-block}* html .clear{height:1%}.clear{display:block}*{box-sizing:border-box}hr{clear:both;border:none;outline:none}em{font-style:italic}a{text-decoration:underline}ul{list-style:disc}ol{list-style:decimal}ol,ul{font-size:14px;padding:0 0 0 33px}ol li,ul li{margin:0}blockquote{padding:0 15px 0 40px}table{font-size:13px;width:100%;margin:20px 0;background:#fff}table th{font-size:16px;font-weight:700}table tr td{padding:7px}::selection{color:#fff;background:#000}::-moz-selection{color:#fff;background:#000}body{height:100vh;margin:0;flex-direction:column;color:#0a0a14;background-color:#e8e8e8}body,div.wrapper{display:flex;overflow:hidden}div.wrapper{flex-grow:1}div.content-wrapper{max-width:75ch}@media (min-width:1024px){div.content-wrapper{margin-left:auto;margin-right:auto}}div.content{flex-grow:1;display:flex;flex-direction:column;overflow:auto;padding:.5rem;margin-bottom:2.5rem}@media (min-width:1024px){div.content{padding:1rem;margin-bottom:0}}div.centered{display:flex;flex-direction:column;flex-wrap:wrap;align-items:center;justify-content:space-around;min-width:100%;margin:0 auto}div.flushleft,div.raggedright{display:flex;justify-content:flex-start}div.flushright,div.raggedbottom,div.raggedleft{display:flex;justify-content:flex-end}div.raggedbottom{flex-direction:column}div.content{line-height:1.4rem}div.content>p{margin:2.1rem 0}li>p{margin:.28rem 0}.icon{display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:1rem;height:1rem;stroke-width:0;stroke:currentColor;fill:currentColor}h1,h2,h3,h4,h5,h6{font-family:Lucida Grande,Arial,Helvetica,sans-serif}h1{font-size:2rem;line-height:2rem;margin:1rem 0}h1,h2{color:#0f2f48}h2{font-size:1.5rem;margin:.8rem 0}h3,h4{margin:.67rem 0;color:#0f2f48}h3,h4,p{font-size:1rem}p{margin:.5rem 0}.titlepage{text-align:center}.titlepage h1{font-weight:400}b,strong{font-weight:700}dfn{font-style:italic}code,kbd,pre,samp{font-family:monospace,serif;font-size:1rem}pre{white-space:pre-wrap}q{quotes:"“" "”" "‘" "’"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5rem}sub{bottom:-.25rem}.mdseries,.textmf{font-weight:400}.bfseries,.textbf{font-weight:700}.rmfamily,.textrm{font-family:serif}.sffamily,.textsf{font-family:sans-serif}.texttt,.ttfamily{font-family:monospace}.textup,.upshape{text-transform:uppercase}.itshape,.textit{font-style:italic}.slshape,.textsl{font-style:oblique}.scshape,.textsc{font-variant:small-caps}small.tiny{font-size:x-small}small.scriptsize{font-size:smaller}small.footnotesize,small.small{font-size:small}.normalsize{font-size:normal}big.large{font-size:large}big.xlarge,big.xxlarge{font-size:x-large}big.huge,big.xhuge{font-size:xx-large}.rm{font-family:serif;font-style:normal;font-weight:400}.cal,.it{font-style:italic}.cal,.it,.sl{font-family:serif;font-weight:400}.sl{font-style:oblique}.bf{font-family:serif;font-weight:700}.bf,.tt{font-style:normal}.tt{font-family:monospace;font-weight:400}.underbar{text-decoration:underline}.fbox,.framebox{border:1px solid #000;padding:1px 3px}.quotation p,.quote p,.verse p{margin-top:0;margin-bottom:.5em}hr{color:#000}dd{margin-left:3rem}dd p{padding:0;margin:0 0 1rem}ul.breadcrumbs{margin:0;padding:0;list-style:none;font-size:small}ul.breadcrumbs li{display:inline}ul.breadcrumbs a{text-decoration:none;color:#396282}li.crumb:after{content:" / "}div.equation{display:flex;align-items:center;margin:1rem}div.equation span.equation_label{margin-right:1rem}div.equation span.equation_label:before{content:"("}div.equation span.equation_label:after{content:")"}div.equation div.equation_content{margin:auto}figure{display:flex;flex-direction:column;vertical-align:bottom;overflow:auto}figure img{display:block;margin:0 auto}figcaption{display:block;text-align:center;margin-bottom:.1rem}span.caption_ref,span.caption_title,span.subcaption{font-weight:700}span.caption_ref:after{content:":"}span.subref:after{content:")"}footer#footnotes{clear:both;padding-top:1rem;padding-left:1rem;border-color:gray;border-top:1px solid}footer#footnotes h1{font-size:1.5rem;margin:0;margin-bottom:.5rem;color:#000}a.footnote{text-decoration:none}a.footnote sup:after{content:"]"}a.footnote sup:before{content:"["}body>header{background:linear-gradient(180deg,#6696bb 0,#396282);color:#fff;text-shadow:1px 2px 0 rgba(0,0,0,.8);display:flex;align-items:center;padding:.5rem}svg#toc-toggle{width:1.125rem;height:1.125rem;margin-right:.5rem}h1#doc_title{color:#fff;font-size:1.5rem;margin:auto}#doc_title a,#doc_title a:visited{text-decoration:none;color:#fff}.theindex li{list-style-type:none}nav.index-groups{margin-bottom:1rem}a[class^=index-group]{text-decoration:none}a.index-group:after{content:" |"}section.theindex{display:flex;flex-direction:row;flex-wrap:wrap;margin-top:1rem}section.theindex h2{min-width:100%;margin:1rem 0 .5rem}ul.index-column{min-width:100%}@media (min-width:1024px){ul.index-column{min-width:auto}}nav.prev_up_next a.index{font-size:small;padding-left:.5rem;padding-right:.5rem}dl.description dt{font-weight:700}table.list{margin-left:15px;margin-top:1em;margin-bottom:1em}table.list td{padding-right:5px}div.displaymath{overflow:auto}a.eqref:before{content:"("}a.eqref:after{content:")"}nav.prev_up_next{position:fixed;z-index:1;right:0;bottom:0;display:flex;height:2.5rem;background:linear-gradient(180deg,#6696bb 0,#396282)}nav.prev_up_next a{font-size:150%;margin:auto;padding:.5rem 1rem;text-decoration:none;color:#fff;text-shadow:1px 2px 0 rgba(0,0,0,.8)}hspace,vspace{margin:0;padding:0}div.bigskip{margin-bottom:4rem}div.medskip{margin:0;padding:0;margin-bottom:2rem}div.bigskip{margin:0;padding:0;margin-bottom:1rem}.tabular{border-collapse:collapse;color:#0a0a14;background-color:#e8e8e8;width:auto}.tabular td,.tabular th{vertical-align:baseline;text-align:left;padding:.3em .6em;empty-cells:show}td p:first-child,th p:first-child{margin-top:0;margin-bottom:0}td p,th p{margin-top:1em;margin-bottom:0}@keyframes a{0%{background-color:#c2c2c2}to{background-color:#e8e8e8}}div[class$=_thmwrapper]{margin-top:1rem}div[class$=_thmwrapper]:target{animation:a 1s ease}div[class$=_thmheading]{display:flex;font-weight:700;line-height:150%}span[class$=_thmtitle]:before{content:"("}span[class$=_thmtitle]:after{content:")"}div[class$=_thmcontent]{font-weight:400;margin-left:1rem;padding-top:.14rem;padding-left:1rem}span[class$=_thmlabel]{margin-left:.5rem;margin-right:.5rem}div[class$=proof_heading]{font-weight:700;line-height:120%;cursor:pointer}div.proof_content{font-weight:400;margin-left:1rem;padding-top:.5rem;padding-left:1rem}span.expand-proof{font-size:80%}div.hilite{animation:a 1s ease}span.qed{float:right}button.modal{border:none;text-align:center;text-decoration:none;background:transparent;cursor:pointer;padding:0}div.modal-container{position:fixed;z-index:2;top:0;left:0;display:none;width:100%;height:100%}div.modal-content{font-weight:400;overflow:auto;margin:auto;vertical-align:middle;border:1px solid #497da5;border-radius:5px;background-color:#fff;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}div.modal-content header{position:relative;background:linear-gradient(180deg,#6696bb 0,#396282);color:#fff;text-shadow:1px 2px 0 rgba(0,0,0,.8);display:flex;flex-direction:row;min-height:1rem;min-width:100%;text-align:center;vertical-align:middle;padding:0 .5rem;justify-content:space-between}div.modal-content header button.closebtn{font-size:120%;font-weight:700;background:Transparent;border:none;margin:auto 0;padding-right:.3rem;text-decoration:none;color:#fff;cursor:pointer}div.modal-content header h1{font-size:120%;margin:auto 0;padding:.2rem;color:#fff}div.modal-content a{text-decoration:none}div.modal-content ul{padding:1rem;list-style:none}div.modal-content li{padding-left:.5rem}a.icon{text-decoration:none;color:#0a0a14;border:none;background-color:Transparent}div[class$=_thmheading]:hover div.thm_icons{display:inline-block}div.thm_icons{display:none}ul.quizz{display:flex;flex-direction:column;list-style:circle!important}ul.quizz li{display:flex;padding:.5rem;flex-direction:row;min-width:100%;min-height:3rem;flex-grow:1;align-items:center;justify-content:space-between}ul.quizz li.active-qright{background-color:green}ul.quizz li.active-qwrong{background-color:red}ul.quizz svg.icon{display:none;padding-right:.5rem;width:2rem;height:2rem}.tikzcd{overflow:auto}.tikzcd,.tikzpicture{display:block;margin:.5rem auto}.local_toc ul{padding-left:1rem;list-style:none}.local_toc ul a{text-decoration:none;color:#0a0a14}.local_toc ul li{padding:.2rem 0}nav.toc{flex-shrink:0;display:none;width:100%;overflow-x:hidden;overflow-y:auto;flex-direction:column;margin-right:1rem;padding:0;padding-right:1rem;transition:left .5s ease;background-color:#6696bb;border-right:none}@media (min-width:1024px){nav.toc{display:flex;max-width:25ch}}nav.active{width:100%}.toc ul{min-width:100%;padding-left:0;list-style:none}.toc ul a{display:inline-block;max-width:90%;padding-top:.5rem;padding-right:.5rem;padding-bottom:.5rem;transition:all .1s ease;text-align:left;text-decoration:none;font-size:1.125rem;color:#fff;text-shadow:2px 2px 2px rgba(0,0,0,.8);flex-grow:1}.toc ul a:hover{transition:all .2s ease;background:#497da5}.toc ul li{display:flex;min-width:100%;align-items:center;flex-wrap:wrap;justify-content:space-between;background-color:#6696bb}.toc ul li.current{background-color:#89aecb;font-weight:400}.sub-toc-0 a{padding-left:.8rem}.sub-toc-1 a{padding-left:1.6rem}.sub-toc-2 a{padding-left:2.4rem}.sub-toc-3 a{padding-left:3.2rem}.sub-toc-4 a{padding-left:4rem}ul.sub-toc-1,ul.sub-toc-2,ul.sub-toc-3,ul.sub-toc-4{display:none}span.expand-toc{min-width:.7rem;width:.8rem;height:.8rem;padding:0;padding-right:.5rem;font-size:125%}span.expand-toc,svg.close-toc{cursor:pointer;text-align:center;color:#fff;background-color:Transparent}svg.close-toc{min-width:1.3rem;min-height:1.3rem;margin:.5rem;margin-left:auto;display:none}nav.active svg.close-toc{display:inline-block}ul.active{display:block}code.verb{font-family:monospace;font-style:normal;font-weight:400}pre.verbatim{margin:1rem 2rem;background-color:#dbdbdb;padding:.5rem} -------------------------------------------------------------------------------- /docs/blueprint/styles/theme-green.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{font:inherit;font-size:100%;margin:0;padding:0;border:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1;overflow-x:hidden;background:#f4f4f4}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}table{border-spacing:0;border-collapse:collapse}.clear:after{font-size:0;display:block;visibility:hidden;clear:both;height:0;content:" "}.clear{display:inline-block}* html .clear{height:1%}.clear{display:block}*{box-sizing:border-box}hr{clear:both;border:none;outline:none}em{font-style:italic}a{text-decoration:underline}ul{list-style:disc}ol{list-style:decimal}ol,ul{font-size:14px;padding:0 0 0 33px}ol li,ul li{margin:0}blockquote{padding:0 15px 0 40px}table{font-size:13px;width:100%;margin:20px 0;background:#fff}table th{font-size:16px;font-weight:700}table tr td{padding:7px}::selection{color:#fff;background:#000}::-moz-selection{color:#fff;background:#000}body{height:100vh;margin:0;flex-direction:column;color:#000;background-color:#fff}body,div.wrapper{display:flex;overflow:hidden}div.wrapper{flex-grow:1}div.content-wrapper{max-width:75ch}@media (min-width:1024px){div.content-wrapper{margin-left:auto;margin-right:auto}}div.content{flex-grow:1;display:flex;flex-direction:column;overflow:auto;padding:.5rem;margin-bottom:2.5rem}@media (min-width:1024px){div.content{padding:1rem;margin-bottom:0}}div.centered{display:flex;flex-direction:column;flex-wrap:wrap;align-items:center;justify-content:space-around;min-width:100%;margin:0 auto}div.flushleft,div.raggedright{display:flex;justify-content:flex-start}div.flushright,div.raggedbottom,div.raggedleft{display:flex;justify-content:flex-end}div.raggedbottom{flex-direction:column}div.content{line-height:1.4rem}div.content>p{margin:2.1rem 0}li>p{margin:.28rem 0}.icon{display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:1rem;height:1rem;stroke-width:0;stroke:currentColor;fill:currentColor}h1,h2,h3,h4,h5,h6{font-family:Lucida Grande,Arial,Helvetica,sans-serif}h1{font-size:2rem;line-height:2rem;margin:1rem 0}h1,h2{color:#000}h2{font-size:1.5rem;margin:.8rem 0}h3,h4{margin:.67rem 0;color:#000}h3,h4,p{font-size:1rem}p{margin:.5rem 0}.titlepage{text-align:center}.titlepage h1{font-weight:400}b,strong{font-weight:700}dfn{font-style:italic}code,kbd,pre,samp{font-family:monospace,serif;font-size:1rem}pre{white-space:pre-wrap}q{quotes:"“" "”" "‘" "’"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5rem}sub{bottom:-.25rem}.mdseries,.textmf{font-weight:400}.bfseries,.textbf{font-weight:700}.rmfamily,.textrm{font-family:serif}.sffamily,.textsf{font-family:sans-serif}.texttt,.ttfamily{font-family:monospace}.textup,.upshape{text-transform:uppercase}.itshape,.textit{font-style:italic}.slshape,.textsl{font-style:oblique}.scshape,.textsc{font-variant:small-caps}small.tiny{font-size:x-small}small.scriptsize{font-size:smaller}small.footnotesize,small.small{font-size:small}.normalsize{font-size:normal}big.large{font-size:large}big.xlarge,big.xxlarge{font-size:x-large}big.huge,big.xhuge{font-size:xx-large}.rm{font-family:serif;font-style:normal;font-weight:400}.cal,.it{font-style:italic}.cal,.it,.sl{font-family:serif;font-weight:400}.sl{font-style:oblique}.bf{font-family:serif;font-weight:700}.bf,.tt{font-style:normal}.tt{font-family:monospace;font-weight:400}.underbar{text-decoration:underline}.fbox,.framebox{border:1px solid #000;padding:1px 3px}.quotation p,.quote p,.verse p{margin-top:0;margin-bottom:.5em}hr{color:#000}dd{margin-left:3rem}dd p{padding:0;margin:0 0 1rem}ul.breadcrumbs{margin:0;padding:0;list-style:none;font-size:small}ul.breadcrumbs li{display:inline}ul.breadcrumbs a{text-decoration:none;color:#4d7326}li.crumb:after{content:" / "}div.equation{display:flex;align-items:center;margin:1rem}div.equation span.equation_label{margin-right:1rem}div.equation span.equation_label:before{content:"("}div.equation span.equation_label:after{content:")"}div.equation div.equation_content{margin:auto}figure{display:flex;flex-direction:column;vertical-align:bottom;overflow:auto}figure img{display:block;margin:0 auto}figcaption{display:block;text-align:center;margin-bottom:.1rem}span.caption_ref,span.caption_title,span.subcaption{font-weight:700}span.caption_ref:after{content:":"}span.subref:after{content:")"}footer#footnotes{clear:both;padding-top:1rem;padding-left:1rem;border-color:gray;border-top:1px solid}footer#footnotes h1{font-size:1.5rem;margin:0;margin-bottom:.5rem;color:#000}a.footnote{text-decoration:none}a.footnote sup:after{content:"]"}a.footnote sup:before{content:"["}body>header{background:linear-gradient(180deg,#80bf40 0,#4d7326);color:#ffc;text-shadow:1px 2px 0 rgba(0,0,0,.8);display:flex;align-items:center;padding:.5rem}svg#toc-toggle{width:1.125rem;height:1.125rem;margin-right:.5rem}h1#doc_title{color:#ffc;font-size:1.5rem;margin:auto}#doc_title a,#doc_title a:visited{text-decoration:none;color:#ffc}.theindex li{list-style-type:none}nav.index-groups{margin-bottom:1rem}a[class^=index-group]{text-decoration:none}a.index-group:after{content:" |"}section.theindex{display:flex;flex-direction:row;flex-wrap:wrap;margin-top:1rem}section.theindex h2{min-width:100%;margin:1rem 0 .5rem}ul.index-column{min-width:100%}@media (min-width:1024px){ul.index-column{min-width:auto}}nav.prev_up_next a.index{font-size:small;padding-left:.5rem;padding-right:.5rem}dl.description dt{font-weight:700}table.list{margin-left:15px;margin-top:1em;margin-bottom:1em}table.list td{padding-right:5px}div.displaymath{overflow:auto}a.eqref:before{content:"("}a.eqref:after{content:")"}nav.prev_up_next{position:fixed;z-index:1;right:0;bottom:0;display:flex;height:2.5rem;background:linear-gradient(180deg,#80bf40 0,#4d7326)}nav.prev_up_next a{font-size:150%;margin:auto;padding:.5rem 1rem;text-decoration:none;color:#fff;text-shadow:1px 2px 0 rgba(0,0,0,.8)}hspace,vspace{margin:0;padding:0}div.bigskip{margin-bottom:4rem}div.medskip{margin:0;padding:0;margin-bottom:2rem}div.bigskip{margin:0;padding:0;margin-bottom:1rem}.tabular{border-collapse:collapse;color:#000;background-color:#fff;width:auto}.tabular td,.tabular th{vertical-align:baseline;text-align:left;padding:.3em .6em;empty-cells:show}td p:first-child,th p:first-child{margin-top:0;margin-bottom:0}td p,th p{margin-top:1em;margin-bottom:0}@keyframes a{0%{background-color:#d9d9d9}to{background-color:#fff}}div[class$=_thmwrapper]{margin-top:1rem}div[class$=_thmwrapper]:target{animation:a 1s ease}div[class$=_thmheading]{display:flex;font-weight:700;line-height:150%}span[class$=_thmtitle]:before{content:"("}span[class$=_thmtitle]:after{content:")"}div[class$=_thmcontent]{font-weight:400;margin-left:1rem;padding-top:.14rem;padding-left:1rem}span[class$=_thmlabel]{margin-left:.5rem;margin-right:.5rem}div[class$=proof_heading]{font-weight:700;line-height:120%;cursor:pointer}div.proof_content{font-weight:400;margin-left:1rem;padding-top:.5rem;padding-left:1rem}span.expand-proof{font-size:80%}div.hilite{animation:a 1s ease}span.qed{float:right}button.modal{border:none;text-align:center;text-decoration:none;background:transparent;cursor:pointer;padding:0}div.modal-container{position:fixed;z-index:2;top:0;left:0;display:none;width:100%;height:100%}div.modal-content{font-weight:400;overflow:auto;margin:auto;vertical-align:middle;border:1px solid #693;border-radius:5px;background-color:#fff;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}div.modal-content header{position:relative;background:linear-gradient(180deg,#80bf40 0,#4d7326);color:#ffc;text-shadow:1px 2px 0 rgba(0,0,0,.8);display:flex;flex-direction:row;min-height:1rem;min-width:100%;text-align:center;vertical-align:middle;padding:0 .5rem;justify-content:space-between}div.modal-content header button.closebtn{font-size:120%;font-weight:700;background:Transparent;border:none;margin:auto 0;padding-right:.3rem;text-decoration:none;color:#ffc;cursor:pointer}div.modal-content header h1{font-size:120%;margin:auto 0;padding:.2rem;color:#fff}div.modal-content a{text-decoration:none}div.modal-content ul{padding:1rem;list-style:none}div.modal-content li{padding-left:.5rem}a.icon{text-decoration:none;color:#000;border:none;background-color:Transparent}div[class$=_thmheading]:hover div.thm_icons{display:inline-block}div.thm_icons{display:none}ul.quizz{display:flex;flex-direction:column;list-style:circle!important}ul.quizz li{display:flex;padding:.5rem;flex-direction:row;min-width:100%;min-height:3rem;flex-grow:1;align-items:center;justify-content:space-between}ul.quizz li.active-qright{background-color:green}ul.quizz li.active-qwrong{background-color:red}ul.quizz svg.icon{display:none;padding-right:.5rem;width:2rem;height:2rem}.tikzcd{overflow:auto}.tikzcd,.tikzpicture{display:block;margin:.5rem auto}.local_toc ul{padding-left:1rem;list-style:none}.local_toc ul a{text-decoration:none;color:#000}.local_toc ul li{padding:.2rem 0}nav.toc{flex-shrink:0;display:none;width:100%;overflow-x:hidden;overflow-y:auto;flex-direction:column;margin-right:1rem;padding:0;padding-right:1rem;transition:left .5s ease;background-color:#80bf40;border-right:none}@media (min-width:1024px){nav.toc{display:flex;max-width:25ch}}nav.active{width:100%}.toc ul{min-width:100%;padding-left:0;list-style:none}.toc ul a{display:inline-block;max-width:90%;padding-top:.5rem;padding-right:.5rem;padding-bottom:.5rem;transition:all .1s ease;text-align:left;text-decoration:none;font-size:1.125rem;color:#fff;text-shadow:2px 2px 2px rgba(0,0,0,.8);flex-grow:1}.toc ul a:hover{transition:all .2s ease;background:#693}.toc ul li{display:flex;min-width:100%;align-items:center;flex-wrap:wrap;justify-content:space-between;background-color:#80bf40}.toc ul li.current{background-color:#9c6;font-weight:400}.sub-toc-0 a{padding-left:.8rem}.sub-toc-1 a{padding-left:1.6rem}.sub-toc-2 a{padding-left:2.4rem}.sub-toc-3 a{padding-left:3.2rem}.sub-toc-4 a{padding-left:4rem}ul.sub-toc-1,ul.sub-toc-2,ul.sub-toc-3,ul.sub-toc-4{display:none}span.expand-toc{min-width:.7rem;width:.8rem;height:.8rem;padding:0;padding-right:.5rem;font-size:125%}span.expand-toc,svg.close-toc{cursor:pointer;text-align:center;color:#fff;background-color:Transparent}svg.close-toc{min-width:1.3rem;min-height:1.3rem;margin:.5rem;margin-left:auto;display:none}nav.active svg.close-toc{display:inline-block}ul.active{display:block}code.verb{font-family:monospace;font-style:normal;font-weight:400}pre.verbatim{margin:1rem 2rem;background-color:#f2f2f2;padding:.5rem} -------------------------------------------------------------------------------- /docs/blueprint/styles/theme-white.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{font:inherit;font-size:100%;margin:0;padding:0;border:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1;overflow-x:hidden;background:#f4f4f4}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}table{border-spacing:0;border-collapse:collapse}.clear:after{font-size:0;display:block;visibility:hidden;clear:both;height:0;content:" "}.clear{display:inline-block}* html .clear{height:1%}.clear{display:block}*{box-sizing:border-box}hr{clear:both;border:none;outline:none}em{font-style:italic}a{text-decoration:underline}ul{list-style:disc}ol{list-style:decimal}ol,ul{font-size:14px;padding:0 0 0 33px}ol li,ul li{margin:0}blockquote{padding:0 15px 0 40px}table{font-size:13px;width:100%;margin:20px 0;background:#fff}table th{font-size:16px;font-weight:700}table tr td{padding:7px}::selection{color:#fff;background:#000}::-moz-selection{color:#fff;background:#000}body{height:100vh;margin:0;flex-direction:column;color:#24292e;background-color:#fff}body,div.wrapper{display:flex;overflow:hidden}div.wrapper{flex-grow:1}div.content-wrapper{max-width:75ch}@media (min-width:1024px){div.content-wrapper{margin-left:auto;margin-right:auto}}div.content{flex-grow:1;display:flex;flex-direction:column;overflow:auto;padding:.5rem;margin-bottom:2.5rem}@media (min-width:1024px){div.content{padding:1rem;margin-bottom:0}}div.centered{display:flex;flex-direction:column;flex-wrap:wrap;align-items:center;justify-content:space-around;min-width:100%;margin:0 auto}div.flushleft,div.raggedright{display:flex;justify-content:flex-start}div.flushright,div.raggedbottom,div.raggedleft{display:flex;justify-content:flex-end}div.raggedbottom{flex-direction:column}div.content{line-height:1.4rem}div.content>p{margin:2.1rem 0}li>p{margin:.28rem 0}.icon{display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:1rem;height:1rem;stroke-width:0;stroke:currentColor;fill:currentColor}h1,h2,h3,h4,h5,h6{font-family:Lucida Grande,Arial,Helvetica,sans-serif}h1{font-size:2rem;line-height:2rem;margin:1rem 0}h1,h2{color:#24292e}h2{font-size:1.5rem;margin:.8rem 0}h3,h4{margin:.67rem 0;color:#24292e}h3,h4,p{font-size:1rem}p{margin:.5rem 0}.titlepage{text-align:center}.titlepage h1{font-weight:400}b,strong{font-weight:700}dfn{font-style:italic}code,kbd,pre,samp{font-family:monospace,serif;font-size:1rem}pre{white-space:pre-wrap}q{quotes:"“" "”" "‘" "’"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5rem}sub{bottom:-.25rem}.mdseries,.textmf{font-weight:400}.bfseries,.textbf{font-weight:700}.rmfamily,.textrm{font-family:serif}.sffamily,.textsf{font-family:sans-serif}.texttt,.ttfamily{font-family:monospace}.textup,.upshape{text-transform:uppercase}.itshape,.textit{font-style:italic}.slshape,.textsl{font-style:oblique}.scshape,.textsc{font-variant:small-caps}small.tiny{font-size:x-small}small.scriptsize{font-size:smaller}small.footnotesize,small.small{font-size:small}.normalsize{font-size:normal}big.large{font-size:large}big.xlarge,big.xxlarge{font-size:x-large}big.huge,big.xhuge{font-size:xx-large}.rm{font-family:serif;font-style:normal;font-weight:400}.cal,.it{font-style:italic}.cal,.it,.sl{font-family:serif;font-weight:400}.sl{font-style:oblique}.bf{font-family:serif;font-weight:700}.bf,.tt{font-style:normal}.tt{font-family:monospace;font-weight:400}.underbar{text-decoration:underline}.fbox,.framebox{border:1px solid #000;padding:1px 3px}.quotation p,.quote p,.verse p{margin-top:0;margin-bottom:.5em}hr{color:#000}dd{margin-left:3rem}dd p{padding:0;margin:0 0 1rem}ul.breadcrumbs{margin:0;padding:0;list-style:none;font-size:small}ul.breadcrumbs li{display:inline}ul.breadcrumbs a{text-decoration:none;color:#3a434b}li.crumb:after{content:" / "}div.equation{display:flex;align-items:center;margin:1rem}div.equation span.equation_label{margin-right:1rem}div.equation span.equation_label:before{content:"("}div.equation span.equation_label:after{content:")"}div.equation div.equation_content{margin:auto}figure{display:flex;flex-direction:column;vertical-align:bottom;overflow:auto}figure img{display:block;margin:0 auto}figcaption{display:block;text-align:center;margin-bottom:.1rem}span.caption_ref,span.caption_title,span.subcaption{font-weight:700}span.caption_ref:after{content:":"}span.subref:after{content:")"}footer#footnotes{clear:both;padding-top:1rem;padding-left:1rem;border-color:gray;border-top:1px solid}footer#footnotes h1{font-size:1.5rem;margin:0;margin-bottom:.5rem;color:#000}a.footnote{text-decoration:none}a.footnote sup:after{content:"]"}a.footnote sup:before{content:"["}body>header{background:#f2f2f2;color:#24292e;text-shadow:none;display:flex;align-items:center;padding:.5rem}svg#toc-toggle{width:1.125rem;height:1.125rem;margin-right:.5rem}h1#doc_title{color:#24292e;font-size:1.5rem;margin:auto}#doc_title a,#doc_title a:visited{text-decoration:none;color:#24292e}.theindex li{list-style-type:none}nav.index-groups{margin-bottom:1rem}a[class^=index-group]{text-decoration:none}a.index-group:after{content:" |"}section.theindex{display:flex;flex-direction:row;flex-wrap:wrap;margin-top:1rem}section.theindex h2{min-width:100%;margin:1rem 0 .5rem}ul.index-column{min-width:100%}@media (min-width:1024px){ul.index-column{min-width:auto}}nav.prev_up_next a.index{font-size:small;padding-left:.5rem;padding-right:.5rem}dl.description dt{font-weight:700}table.list{margin-left:15px;margin-top:1em;margin-bottom:1em}table.list td{padding-right:5px}div.displaymath{overflow:auto}a.eqref:before{content:"("}a.eqref:after{content:")"}nav.prev_up_next{position:fixed;z-index:1;right:0;bottom:0;display:flex;height:2.5rem;background:#f2f2f2}nav.prev_up_next a{font-size:150%;margin:auto;padding:.5rem 1rem;text-decoration:none;color:#24292e;text-shadow:none}hspace,vspace{margin:0;padding:0}div.bigskip{margin-bottom:4rem}div.medskip{margin:0;padding:0;margin-bottom:2rem}div.bigskip{margin:0;padding:0;margin-bottom:1rem}.tabular{border-collapse:collapse;color:#24292e;background-color:#fff;width:auto}.tabular td,.tabular th{vertical-align:baseline;text-align:left;padding:.3em .6em;empty-cells:show}td p:first-child,th p:first-child{margin-top:0;margin-bottom:0}td p,th p{margin-top:1em;margin-bottom:0}@keyframes a{0%{background-color:#d9d9d9}to{background-color:#fff}}div[class$=_thmwrapper]{margin-top:1rem}div[class$=_thmwrapper]:target{animation:a 1s ease}div[class$=_thmheading]{display:flex;font-weight:700;line-height:150%}span[class$=_thmtitle]:before{content:"("}span[class$=_thmtitle]:after{content:")"}div[class$=_thmcontent]{font-weight:400;margin-left:1rem;padding-top:.14rem;padding-left:1rem}span[class$=_thmlabel]{margin-left:.5rem;margin-right:.5rem}div[class$=proof_heading]{font-weight:700;line-height:120%;cursor:pointer}div.proof_content{font-weight:400;margin-left:1rem;padding-top:.5rem;padding-left:1rem}span.expand-proof{font-size:80%}div.hilite{animation:a 1s ease}span.qed{float:right}button.modal{border:none;text-align:center;text-decoration:none;background:transparent;cursor:pointer;padding:0}div.modal-container{position:fixed;z-index:2;top:0;left:0;display:none;width:100%;height:100%}div.modal-content{font-weight:400;overflow:auto;margin:auto;vertical-align:middle;border:1px solid #e6e6e6;border-radius:5px;background-color:#fff;box-shadow:0 4px 8px 0 rgba(0,0,0,.2),0 6px 20px 0 rgba(0,0,0,.19)}div.modal-content header{position:relative;background:#f2f2f2;color:#24292e;text-shadow:none;display:flex;flex-direction:row;min-height:1rem;min-width:100%;text-align:center;vertical-align:middle;padding:0 .5rem;justify-content:space-between}div.modal-content header button.closebtn{font-size:120%;font-weight:700;background:Transparent;border:none;margin:auto 0;padding-right:.3rem;text-decoration:none;color:#24292e;cursor:pointer}div.modal-content header h1{font-size:120%;margin:auto 0;padding:.2rem;color:#464f59}div.modal-content a{text-decoration:none}div.modal-content ul{padding:1rem;list-style:none}div.modal-content li{padding-left:.5rem}a.icon{text-decoration:none;color:#24292e;border:none;background-color:Transparent}div[class$=_thmheading]:hover div.thm_icons{display:inline-block}div.thm_icons{display:none}ul.quizz{display:flex;flex-direction:column;list-style:circle!important}ul.quizz li{display:flex;padding:.5rem;flex-direction:row;min-width:100%;min-height:3rem;flex-grow:1;align-items:center;justify-content:space-between}ul.quizz li.active-qright{background-color:green}ul.quizz li.active-qwrong{background-color:red}ul.quizz svg.icon{display:none;padding-right:.5rem;width:2rem;height:2rem}.tikzcd{overflow:auto}.tikzcd,.tikzpicture{display:block;margin:.5rem auto}.local_toc ul{padding-left:1rem;list-style:none}.local_toc ul a{text-decoration:none;color:#24292e}.local_toc ul li{padding:.2rem 0}nav.toc{flex-shrink:0;display:none;width:100%;overflow-x:hidden;overflow-y:auto;flex-direction:column;margin-right:1rem;padding:0;padding-right:1rem;transition:left .5s ease;background-color:#fff;border-right:1px solid #f2f2f2}@media (min-width:1024px){nav.toc{display:flex;max-width:25ch}}nav.active{width:100%}.toc ul{min-width:100%;padding-left:0;list-style:none}.toc ul a{display:inline-block;max-width:90%;padding-top:.5rem;padding-right:.5rem;padding-bottom:.5rem;transition:all .1s ease;text-align:left;text-decoration:none;font-size:1.125rem;color:#464f59;text-shadow:none;flex-grow:1}.toc ul a:hover{transition:all .2s ease;background:#e6e6e6}.toc ul li{display:flex;min-width:100%;align-items:center;flex-wrap:wrap;justify-content:space-between;background-color:#fff}.toc ul li.current{background-color:#fff;font-weight:700}.sub-toc-0 a{padding-left:.8rem}.sub-toc-1 a{padding-left:1.6rem}.sub-toc-2 a{padding-left:2.4rem}.sub-toc-3 a{padding-left:3.2rem}.sub-toc-4 a{padding-left:4rem}ul.sub-toc-1,ul.sub-toc-2,ul.sub-toc-3,ul.sub-toc-4{display:none}span.expand-toc{min-width:.7rem;width:.8rem;height:.8rem;padding:0;padding-right:.5rem;color:#5c6976;font-size:125%}span.expand-toc,svg.close-toc{cursor:pointer;text-align:center;background-color:Transparent}svg.close-toc{min-width:1.3rem;min-height:1.3rem;margin:.5rem;margin-left:auto;color:#464f59;display:none}nav.active svg.close-toc{display:inline-block}ul.active{display:block}code.verb{font-family:monospace;font-style:normal;font-weight:400}pre.verbatim{margin:1rem 2rem;background-color:#f2f2f2;padding:.5rem} -------------------------------------------------------------------------------- /docs/blueprint/symbol-defs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mindmap 5 | 6 | 7 | 8 | pencil 9 | 10 | 11 | 12 | lifebuoy 13 | 14 | 15 | 16 | cogs 17 | 18 | 19 | 20 | list-numbered 21 | 22 | 23 | 24 | list2 25 | 26 | 27 | 28 | menu 29 | 30 | 31 | 32 | eye-plus 33 | 34 | 35 | 36 | 37 | eye-minus 38 | 39 | 40 | 41 | 42 | smile 43 | 44 | 45 | 46 | sad 47 | 48 | 49 | 50 | plus 51 | 52 | 53 | 54 | cross 55 | 56 | 57 | 58 | arrow-up 59 | 60 | 61 | 62 | arrow-right 63 | 64 | 65 | 66 | arrow-left 67 | 68 | 69 | 70 | warning 71 | 72 | 73 | 74 | 75 | 76 | question 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Unit fractions 7 | 8 | 9 | 10 | 11 | 12 | 13 | 32 | 35 | 36 | 37 | 44 | 45 |
46 | 47 |

What is it about?

48 |

This project contains a formalized proof of the main result of the preprint ‘On a density conjecture about unit fractions’ using the Lean theorem prover, mainly developed at Microsoft Research by 49 | Leonardo de Moura. 50 | This project structure is adapted from the infrastructure created by Patrick Massot for the Sphere Eversion project.

51 |

More precisely we will prove that, any dense set of integers contains distinct integers whose reciprocals sum to 1. (This generalises a colouring result of Croot, and resolves an old open problem of Erdős and Graham.) For further details, precise statements, context, and so on, we refer to the preprint itself.

52 |

Exploring and helping

53 | This project is now complete! If you have any questions about it, please email bloom@maths.ox.ac.uk.

54 | 55 | 59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /docs/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight .c { color: #60a0b0; font-style: italic } /* Comment */ 3 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 4 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 5 | .highlight .o { color: #666666 } /* Operator */ 6 | .highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 8 | .highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ 9 | .highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */ 10 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 11 | .highlight .ge { font-style: italic } /* Generic.Emph */ 12 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 13 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 14 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 15 | .highlight .go { color: #808080 } /* Generic.Output */ 16 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 17 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 18 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 19 | .highlight .gt { color: #0040D0 } /* Generic.Traceback */ 20 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 21 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 22 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 23 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 24 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 25 | .highlight .kt { color: #902000 } /* Keyword.Type */ 26 | .highlight .m { color: #40a070 } /* Literal.Number */ 27 | .highlight .s { color: #4070a0 } /* Literal.String */ 28 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 29 | .highlight .nb { color: #007020 } /* Name.Builtin */ 30 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 31 | .highlight .no { color: #60add5 } /* Name.Constant */ 32 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 33 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 34 | .highlight .ne { color: #007020 } /* Name.Exception */ 35 | .highlight .nf { color: #06287e } /* Name.Function */ 36 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 37 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 38 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 39 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 40 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 41 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 42 | .highlight .mf { color: #40a070 } /* Literal.Number.Float */ 43 | .highlight .mh { color: #40a070 } /* Literal.Number.Hex */ 44 | .highlight .mi { color: #40a070 } /* Literal.Number.Integer */ 45 | .highlight .mo { color: #40a070 } /* Literal.Number.Oct */ 46 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 47 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 48 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 49 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 50 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 51 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 52 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 53 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 54 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 55 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 56 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 57 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 58 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 59 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 60 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 61 | .highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */ 62 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.highlight table td{padding:5px}.highlight table pre{margin:0}.highlight .cm{color:#999988;font-style:italic}.highlight .cp{color:#999999;font-weight:bold}.highlight .c1{color:#999988;font-style:italic}.highlight .cs{color:#999999;font-weight:bold;font-style:italic}.highlight .c,.highlight .cd{color:#999988;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .gd{color:#000000;background-color:#ffdddd}.highlight .ge{color:#000000;font-style:italic}.highlight .gr{color:#aa0000}.highlight .gh{color:#999999}.highlight .gi{color:#000000;background-color:#ddffdd}.highlight .go{color:#888888}.highlight .gp{color:#555555}.highlight .gs{font-weight:bold}.highlight .gu{color:#aaaaaa}.highlight .gt{color:#aa0000}.highlight .kc{color:#000000;font-weight:bold}.highlight .kd{color:#000000;font-weight:bold}.highlight .kn{color:#000000;font-weight:bold}.highlight .kp{color:#000000;font-weight:bold}.highlight .kr{color:#000000;font-weight:bold}.highlight .kt{color:#445588;font-weight:bold}.highlight .k,.highlight .kv{color:#000000;font-weight:bold}.highlight .mf{color:#009999}.highlight .mh{color:#009999}.highlight .il{color:#009999}.highlight .mi{color:#009999}.highlight .mo{color:#009999}.highlight .m,.highlight .mb,.highlight .mx{color:#009999}.highlight .sb{color:#d14}.highlight .sc{color:#d14}.highlight .sd{color:#d14}.highlight .s2{color:#d14}.highlight .se{color:#d14}.highlight .sh{color:#d14}.highlight .si{color:#d14}.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .bp{color:#999999}.highlight .nb{color:#0086B3}.highlight .nc{color:#445588;font-weight:bold}.highlight .no{color:#008080}.highlight .nd{color:#3c5d5d;font-weight:bold}.highlight .ni{color:#800080}.highlight .ne{color:#990000;font-weight:bold}.highlight .nf{color:#990000;font-weight:bold}.highlight .nl{color:#990000;font-weight:bold}.highlight .nn{color:#555555}.highlight .nt{color:#000080}.highlight .vc{color:#008080}.highlight .vg{color:#008080}.highlight .vi{color:#008080}.highlight .nv{color:#008080}.highlight .ow{color:#000000;font-weight:bold}.highlight .o{color:#000000;font-weight:bold}.highlight .w{color:#bbbbbb}.highlight{background-color:#f8f8f8}*{box-sizing:border-box}body{padding:0;margin:0;font-family:"Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;color:#606c71}a{color:#1e6bb8;text-decoration:none}a:hover{text-decoration:underline}.btn{display:inline-block;margin-bottom:1rem;color:rgba(255,255,255,0.7);background-color:rgba(255,255,255,0.08);border-color:rgba(255,255,255,0.2);border-style:solid;border-width:1px;border-radius:0.3rem;transition:color 0.2s, background-color 0.2s, border-color 0.2s}.btn:hover{color:rgba(255,255,255,0.8);text-decoration:none;background-color:rgba(255,255,255,0.2);border-color:rgba(255,255,255,0.3)}.btn+.btn{margin-left:1rem}@media screen and (min-width: 64em){.btn{padding:0.75rem 1rem}}@media screen and (min-width: 42em) and (max-width: 64em){.btn{padding:0.6rem 0.9rem;font-size:0.9rem}}@media screen and (max-width: 42em){.btn{display:block;width:100%;padding:0.75rem;font-size:0.9rem}.btn+.btn{margin-top:1rem;margin-left:0}}.page-header{color:#fff;text-align:center;background-color:#159957;background-image:linear-gradient(120deg, #155799, #159957)}@media screen and (min-width: 64em){.page-header{padding:5rem 6rem}}@media screen and (min-width: 42em) and (max-width: 64em){.page-header{padding:3rem 4rem}}@media screen and (max-width: 42em){.page-header{padding:2rem 1rem}}.project-name{margin-top:0;margin-bottom:0.1rem}@media screen and (min-width: 64em){.project-name{font-size:3.25rem}}@media screen and (min-width: 42em) and (max-width: 64em){.project-name{font-size:2.25rem}}@media screen and (max-width: 42em){.project-name{font-size:1.75rem}}.project-tagline{margin-bottom:2rem;font-weight:normal;opacity:0.7}@media screen and (min-width: 64em){.project-tagline{font-size:1.25rem}}@media screen and (min-width: 42em) and (max-width: 64em){.project-tagline{font-size:1.15rem}}@media screen and (max-width: 42em){.project-tagline{font-size:1rem}}.main-content{word-wrap:break-word}.main-content :first-child{margin-top:0}@media screen and (min-width: 64em){.main-content{max-width:64rem;padding:2rem 6rem;margin:0 auto;font-size:1.1rem}}@media screen and (min-width: 42em) and (max-width: 64em){.main-content{padding:2rem 4rem;font-size:1.1rem}}@media screen and (max-width: 42em){.main-content{padding:2rem 1rem;font-size:1rem}}.main-content img{max-width:100%}.main-content h1,.main-content h2,.main-content h3,.main-content h4,.main-content h5,.main-content h6{margin-top:2rem;margin-bottom:1rem;font-weight:normal;color:#159957}.main-content p{margin-bottom:1em}.main-content code{padding:2px 4px;font-family:Consolas, "Liberation Mono", Menlo, Courier, monospace;font-size:0.9rem;color:#567482;background-color:#f3f6fa;border-radius:0.3rem}.main-content pre{padding:0.8rem;margin-top:0;margin-bottom:1rem;font:1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;color:#567482;word-wrap:normal;background-color:#f3f6fa;border:solid 1px #dce6f0;border-radius:0.3rem}.main-content pre>code{padding:0;margin:0;font-size:0.9rem;color:#567482;word-break:normal;white-space:pre;background:transparent;border:0}.main-content .highlight{margin-bottom:1rem}.main-content .highlight pre{margin-bottom:0;word-break:normal}.main-content .highlight pre,.main-content pre{padding:0.8rem;overflow:auto;font-size:0.9rem;line-height:1.45;border-radius:0.3rem;-webkit-overflow-scrolling:touch}.main-content pre code,.main-content pre tt{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.main-content pre code:before,.main-content pre code:after,.main-content pre tt:before,.main-content pre tt:after{content:normal}.main-content ul,.main-content ol{margin-top:0}.main-content blockquote{padding:0 1rem;margin-left:0;color:#819198;border-left:0.3rem solid #dce6f0}.main-content blockquote>:first-child{margin-top:0}.main-content blockquote>:last-child{margin-bottom:0}.main-content table{display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all;-webkit-overflow-scrolling:touch}.main-content table th{font-weight:bold}.main-content table th,.main-content table td{padding:0.5rem 1rem;border:1px solid #e9ebec}.main-content dl{padding:0}.main-content dl dt{padding:0;margin-top:1rem;font-size:1rem;font-weight:bold}.main-content dl dd{padding:0;margin-bottom:1rem}.main-content hr{height:2px;padding:0;margin:1rem 0;background-color:#eff0f1;border:0}.site-footer{padding-top:2rem;margin-top:2rem;border-top:solid 1px #eff0f1}@media screen and (min-width: 64em){.site-footer{font-size:1rem}}@media screen and (min-width: 42em) and (max-width: 64em){.site-footer{font-size:1rem}}@media screen and (max-width: 42em){.site-footer{font-size:0.9rem}}.site-footer-owner{display:block;font-weight:bold}.site-footer-credits{color:#819198}.page-header a {color: #fff; text-decoration: none} 2 | 3 | -------------------------------------------------------------------------------- /docs_src/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: On a density conjecture about unit fractions 3 | --- 4 | # What is it about? 5 | 6 | The goal of this project is to formalize the main result of the preprint 7 | ['On a density conjecture about unit fractions'](https://arxiv.org/abs/2112.03726) 8 | using the [Lean theorem prover](https://leanprover.github.io/), 9 | mainly developed at [Microsoft Research](https://www.microsoft.com/en-us/research/) 10 | by [Leonardo de Moura](https://leodemoura.github.io/). 11 | This project structure is adapted from the infrastructure created by Patrick Massot 12 | for the [Sphere Eversion project](https://github.com/leanprover-community/sphere-eversion). 13 | 14 | 15 | More precisely we will prove that, any dense set of integers contains 16 | distinct integers whose reciprocals sum to 1. (This generalises a colouring 17 | result of Croot, and resolves an old open problem of Erdős and Graham.) For further 18 | details, precise statements, context, and so on, we refer to the preprint itself. 19 | 20 | ### Exploring and helping 21 | 22 | The best way to get started is to read the blueprint introduction, 23 | either in [pdf](blueprint.pdf) or [online](blueprint/sect0001.html). 24 | Then have a look at the [dependency graph](blueprint/dep_graph.html), 25 | paying special attention to blue items. 26 | Blue items are items that are ready to be formalized because their 27 | dependencies are formalized. 28 | For lemmas, a blue border means the statement is ready for formalization, 29 | and a blue background means the proof is ready for formalization. 30 | 31 | If you are interested in contributing, or have any questions about the project, 32 | please email bloom@maths.ox.ac.uk. 33 | -------------------------------------------------------------------------------- /docs_src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Unit fractions 7 | 8 | 9 | 10 | 11 | 12 | 13 | 32 | 35 | 36 | 37 | 44 | 45 |
46 | 47 | $body$ 48 | 49 | 53 |
54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /leanpkg.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "unit-fractions" 3 | version = "0.1" 4 | lean_version = "leanprover-community/lean:3.42.1" 5 | path = "src" 6 | 7 | [dependencies] 8 | mathlib = {git = "https://github.com/leanprover-community/mathlib", rev = "38ad656e278f3ce0e5c990ed8ab35e02792ee026"} 9 | -------------------------------------------------------------------------------- /scripts/count_sorry.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git grep -l sorry | grep -v scripts | xargs -I % sh -c 'nsorry=`grep sorry % | wc -l`; echo -n "$nsorry\t%\n"'; echo -en "Total:\t"; git grep sorry | grep -v scripts | wc -l 4 | -------------------------------------------------------------------------------- /scripts/detect_errors.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | from json import loads 3 | from pathlib import Path 4 | import sys 5 | 6 | def encode_msg_text_for_github(msg): 7 | # even though this is probably url quoting, we match the implementation at 8 | # https://github.com/actions/toolkit/blob/af821474235d3c5e1f49cee7c6cf636abb0874c4/packages/core/src/command.ts#L36-L94 9 | return msg.replace('%', '%25').replace('\r', '%0D').replace('\n', '%0A') 10 | 11 | def format_msg(msg): 12 | # Formatted for https://github.com/actions/toolkit/blob/master/docs/commands.md#log-level 13 | 14 | # mapping between lean severity levels and github levels. 15 | # github does not support info levels, which are emitted by `#check` etc: 16 | # https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message 17 | severity_map = {'information': 'warning'} 18 | severity = msg.get('severity') 19 | severity = severity_map.get(severity, severity) 20 | 21 | # We include the filename / line number information as both message and metadata, to ensure 22 | # that github shows it. 23 | msg_text = f"{msg['file_name']}:{msg.get('pos_line')}:{msg.get('pos_col')}:\n{msg.get('text')}" 24 | msg_text = encode_msg_text_for_github(msg_text) 25 | return f"::{severity} file={msg['file_name']},line={msg.get('pos_line')},col={msg.get('pos_col')}::{msg_text}" 26 | 27 | def write_and_print_noisy_files(noisy_files): 28 | with open('src/.noisy_files', 'w') as f: 29 | for file in noisy_files: 30 | f.write(file + '\n') 31 | print(file) 32 | 33 | noisy_files = set() 34 | for line in sys.stdin: 35 | msg = loads(line) 36 | print(format_msg(msg)) 37 | if msg.get('severity') == 'error': 38 | if len(noisy_files) > 0: 39 | print("Also, the following files were noisy:") 40 | write_and_print_noisy_files(noisy_files) 41 | sys.exit(1) 42 | elif msg.get('text', '').endswith("uses sorry"): 43 | # Using sorry should not cause the build to fail in this repository. 44 | continue 45 | else: 46 | noisy_files.add(str(Path(msg['file_name']).relative_to(Path.cwd()))) 47 | 48 | if len(noisy_files) > 0: 49 | print("Build succeeded, but the following files were noisy:") 50 | write_and_print_noisy_files(noisy_files) 51 | sys.exit(1) 52 | -------------------------------------------------------------------------------- /scripts/lean_version.lean: -------------------------------------------------------------------------------- 1 | -- Print the current version of lean, using logic copied from leanpkg. 2 | 3 | import system.io 4 | 5 | def lean_version_string_core := 6 | let (major, minor, patch) := lean.version in 7 | sformat!("{major}.{minor}.{patch}") 8 | 9 | def main : io unit := 10 | io.put_str_ln lean_version_string_core 11 | -------------------------------------------------------------------------------- /scripts/lint_project.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2020 Robert Y. Lewis. All rights reserved. 3 | Released under Apache 2.0 license as described in the file LICENSE. 4 | Authors: Robert Y. Lewis, Gabriel Ebner 5 | -/ 6 | 7 | import tactic.lint 8 | import system.io -- these are required 9 | import all -- then import everything, to parse the library for failing linters 10 | 11 | /-! 12 | # lint_mathlib 13 | Script that runs the linters listed in `mathlib_linters` on all of mathlib. 14 | As a side effect, the file `nolints.txt` is generated in the current 15 | directory. This script needs to be run in the root directory of mathlib. 16 | It assumes that files generated by `mk_all.sh` are present. 17 | This is used by the CI script for mathlib. 18 | Usage: `lean --run scripts/lint_mathlib.lean` 19 | -/ 20 | 21 | open native 22 | 23 | /-- 24 | Returns the contents of the `nolints.txt` file. 25 | -/ 26 | meta def mk_nolint_file (env : environment) (mathlib_path_len : ℕ) 27 | (results : list (name × linter × rb_map name string)) : format := do 28 | let failed_decls_by_file := rb_lmap.of_list (do 29 | (linter_name, _, decls) ← results, 30 | (decl_name, _) ← decls.to_list, 31 | let file_name := (env.decl_olean decl_name).get_or_else "", 32 | pure (file_name.popn mathlib_path_len, decl_name.to_string, linter_name.last)), 33 | format.intercalate format.line $ 34 | "import .all" :: 35 | "run_cmd tactic.skip" :: do 36 | (file_name, decls) ← failed_decls_by_file.to_list.reverse, 37 | "" :: ("-- " ++ file_name) :: do 38 | (decl, linters) ← (rb_lmap.of_list decls).to_list.reverse, 39 | pure $ "apply_nolint " ++ decl ++ " " ++ " ".intercalate linters 40 | 41 | /-- 42 | Parses the list of lines of the `nolints.txt` into an `rb_lmap` from linters to declarations. 43 | -/ 44 | meta def parse_nolints (lines : list string) : rb_lmap name name := 45 | rb_lmap.of_list $ do 46 | line ← lines, 47 | guard $ line.front = 'a', 48 | _ :: decl :: linters ← pure $ line.split (= ' ') | [], 49 | let decl := name.from_string decl, 50 | linter ← linters, 51 | pure (linter, decl) 52 | 53 | open io io.fs 54 | 55 | /-- 56 | Reads the `nolints.txt`, and returns it as an `rb_lmap` from linters to declarations. 57 | -/ 58 | meta def read_nolints_file (fn := "scripts/nolints.txt") : io (rb_lmap name name) := do 59 | cont ← io.fs.read_file fn, 60 | pure $ parse_nolints $ cont.to_string.split (= '\n') 61 | 62 | meta instance coe_tactic_to_io {α} : has_coe (tactic α) (io α) := 63 | ⟨run_tactic⟩ 64 | 65 | /-- 66 | Writes a file with the given contents. 67 | -/ 68 | meta def io.write_file (fn : string) (contents : string) : io unit := do 69 | h ← mk_file_handle fn mode.write, 70 | put_str h contents, 71 | close h 72 | 73 | /-- Returns the full path of the `src/` dir. 74 | We obtain this by starting with a "hackish way to get the `src` directory of mathlib" as implemented 75 | in `tactic.get_mathlib_dir`. We note that this is a rather ridiculous way to get the full path of 76 | `src/`. 77 | -/ 78 | meta def get_src_dir : tactic string := do 79 | ml ← tactic.get_mathlib_dir, 80 | pure $ ml.popn_back (string.length "_target/deps/mathlib/src/") ++ "src/" 81 | 82 | /-- Returns the declarations to be considered. -/ 83 | meta def lint_decls : tactic (list declaration) := do 84 | e ← tactic.get_env, 85 | src ← get_src_dir, 86 | pure $ e.filter $ λ d, e.is_prefix_of_file src d.to_name 87 | 88 | meta def enabled_linters : list name := 89 | -- Enable linters by editing this list. 90 | let enabled_linter_names := list.map (λ x, "linter." ++ x) [ 91 | "check_type", 92 | "def_lemma", 93 | -- "doc_blame", 94 | "unused_arguments", 95 | "dup_namespace", 96 | "ge_or_gt", 97 | "has_coe_to_fun", 98 | "decidable_classical", 99 | "inhabited_nonempty", 100 | "has_coe_variable", 101 | "class_structure", 102 | "fails_quickly", 103 | "dangerous_instance", 104 | "incorrect_type_class_argument", 105 | "impossible_instance", 106 | "has_inhabited_instance", 107 | "instance_priority", 108 | "simp_comm", 109 | "simp_var_head", 110 | "simp_nf" 111 | ] in 112 | mathlib_linters.filter $ λ x: name, x.to_string ∈ enabled_linter_names 113 | 114 | /-- Runs when called with `lean --run`. 115 | Edit the list in `enabled_linters` to run additional linters. 116 | We currently rely on mathlib to provide the `nolints.txt` file and do not maintain a separate 117 | `nolints.txt` file for unit-fractions. 118 | -/ 119 | meta def main : io unit := do 120 | env ← tactic.get_env, 121 | decls ← lint_decls, 122 | linters ← get_linters enabled_linters, 123 | path_len ← string.length <$> get_src_dir, 124 | let non_auto_decls := decls.filter (λ d, ¬ d.is_auto_or_internal env), 125 | results₀ ← lint_core decls non_auto_decls linters, 126 | nolint_file ← read_nolints_file, 127 | let results := (do 128 | (linter_name, linter, decls) ← results₀, 129 | [(linter_name, linter, (nolint_file.find linter_name).foldl rb_map.erase decls)]), 130 | io.print $ to_string $ format_linter_results env results decls non_auto_decls 131 | path_len "in unit-fractions" tt lint_verbosity.medium linters.length, 132 | io.write_file "nolints.txt" $ to_string $ mk_nolint_file env path_len results₀, 133 | if results.all (λ r, r.2.2.empty) then pure () else io.fail "" 134 | -------------------------------------------------------------------------------- /scripts/mk_all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: mk_all.sh [subdirectory] 3 | # 4 | # Examples: 5 | # ./scripts/mk_all.sh 6 | # ./scripts/mk_all.sh data/real 7 | # 8 | # Makes a mathlib/src/$directory/all.lean importing all files inside $directory. 9 | # If $directory is omitted, creates `mathlib/src/all.lean`. 10 | 11 | cd "$( dirname "${BASH_SOURCE[0]}" )"/../src 12 | if [[ $# = 1 ]]; then 13 | dir="$1" 14 | else 15 | dir="." 16 | fi 17 | 18 | find "$dir" -name \*.lean -not -name all.lean \ 19 | | sed 's,^\./,,;s,\.lean$,,;s,/,.,g;s,^,import ,' \ 20 | | sort >"$dir"/all.lean 21 | -------------------------------------------------------------------------------- /scripts/update_nolints.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -x 5 | 6 | # Exit if there are no changes relative to master 7 | git diff-index --quiet refs/remotes/origin/master -- scripts/nolints.txt && exit 0 8 | 9 | git checkout master 10 | git add scripts/nolints.txt 11 | git commit -m "chore(scripts): update nolints.txt" 12 | git pull origin master || exit 0 13 | git push origin master 14 | -------------------------------------------------------------------------------- /src/defs.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2021 Bhavik Mehta, Thomas Bloom. All rights reserved. 3 | Released under Apache 2.0 license as described in the file LICENSE. 4 | Authors: Bhavik Mehta, Thomas Bloom 5 | -/ 6 | 7 | import data.real.basic 8 | import analysis.special_functions.log.basic 9 | import analysis.special_functions.pow 10 | import order.filter.at_top_bot 11 | import number_theory.arithmetic_function 12 | import algebra.is_prime_pow 13 | 14 | /-! 15 | # Title 16 | 17 | This file should contain a formal proof of https://arxiv.org/pdf/2112.03726.pdf, but for now it 18 | contains associated results useful for that paper. 19 | -/ 20 | 21 | open_locale big_operators -- this lets me use ∑ and ∏ notation 22 | open filter real finset 23 | open nat (coprime) 24 | 25 | open_locale arithmetic_function classical 26 | noncomputable theory 27 | 28 | section 29 | 30 | variables (A : set ℕ) 31 | 32 | def partial_density (N : ℕ) : ℝ := ((range N).filter (λ n, n ∈ A)).card / N 33 | 34 | def upper_density : ℝ := limsup at_top (partial_density A) 35 | 36 | variables {A} 37 | 38 | lemma partial_density_sdiff_finset (N : ℕ) (S : finset ℕ) : 39 | partial_density A N ≤ partial_density (A \ S) N + S.card / N := 40 | begin 41 | rw [partial_density, partial_density, ←add_div], 42 | refine div_le_div_of_le (nat.cast_nonneg _) _, 43 | rw [←nat.cast_add, nat.cast_le], 44 | refine (card_le_of_subset _).trans (card_union_le _ _), 45 | intros x hx, 46 | simp only [mem_filter] at hx, 47 | simp only [mem_union, mem_filter, set.mem_diff, hx.1, hx.2, mem_coe, true_and], 48 | apply em' 49 | end 50 | 51 | lemma is_bounded_under_ge_partial_density : is_bounded_under (≥) at_top (partial_density A) := 52 | is_bounded_under_of ⟨0, λ x, div_nonneg (nat.cast_nonneg _) (nat.cast_nonneg _)⟩ 53 | 54 | lemma is_cobounded_under_le_partial_density : is_cobounded_under (≤) at_top (partial_density A) := 55 | is_bounded_under_ge_partial_density.is_cobounded_le 56 | 57 | lemma is_bounded_under_le_partial_density : is_bounded_under (≤) at_top (partial_density A) := 58 | is_bounded_under_of 59 | ⟨1, λ x, div_le_one_of_le 60 | (nat.cast_le.2 ((card_le_of_subset (filter_subset _ _)).trans (by simp))) (nat.cast_nonneg _)⟩ 61 | 62 | lemma upper_density_preserved {S : finset ℕ} : 63 | upper_density A = upper_density (A \ (S : set ℕ)) := 64 | begin 65 | apply ge_antisymm, 66 | { refine limsup_le_limsup _ is_cobounded_under_le_partial_density 67 | is_bounded_under_le_partial_density, 68 | refine eventually_of_forall (λ N, div_le_div_of_le (nat.cast_nonneg _) _), 69 | refine nat.mono_cast (card_le_of_subset _), 70 | letI := classical.prop_decidable, 71 | refine monotone_filter_right _ (λ n, _), 72 | simp only [set.mem_diff, le_Prop_eq, and_imp, implies_true_iff] {contextual := tt} }, 73 | rw le_iff_forall_pos_le_add, 74 | intros ε hε, 75 | rw ←sub_le_iff_le_add, 76 | apply le_Limsup_of_le is_bounded_under_le_partial_density, 77 | rintro a (ha : ∀ᶠ n : ℕ in at_top, _ ≤ _), 78 | rw sub_le_iff_le_add, 79 | apply Limsup_le_of_le is_cobounded_under_le_partial_density, 80 | change ∀ᶠ n : ℕ in at_top, _ ≤ _, 81 | have := tendsto_coe_nat_at_top_at_top.eventually_ge_at_top (↑S.card / ε), 82 | filter_upwards [ha, this, eventually_gt_at_top 0] with N hN hN' hN'', 83 | have : 0 < (N : ℝ) := nat.cast_pos.2 hN'', 84 | rw [div_le_iff hε, ←div_le_iff' this] at hN', 85 | exact (partial_density_sdiff_finset _ S).trans (add_le_add hN hN'), 86 | end 87 | 88 | lemma frequently_nat_of {ε : ℝ} (hA : ε < upper_density A) : 89 | ∃ᶠ (N : ℕ) in at_top, ε < ((range N).filter (λ n, n ∈ A)).card / N := 90 | frequently_lt_of_lt_limsup is_cobounded_under_le_partial_density hA 91 | 92 | lemma exists_nat_of {ε : ℝ} (hA : ε < upper_density A) : 93 | ∃ (N : ℕ), 0 < N ∧ ε < ((range N).filter (λ n, n ∈ A)).card / N := 94 | by simpa using frequently_at_top'.1 (frequently_nat_of hA) 0 95 | 96 | lemma exists_density_of {ε : ℝ} (hA : ε < upper_density A) : 97 | ∃ (N : ℕ), 0 < N ∧ ε * N < ((range N).filter (λ n, n ∈ A)).card := 98 | begin 99 | obtain ⟨N, hN, hN'⟩ := exists_nat_of hA, 100 | refine ⟨N, hN, _⟩, 101 | rwa lt_div_iff at hN', 102 | rwa nat.cast_pos 103 | end 104 | 105 | lemma upper_density_nonneg : 0 ≤ upper_density A := 106 | begin 107 | refine le_limsup_of_frequently_le _ is_bounded_under_le_partial_density, 108 | exact frequently_of_forall (λ x, div_nonneg (nat.cast_nonneg _) (nat.cast_nonneg _)), 109 | end 110 | 111 | end 112 | 113 | -- This is R(A) in the paper. 114 | def rec_sum (A : finset ℕ) : ℚ := ∑ n in A, 1/n 115 | 116 | lemma rec_sum_bUnion_disjoint {A : finset (finset ℕ)} 117 | (hA : (A : set (finset ℕ)).pairwise_disjoint id) : rec_sum (A.bUnion id) = ∑ s in A, rec_sum s := 118 | by simp only [rec_sum, sum_bUnion hA, id.def] 119 | 120 | lemma rec_sum_disjoint {A B : finset ℕ} (h : disjoint A B) : 121 | rec_sum (A ∪ B) = rec_sum A + rec_sum B := 122 | by simp only [rec_sum, sum_union h] 123 | 124 | @[simp] lemma rec_sum_empty : rec_sum ∅ = 0 := by simp [rec_sum] 125 | 126 | lemma rec_sum_nonneg {A : finset ℕ} : 0 ≤ rec_sum A := 127 | sum_nonneg (λ i hi, div_nonneg zero_le_one (nat.cast_nonneg _)) 128 | 129 | lemma rec_sum_mono {A₁ A₂ : finset ℕ} (h : A₁ ⊆ A₂) : rec_sum A₁ ≤ rec_sum A₂ := 130 | sum_le_sum_of_subset_of_nonneg h (λ _ _ _, div_nonneg zero_le_one (nat.cast_nonneg _)) 131 | 132 | -- can make this stronger without 0 ∉ A but we never care about that case 133 | lemma rec_sum_eq_zero_iff {A : finset ℕ} (hA : 0 ∉ A) : rec_sum A = 0 ↔ A = ∅ := 134 | begin 135 | symmetry, 136 | split, 137 | { rintro rfl, 138 | simp }, 139 | simp_rw [rec_sum, one_div], 140 | rw [sum_eq_zero_iff_of_nonneg (λ i hi, _)], 141 | { intro h, 142 | simp only [one_div, inv_eq_zero, nat.cast_eq_zero] at h, 143 | apply eq_empty_of_forall_not_mem, 144 | intros x hx, 145 | cases h x hx, 146 | apply hA hx }, 147 | exact inv_nonneg.2 (nat.cast_nonneg _), 148 | end 149 | 150 | lemma nonempty_of_rec_sum_recip {A : finset ℕ} {d : ℕ} (hd : 1 ≤ d) : 151 | rec_sum A = 1 / d → A.nonempty := 152 | begin -- should be able to simplify this 153 | intro h, 154 | rw [nonempty_iff_ne_empty], 155 | rintro rfl, 156 | simp only [one_div, zero_eq_inv, rec_sum_empty] at h, 157 | have : 0 < d := hd, 158 | exact this.ne (by exact_mod_cast h), 159 | end 160 | 161 | /-- 162 | This is A_q in the paper. 163 | -/ 164 | def local_part (A : finset ℕ) (q : ℕ) : finset ℕ := A.filter (λ n, q ∣ n ∧ coprime q (n / q)) 165 | 166 | lemma mem_local_part {A : finset ℕ} {q : ℕ} (n : ℕ) : 167 | n ∈ local_part A q ↔ n ∈ A ∧ q ∣ n ∧ coprime q (n / q) := 168 | by rw [local_part, mem_filter] 169 | 170 | lemma local_part_mono {A₁ A₂ : finset ℕ} {q : ℕ} (h : A₁ ⊆ A₂) : 171 | local_part A₁ q ⊆ local_part A₂ q := 172 | filter_subset_filter _ h 173 | 174 | lemma local_part_subset {A : finset ℕ} {q : ℕ} : 175 | local_part A q ⊆ A := 176 | filter_subset _ _ 177 | 178 | lemma zero_mem_local_part_iff {A : finset ℕ} {q : ℕ} (hA : 0 ∉ A) : 179 | 0 ∉ local_part A q := 180 | λ i, hA (local_part_subset i) 181 | 182 | /-- 183 | This is Q_A in the paper. The definition looks a bit different, but `mem_ppowers_in_set` shows 184 | it's the same thing. 185 | -/ 186 | def ppowers_in_set (A : finset ℕ) : finset ℕ := 187 | A.bUnion (λ n, n.divisors.filter (λ q, is_prime_pow q ∧ coprime q (n / q))) 188 | 189 | @[simp] lemma ppowers_in_set_empty : ppowers_in_set ∅ = ∅ := bUnion_empty 190 | 191 | lemma ppowers_in_set_insert_zero (A : finset ℕ) : ppowers_in_set (insert 0 A) = ppowers_in_set A := 192 | by rw [ppowers_in_set, ppowers_in_set, bUnion_insert, nat.divisors_zero, filter_empty, empty_union] 193 | 194 | lemma ppowers_in_set_erase_zero (A : finset ℕ) : ppowers_in_set (A.erase 0) = ppowers_in_set A := 195 | begin 196 | by_cases 0 ∈ A, 197 | { rw [←ppowers_in_set_insert_zero, insert_erase h] }, 198 | { rw finset.erase_eq_of_not_mem h }, 199 | end 200 | 201 | lemma mem_ppowers_in_set {A : finset ℕ} {q : ℕ} : 202 | q ∈ ppowers_in_set A ↔ is_prime_pow q ∧ (local_part A q).nonempty := 203 | begin 204 | simp only [ppowers_in_set, mem_bUnion, mem_filter, exists_prop, nat.mem_divisors, 205 | finset.nonempty, mem_local_part, ←exists_and_distrib_left], 206 | refine exists_congr (λ i, _), 207 | split, 208 | { rintro ⟨h₁, h₂, h₃, h₄⟩, 209 | exact ⟨h₃, h₁, h₂.1, h₄⟩ }, 210 | { rintro ⟨h₁, h₂, h₃, h₄⟩, 211 | refine ⟨h₂, ⟨h₃, _⟩, h₁, h₄⟩, 212 | rintro rfl, 213 | simp only [nat.zero_div, nat.coprime_zero_right] at h₄, 214 | exact h₁.ne_one h₄ }, 215 | end 216 | 217 | lemma zero_not_mem_ppowers_in_set {A : finset ℕ} : 0 ∉ ppowers_in_set A := 218 | λ t, not_is_prime_pow_zero (mem_ppowers_in_set.1 t).1 219 | 220 | lemma nat.pow_eq_one_iff {n k : ℕ} : n ^ k = 1 ↔ n = 1 ∨ k = 0 := 221 | begin 222 | rcases eq_or_ne k 0 with rfl | hk, 223 | { simp }, 224 | { simp [pow_eq_one_iff, hk] }, 225 | end 226 | 227 | lemma coprime_div_iff {n p k : ℕ} (hp : p.prime) (hn : p ^ k ∣ n) (hk : k ≠ 0) : 228 | nat.coprime (p^k) (n / p^k) → k = n.factorization p := 229 | begin 230 | rcases eq_or_ne n 0 with rfl | hn', 231 | { simp [nat.pow_eq_one_iff, hp.ne_one] }, 232 | intro h, 233 | have := nat.factorization_mul_of_coprime h, 234 | rw [nat.mul_div_cancel' hn] at this, 235 | rw [this, hp.factorization_pow, finsupp.coe_add, pi.add_apply, finsupp.single_eq_same, 236 | self_eq_add_right, ←finsupp.not_mem_support_iff], 237 | intro i, 238 | apply nat.factorization_disjoint_of_coprime h, 239 | simp only [inf_eq_inter, mem_inter], 240 | refine ⟨_, i⟩, 241 | simp only [nat.support_factorization], 242 | rw [nat.prime_pow_prime_divisor hk hp, finset.mem_singleton], 243 | end 244 | 245 | lemma factorization_disjoint_iff {a b : ℕ} (ha : a ≠ 0) (hb : b ≠ 0) : 246 | disjoint a.factorization.support b.factorization.support ↔ a.coprime b := 247 | begin 248 | rw ←@not_not (a.coprime b), 249 | simp [disjoint_left, nat.prime.not_coprime_iff_dvd, nat.mem_factors ha, nat.mem_factors hb] 250 | {contextual := tt}, 251 | end 252 | 253 | lemma factorization_eq_iff {n p k : ℕ} (hp : p.prime) (hk : k ≠ 0) : 254 | p ^ k ∣ n ∧ (p ^ k).coprime (n / p ^ k) ↔ n.factorization p = k := 255 | begin 256 | split, 257 | { rintro ⟨h₁, h₂⟩, 258 | rw ←coprime_div_iff hp h₁ hk h₂ }, 259 | intro hk', 260 | have : p ^ k ∣ n, 261 | { rw ←hk', 262 | exact nat.pow_factorization_dvd n p }, 263 | have hn : n ≠ 0, 264 | { rintro rfl, 265 | apply hk, 266 | simpa using hk'.symm }, 267 | refine ⟨this, _⟩, 268 | rw ←factorization_disjoint_iff (pow_ne_zero _ hp.ne_zero), 269 | { rw [nat.factorization_div this, hp.factorization_pow, finsupp.support_single_ne_zero _ hk, 270 | disjoint_singleton_left, finsupp.mem_support_iff, finsupp.coe_tsub, pi.sub_apply, ne.def, 271 | tsub_eq_zero_iff_le, not_not, finsupp.single_eq_same, hk'] }, 272 | rw [ne.def, nat.div_eq_zero_iff (pow_pos hp.pos _), not_lt], 273 | apply nat.le_of_dvd hn.bot_lt this, 274 | end 275 | 276 | lemma mem_ppowers_in_set' {A : finset ℕ} {p k : ℕ} (hp : p.prime) (hk : k ≠ 0) : 277 | p ^ k ∈ ppowers_in_set A ↔ ∃ n ∈ A, nat.factorization n p = k := 278 | begin 279 | rw [mem_ppowers_in_set, and_iff_right (hp.is_prime_pow.pow hk)], 280 | simp only [finset.nonempty, mem_local_part, exists_prop], 281 | refine exists_congr (λ n, and_congr_right' _), 282 | rw factorization_eq_iff hp hk, 283 | end 284 | 285 | lemma mem_ppowers_in_set'' {A : finset ℕ} {n p : ℕ} (hn : n ∈ A) (hpk : n.factorization p ≠ 0) : 286 | p ^ n.factorization p ∈ ppowers_in_set A := 287 | (mem_ppowers_in_set' (nat.prime_of_mem_factorization (finsupp.mem_support_iff.2 hpk)) hpk).2 288 | ⟨_, hn, rfl⟩ 289 | 290 | lemma ppowers_in_set_subset { A B : finset ℕ} (hAB : A ⊆ B) : 291 | ppowers_in_set A ⊆ ppowers_in_set B := 292 | bUnion_subset_bUnion_of_subset_left _ hAB 293 | 294 | lemma ppowers_in_set_nonempty {A : finset ℕ} (hA : ∃ n ∈ A, 2 ≤ n) : 295 | (ppowers_in_set A).nonempty := 296 | begin 297 | obtain ⟨n, hn, hn'⟩ := hA, 298 | have : n ≠ 1, 299 | { linarith }, 300 | rw nat.ne_one_iff_exists_prime_dvd at this, 301 | obtain ⟨p, hp₁, hp₂⟩ := this, 302 | refine ⟨p ^ _, (mem_ppowers_in_set' hp₁ _).2 ⟨n, hn, rfl⟩⟩, 303 | rwa [←finsupp.mem_support_iff, nat.support_factorization, list.mem_to_finset, 304 | nat.mem_factors_iff_dvd _ hp₁], 305 | linarith 306 | end 307 | 308 | lemma ppowers_in_set_eq_empty {A : finset ℕ} (hA : ppowers_in_set A = ∅) : 309 | ∀ n ∈ A, n < 2 := 310 | begin 311 | contrapose hA, 312 | rw [←ne.def, ←finset.nonempty_iff_ne_empty], 313 | apply ppowers_in_set_nonempty, 314 | simpa using hA 315 | end 316 | 317 | lemma ppowers_in_set_eq_empty' {A : finset ℕ} (hA : ppowers_in_set A = ∅) (hA' : 0 ∉ A): 318 | A.lcm id = 1 := 319 | begin 320 | have : A ⊆ {1}, 321 | { intros n hn, 322 | have := ppowers_in_set_eq_empty hA n hn, 323 | interval_cases n, 324 | { trivial }, 325 | simp }, 326 | rw finset.subset_singleton_iff at this, 327 | rcases this with rfl | rfl; 328 | simp, 329 | end 330 | 331 | -- This is R(A;q) in the paper. 332 | def rec_sum_local (A : finset ℕ) (q : ℕ) : ℚ := ∑ n in local_part A q, q / n 333 | 334 | lemma rec_sum_local_disjoint {A B : finset ℕ} {q : ℕ} (h : disjoint A B) : 335 | rec_sum_local (A ∪ B) q = rec_sum_local A q + rec_sum_local B q := 336 | by { rw [rec_sum_local, local_part, filter_union, sum_union (disjoint_filter_filter h)], refl } 337 | 338 | lemma rec_sum_local_mono {A₁ A₂ : finset ℕ} {q : ℕ} (h : A₁ ⊆ A₂) : 339 | rec_sum_local A₁ q ≤ rec_sum_local A₂ q := 340 | sum_le_sum_of_subset_of_nonneg (local_part_mono h) (λ i _ _, div_nonneg (by simp) (by simp)) 341 | 342 | def ppower_rec_sum (A : finset ℕ) : ℚ := 343 | ∑ q in ppowers_in_set A, 1 / q 344 | 345 | lemma ppower_rec_sum_mono {A₁ A₂ : finset ℕ} (h : A₁ ⊆ A₂) : 346 | ppower_rec_sum A₁ ≤ ppower_rec_sum A₂ := 347 | sum_le_sum_of_subset_of_nonneg (ppowers_in_set_subset h) (by simp) 348 | 349 | -- Replace nat.prime here with prime_power 350 | def is_smooth (y : ℝ) (n : ℕ) : Prop := ∀ q : ℕ, is_prime_pow q → q ∣ n → (q : ℝ) ≤ y 351 | 352 | def arith_regular (N : ℕ) (A : finset ℕ) : Prop := 353 | ∀ n ∈ A, ((99 : ℝ) / 100) * log (log N) ≤ ω n ∧ (ω n : ℝ) ≤ 2 * log (log N) 354 | 355 | lemma arith_regular.subset {N : ℕ} {A A' : finset ℕ} (hA : arith_regular N A) (hA' : A' ⊆ A) : 356 | arith_regular N A' := 357 | λ n hn, hA n (hA' hn) 358 | 359 | -- This is the set D_I 360 | def interval_rare_ppowers (I : finset ℤ) (A : finset ℕ) (K : ℝ) : finset ℕ := 361 | (ppowers_in_set A).filter $ λ q, ↑((local_part A q).filter (λ n, ∀ x ∈ I, ¬ ↑n ∣ x)).card < K / q 362 | 363 | lemma interval_rare_ppowers_subset (I : finset ℤ) {A : finset ℕ} (K : ℝ) : 364 | interval_rare_ppowers I A K ⊆ ppowers_in_set A := 365 | filter_subset _ _ 366 | 367 | -- This is the awkward condition that 'bridges' the hypothesis of the Fourier stuff 368 | -- with the conclusion of the combinatorial bits 369 | def good_condition (A : finset ℕ) (K T L : ℝ) : Prop := 370 | (∀ (t : ℝ) (I : finset ℤ), I = finset.Icc ⌈t - K / 2⌉ ⌊t + K / 2⌋ → 371 | T ≤ (A.filter (λ n, ∀ x ∈ I, ¬ ↑n ∣ x)).card ∨ 372 | ∃ x ∈ I, ∀ q ∈ interval_rare_ppowers I A L, ↑q ∣ x) 373 | -------------------------------------------------------------------------------- /src/for_mathlib/integral_rpow.lean: -------------------------------------------------------------------------------- 1 | /- 2 | Copyright (c) 2022 Bhavik Mehta. All rights reserved. 3 | Released under Apache 2.0 license as described in the file LICENSE. 4 | Authors: Bhavik Mehta 5 | -/ 6 | 7 | import analysis.special_functions.integrals 8 | import analysis.special_functions.pow 9 | import measure_theory.integral.integral_eq_improper 10 | 11 | noncomputable theory 12 | 13 | open_locale big_operators nnreal filter topological_space 14 | 15 | open asymptotics filter set real measure_theory 16 | 17 | lemma integral_Ioi_rpow_tendsto_aux {a r : ℝ} (hr : r < -1) (ha : 0 < a) 18 | {ι : Type*} {b : ι → ℝ} {l : filter ι} (hb : tendsto b l at_top) : 19 | tendsto (λ i, ∫ x in a..b i, x ^ r) l (nhds (-a ^ (r + 1) / (r + 1))) := 20 | begin 21 | suffices : 22 | tendsto (λ i, ∫ x in a..b i, x ^ r) l (nhds (0 / (r + 1) - a ^ (r + 1) / (r + 1))), 23 | { simpa [neg_div] using this }, 24 | have : ∀ᶠ i in l, ∫ x in a..b i, x ^ r = (b i) ^ (r + 1) / (r + 1) - a ^ (r + 1) / (r + 1), 25 | { filter_upwards [hb.eventually (eventually_ge_at_top a)], 26 | intros i hi, 27 | rw [←sub_div, ←integral_rpow (or.inr ⟨hr.ne, not_mem_interval_of_lt ha (ha.trans_le hi)⟩)], }, 28 | rw tendsto_congr' this, 29 | refine tendsto.sub_const _ (tendsto.div_const _), 30 | rw ←neg_neg (r+1), 31 | apply (tendsto_rpow_neg_at_top _).comp hb, 32 | simpa using hr 33 | end 34 | 35 | -- TODO: Move to mathlib 36 | lemma integrable_on_rpow_Ioi {a r : ℝ} (hr : r < -1) (ha : 0 < a) : 37 | integrable_on (λ x, x ^ r) (Ioi a) := 38 | begin 39 | have hb : tendsto (λ (x : ℝ≥0), a + x) at_top at_top := 40 | tendsto_at_top_add_const_left _ _ (nnreal.tendsto_coe_at_top.2 tendsto_id), 41 | have : tendsto (λ (i : ℝ≥0), ∫ x in a..(a + i), ∥x ^ r∥) at_top (nhds (-a ^ (r + 1) / (r + 1))), 42 | { refine (integral_Ioi_rpow_tendsto_aux hr ha hb).congr (λ x, _), 43 | refine interval_integral.integral_congr (λ i hi, _), 44 | apply (real.norm_of_nonneg (real.rpow_nonneg_of_nonneg _ _)).symm, 45 | exact ha.le.trans ((by simp : _ ≤ _).trans hi.1) }, 46 | refine integrable_on_Ioi_of_interval_integral_norm_tendsto _ _ (λ i, _) hb this, 47 | refine (continuous_on.integrable_on_Icc _).mono_set Ioc_subset_Icc_self, 48 | exact continuous_on_id.rpow_const (λ x hx, or.inl (ha.trans_le hx.1).ne'), 49 | end 50 | 51 | -- TODO: Move to mathlib 52 | lemma integral_rpow_Ioi {a r : ℝ} (hr : r < -1) (ha : 0 < a) : 53 | ∫ x in Ioi a, x ^ r = - a ^ (r + 1) / (r + 1) := 54 | tendsto_nhds_unique 55 | (interval_integral_tendsto_integral_Ioi _ (integrable_on_rpow_Ioi hr ha) tendsto_id) 56 | (integral_Ioi_rpow_tendsto_aux hr ha tendsto_id) 57 | 58 | -- TODO: Move to mathlib 59 | lemma integrable_on_rpow_inv_Ioi {a r : ℝ} (hr : 1 < r) (ha : 0 < a) : 60 | integrable_on (λ x, (x ^ r)⁻¹) (Ioi a) := 61 | (integrable_on_rpow_Ioi (neg_lt_neg hr) ha).congr_fun (λ x hx, rpow_neg (ha.trans hx).le _) 62 | measurable_set_Ioi 63 | 64 | -- TODO: Move to mathlib 65 | lemma integral_rpow_inv {a r : ℝ} (hr : 1 < r) (ha : 0 < a) : 66 | ∫ x in Ioi a, (x ^ r)⁻¹ = a ^ (1 - r) / (r - 1) := 67 | begin 68 | rw [←set_integral_congr, integral_rpow_Ioi (neg_lt_neg hr) ha, neg_div, ←div_neg, neg_add', 69 | neg_neg, neg_add_eq_sub], 70 | { apply measurable_set_Ioi }, 71 | exact λ x hx, (rpow_neg (ha.trans hx).le _) 72 | end 73 | 74 | -- TODO: Move to mathlib 75 | lemma integrable_on_zpow_Ioi {a : ℝ} {n : ℤ} (hn : n < -1) (ha : 0 < a) : 76 | integrable_on (λ x, x ^ n) (Ioi a) := 77 | by exact_mod_cast integrable_on_rpow_Ioi (show (n : ℝ) < -1, by exact_mod_cast hn) ha 78 | 79 | -- TODO: Move to mathlib 80 | lemma integral_zpow_Ioi {a : ℝ} {n : ℤ} (hn : n < -1) (ha : 0 < a) : 81 | ∫ x in Ioi a, x ^ n = - a ^ (n + 1) / (n + 1) := 82 | by exact_mod_cast integral_rpow_Ioi (show (n : ℝ) < -1, by exact_mod_cast hn) ha 83 | 84 | -- TODO: Move to mathlib 85 | lemma integrable_on_zpow_inv_Ioi {a : ℝ} {n : ℤ} (hn : 1 < n) (ha : 0 < a) : 86 | integrable_on (λ x, (x ^ n)⁻¹) (Ioi a) := 87 | (integrable_on_zpow_Ioi (neg_lt_neg hn) ha).congr_fun (by simp) measurable_set_Ioi 88 | 89 | -- TODO: Move to mathlib 90 | lemma integral_zpow_inv_Ioi {a : ℝ} {n : ℤ} (hn : 1 < n) (ha : 0 < a) : 91 | ∫ x in Ioi a, (x ^ n)⁻¹ = a ^ (1 - n) / (n - 1) := 92 | begin 93 | simp_rw [←zpow_neg, integral_zpow_Ioi (neg_lt_neg hn) ha, neg_div, ←div_neg, neg_add', 94 | int.cast_neg, neg_neg, neg_add_eq_sub], 95 | end 96 | 97 | -- TODO: Move to mathlib 98 | lemma integrable_on_pow_inv_Ioi {a : ℝ} {n : ℕ} (hn : 1 < n) (ha : 0 < a) : 99 | integrable_on (λ x, (x ^ n)⁻¹) (Ioi a) := 100 | by exact_mod_cast integrable_on_zpow_inv_Ioi (show 1 < (n : ℤ), by exact_mod_cast hn) ha 101 | 102 | -- TODO: Move to mathlib 103 | lemma integral_pow_inv_Ioi {a : ℝ} {n : ℕ} (hn : 1 < n) (ha : 0 < a) : 104 | ∫ x in Ioi a, (x ^ n)⁻¹ = (a ^ (n - 1))⁻¹ / (n - 1) := 105 | by simp_rw [←zpow_coe_nat, integral_zpow_inv_Ioi (show 1 < (n : ℤ), by exact_mod_cast hn) ha, 106 | int.cast_coe_nat, ←zpow_neg, int.coe_nat_sub hn.le, neg_sub, int.coe_nat_one] 107 | -------------------------------------------------------------------------------- /src/for_mathlib/misc.lean: -------------------------------------------------------------------------------- 1 | import analysis.convex.specific_functions 2 | import analysis.special_functions.trigonometric.complex 3 | import algebra.is_prime_pow 4 | 5 | lemma int.Ico_succ_right {a b : ℤ} : finset.Ico a (b+1) = finset.Icc a b := 6 | by { ext x, simp only [finset.mem_Icc, finset.mem_Ico, int.lt_add_one_iff] } 7 | 8 | lemma int.Ioc_succ_right {a b : ℤ} (h : a ≤ b) : 9 | finset.Ioc a (b+1) = insert (b+1) (finset.Ioc a b) := 10 | begin 11 | ext x, 12 | simp only [finset.mem_Ioc, finset.mem_insert], 13 | rw [le_iff_lt_or_eq, int.lt_add_one_iff, or_comm, and_or_distrib_left, or_congr_left'], 14 | rw and_iff_right_of_imp, 15 | rintro rfl, 16 | exact int.lt_add_one_iff.2 h 17 | end 18 | 19 | lemma int.insert_Ioc_succ_left {a b : ℤ} (h : a < b) : 20 | insert (a+1) (finset.Ioc (a+1) b) = finset.Ioc a b := 21 | begin 22 | ext x, 23 | simp only [finset.mem_Ioc, finset.mem_insert], 24 | rw [or_and_distrib_left, eq_comm, ←le_iff_eq_or_lt, int.add_one_le_iff, and_congr_right'], 25 | rw or_iff_right_of_imp, 26 | rintro rfl, 27 | rwa int.add_one_le_iff, 28 | end 29 | 30 | lemma int.Ioc_succ_left {a b : ℤ} (h : a < b) : 31 | finset.Ioc (a+1) b = (finset.Ioc a b).erase (a+1) := 32 | begin 33 | rw [←@int.insert_Ioc_succ_left a b h, finset.erase_insert], 34 | simp only [finset.left_not_mem_Ioc, not_false_iff], 35 | end 36 | 37 | lemma int.Ioc_succ_succ {a b : ℤ} (h : a ≤ b) : 38 | finset.Ioc (a+1) (b+1) = (insert (b+1) (finset.Ioc a b)).erase (a+1) := 39 | begin 40 | rw [int.Ioc_succ_left, int.Ioc_succ_right h], 41 | rwa int.lt_add_one_iff, 42 | end 43 | 44 | lemma finset.Icc_subset_range_add_one {x y : ℕ} : finset.Icc x y ⊆ finset.range (y+1) := 45 | begin 46 | rw [finset.range_eq_Ico, nat.Ico_succ_right], 47 | exact finset.Icc_subset_Icc_left (nat.zero_le _), 48 | end 49 | 50 | lemma finset.Ico_union_Icc_eq_Icc {x y z : ℕ} (h₁ : x ≤ y) (h₂ : y ≤ z) : 51 | finset.Ico x y ∪ finset.Icc y z = finset.Icc x z := 52 | by rw [←finset.coe_inj, finset.coe_union, finset.coe_Ico, finset.coe_Icc, finset.coe_Icc, 53 | set.Ico_union_Icc_eq_Icc h₁ h₂] 54 | 55 | @[simp] lemma Ico_inter_Icc_consecutive {α : Type*} [linear_order α] 56 | [locally_finite_order α] (a b c : α) : finset.Ico a b ∩ finset.Icc b c = ∅ := 57 | begin 58 | refine finset.eq_empty_of_forall_not_mem (λ x hx, _), 59 | rw [finset.mem_inter, finset.mem_Ico, finset.mem_Icc] at hx, 60 | exact hx.1.2.not_le hx.2.1, 61 | end 62 | 63 | lemma Ico_disjoint_Icc_consecutive {α : Type*} [linear_order α] 64 | [locally_finite_order α] (a b c : α) : disjoint (finset.Ico a b) (finset.Icc b c) := 65 | (Ico_inter_Icc_consecutive a b c).le 66 | 67 | lemma finset.Icc_sdiff_Icc_right {x y z : ℕ} (h₁ : x ≤ y) (h₂ : y ≤ z) : 68 | finset.Icc x z \ finset.Icc y z = finset.Ico x y := 69 | begin 70 | rw ←finset.Ico_union_Icc_eq_Icc h₁ h₂, 71 | rw finset.union_sdiff_self, 72 | rw finset.sdiff_eq_self_of_disjoint, 73 | apply Ico_disjoint_Icc_consecutive, 74 | end 75 | 76 | lemma finset.Icc_sdiff_Icc_left {x y z : ℕ} (h₁ : z ≤ y) (h₂ : x ≤ z) : 77 | finset.Icc x y \ finset.Icc x z = finset.Ioc z y := 78 | begin 79 | ext m, 80 | simp only [finset.mem_Icc, finset.mem_sdiff, finset.mem_Ioc, not_and, not_le], 81 | exact ⟨λ h, ⟨h.2 h.1.1, h.1.2⟩, λ h, ⟨⟨h₂.trans h.1.le, h.2⟩, λ _, h.1⟩⟩, 82 | end 83 | 84 | lemma range_sdiff_Icc {x y : ℕ} (h : x ≤ y) : 85 | finset.range (y+1) \ finset.Icc x y = finset.Ico 0 x := 86 | begin 87 | rw [finset.range_eq_Ico, nat.Ico_succ_right, finset.Icc_sdiff_Icc_right (nat.zero_le _) h], 88 | end 89 | 90 | lemma Ici_diff_Icc {a b : ℝ} (hab : a ≤ b) : set.Ici a \ set.Icc a b = set.Ioi b := 91 | begin 92 | rw [←set.Icc_union_Ioi_eq_Ici hab, set.union_diff_left, set.diff_eq_self], 93 | rintro x ⟨⟨_, hx⟩, hx'⟩, 94 | exact not_le_of_lt hx' hx, 95 | end 96 | 97 | lemma Ioi_diff_Icc {a b : ℝ} (hab : a ≤ b) : set.Ioi a \ set.Ioc a b = set.Ioi b := 98 | begin 99 | rw [←set.Ioc_union_Ioi_eq_Ioi hab, set.union_diff_left, set.diff_eq_self, set.subset_def], 100 | simp, 101 | end 102 | 103 | open_locale big_operators 104 | 105 | @[simp, norm_cast] lemma rat.cast_sum {α β : Type*} [division_ring β] [char_zero β] (s : finset α) 106 | (f : α → ℚ) : 107 | ↑(∑ x in s, f x : ℚ) = (∑ x in s, (f x : β)) := 108 | (rat.cast_hom β).map_sum f s 109 | 110 | lemma finset.prod_rpow {ι : Type*} {s : finset ι} {f : ι → ℝ} 111 | (c : ℝ) (hf : ∀ x ∈ s, 0 ≤ f x) : 112 | (∏ i in s, f i) ^ c = ∏ i in s, f i ^ c := 113 | begin 114 | induction s using finset.cons_induction_on with a s has ih generalizing hf, 115 | { simp }, 116 | simp only [finset.mem_cons, forall_eq_or_imp] at hf, 117 | rw [finset.prod_cons has, real.mul_rpow hf.1 (finset.prod_nonneg hf.2), 118 | finset.prod_cons has, ih hf.2], 119 | end 120 | 121 | lemma one_le_prod {ι R : Type*} [ordered_comm_semiring R] {f : ι → R} {s : finset ι} 122 | (h1 : ∀ i ∈ s, 1 ≤ f i) : 1 ≤ ∏ i in s, f i := 123 | (finset.prod_le_prod (λ _ _, zero_le_one) h1).trans' (by simp) 124 | 125 | lemma finset.filter_comm {α : Type*} (p q : α → Prop) [decidable_eq α] 126 | [decidable_pred p] [decidable_pred q] (s : finset α) : 127 | (s.filter p).filter q = (s.filter q).filter p := 128 | by simp only [finset.filter_filter, and_comm] 129 | 130 | lemma real.le_rpow_self_of_one_le {x r : ℝ} (hx : 1 ≤ x) (hr : 1 ≤ r) : 131 | x ≤ x ^ r := 132 | by simpa using real.rpow_le_rpow_of_exponent_le hx hr 133 | 134 | lemma real.le_rpow_self_of {x : ℝ} {r : ℝ} (hx₀ : 0 ≤ x) (hx₁ : x ≤ 1) (h_one_le : r ≤ 1) : 135 | x ≤ x ^ r := 136 | begin 137 | rcases eq_or_ne r 0 with rfl | hr, 138 | { simp [hx₁] }, 139 | rcases eq_or_lt_of_le hx₀ with rfl | hx₀, 140 | { rw real.zero_rpow hr }, 141 | simpa using real.rpow_le_rpow_of_exponent_ge hx₀ hx₁ h_one_le 142 | end 143 | 144 | @[to_additive] 145 | lemma prod_powerset_compl {α β : Type*} [decidable_eq α] [comm_monoid β] 146 | (s : finset α) (f : finset α → β) : 147 | ∏ x in s.powerset, f (s \ x) = ∏ x in s.powerset, f x := 148 | begin 149 | refine finset.prod_bij' (λ x _, s \ x) (by simp) (λ _ _, rfl) (λ x _, s \ x) (by simp) _ _; 150 | simp [finset.inter_eq_right_iff_subset], 151 | end 152 | -------------------------------------------------------------------------------- /tasks.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | from pathlib import Path 4 | from invoke import run, task 5 | 6 | from mathlibtools.lib import LeanProject 7 | 8 | from blueprint.tasks import web, bp, print, serve 9 | 10 | ROOT = Path(__file__).parent 11 | 12 | @task 13 | def doc(ctx): 14 | cwd = os.getcwd() 15 | os.chdir(ROOT/'docs_src') 16 | for path in (ROOT/'docs_src').glob('*.md'): 17 | run(f'pandoc -t html --mathjax -f markdown+tex_math_dollars+raw_tex {path.name} --template template.html -o ../docs/{path.with_suffix(".html").name}') 18 | os.chdir(cwd) 19 | 20 | @task 21 | def decls(ctx): 22 | proj = LeanProject.from_path(ROOT) 23 | proj.pickle_decls(ROOT/'decls.pickle') 24 | 25 | @task(doc, decls, bp, web) 26 | def all(ctx): 27 | shutil.rmtree(ROOT/'docs'/'blueprint', ignore_errors=True) 28 | shutil.copytree(ROOT/'blueprint'/'web', ROOT/'docs'/'blueprint') 29 | shutil.copy2(ROOT/'blueprint'/'print'/'print.pdf', ROOT/'docs'/'blueprint.pdf') 30 | 31 | @task(doc, web) 32 | def html(ctx): 33 | shutil.rmtree(ROOT/'docs'/'blueprint', ignore_errors=True) 34 | shutil.copytree(ROOT/'blueprint'/'web', ROOT/'docs'/'blueprint') 35 | --------------------------------------------------------------------------------