rcas 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. checksums.yaml +7 -0
  2. data/CITATION.cff +17 -0
  3. data/DESIGN.md +783 -0
  4. data/LICENSE +21 -0
  5. data/MANUAL.md +6265 -0
  6. data/README.md +267 -0
  7. data/bin/rcas +9 -0
  8. data/bin/rcas-app +9 -0
  9. data/bin/rcas-chat +9 -0
  10. data/lib/rcas/algebraic.rb +481 -0
  11. data/lib/rcas/analysis.rb +966 -0
  12. data/lib/rcas/app/launcher.rb +203 -0
  13. data/lib/rcas/app/public/app.css +402 -0
  14. data/lib/rcas/app/public/app.js +449 -0
  15. data/lib/rcas/app/public/index.html +46 -0
  16. data/lib/rcas/app/server.rb +220 -0
  17. data/lib/rcas/app/window.rb +94 -0
  18. data/lib/rcas/app/worksheet.rb +290 -0
  19. data/lib/rcas/app.rb +168 -0
  20. data/lib/rcas/background.rb +758 -0
  21. data/lib/rcas/chat/assistant.rb +199 -0
  22. data/lib/rcas/chat/picker.rb +164 -0
  23. data/lib/rcas/chat/repl.rb +583 -0
  24. data/lib/rcas/chat/session.rb +137 -0
  25. data/lib/rcas/chat/settings.rb +71 -0
  26. data/lib/rcas/chat/style.rb +30 -0
  27. data/lib/rcas/chat/tool.rb +53 -0
  28. data/lib/rcas/chat/ui.rb +316 -0
  29. data/lib/rcas/chat/usage.rb +62 -0
  30. data/lib/rcas/chat/workspace.rb +132 -0
  31. data/lib/rcas/chat.rb +54 -0
  32. data/lib/rcas/coefficients.rb +170 -0
  33. data/lib/rcas/combinatorics.rb +274 -0
  34. data/lib/rcas/complex_parts.rb +160 -0
  35. data/lib/rcas/constants.rb +129 -0
  36. data/lib/rcas/core_ext.rb +35 -0
  37. data/lib/rcas/decide.rb +501 -0
  38. data/lib/rcas/decompositions.rb +241 -0
  39. data/lib/rcas/differentiate.rb +144 -0
  40. data/lib/rcas/discussion.rb +558 -0
  41. data/lib/rcas/distributions.rb +980 -0
  42. data/lib/rcas/dixon.rb +95 -0
  43. data/lib/rcas/docs.rb +321 -0
  44. data/lib/rcas/domains.rb +728 -0
  45. data/lib/rcas/expand.rb +174 -0
  46. data/lib/rcas/expression.rb +613 -0
  47. data/lib/rcas/factor.rb +605 -0
  48. data/lib/rcas/finite_field.rb +577 -0
  49. data/lib/rcas/fourier.rb +118 -0
  50. data/lib/rcas/fps.rb +678 -0
  51. data/lib/rcas/fraction.rb +126 -0
  52. data/lib/rcas/functions.rb +1136 -0
  53. data/lib/rcas/gcd.rb +112 -0
  54. data/lib/rcas/geometry.rb +266 -0
  55. data/lib/rcas/groebner.rb +162 -0
  56. data/lib/rcas/hold.rb +277 -0
  57. data/lib/rcas/hypothesis.rb +364 -0
  58. data/lib/rcas/inequalities.rb +689 -0
  59. data/lib/rcas/integral_functions.rb +260 -0
  60. data/lib/rcas/integrate.rb +1589 -0
  61. data/lib/rcas/integrate_substitutions.rb +434 -0
  62. data/lib/rcas/interpolate.rb +40 -0
  63. data/lib/rcas/irb.rb +146 -0
  64. data/lib/rcas/laplace.rb +159 -0
  65. data/lib/rcas/latex.rb +556 -0
  66. data/lib/rcas/lattice.rb +172 -0
  67. data/lib/rcas/linear_algebra.rb +117 -0
  68. data/lib/rcas/linear_program.rb +416 -0
  69. data/lib/rcas/lint.rb +79 -0
  70. data/lib/rcas/matrix.rb +531 -0
  71. data/lib/rcas/matrix_multiply.rb +202 -0
  72. data/lib/rcas/multimodular.rb +286 -0
  73. data/lib/rcas/named_polynomials.rb +274 -0
  74. data/lib/rcas/number_theory.rb +443 -0
  75. data/lib/rcas/numerics.rb +825 -0
  76. data/lib/rcas/ode.rb +488 -0
  77. data/lib/rcas/openmath/objects.rb +364 -0
  78. data/lib/rcas/openmath/phrasebook.rb +551 -0
  79. data/lib/rcas/openmath/popcorn.rb +518 -0
  80. data/lib/rcas/openmath/xml.rb +309 -0
  81. data/lib/rcas/openmath.rb +49 -0
  82. data/lib/rcas/petkovsek.rb +165 -0
  83. data/lib/rcas/piecewise.rb +488 -0
  84. data/lib/rcas/plot.rb +763 -0
  85. data/lib/rcas/plot3d.rb +419 -0
  86. data/lib/rcas/poly_matrix.rb +318 -0
  87. data/lib/rcas/poly_recurrence.rb +117 -0
  88. data/lib/rcas/polynomial.rb +466 -0
  89. data/lib/rcas/precision.rb +925 -0
  90. data/lib/rcas/printer.rb +150 -0
  91. data/lib/rcas/product.rb +155 -0
  92. data/lib/rcas/q_difference.rb +296 -0
  93. data/lib/rcas/q_functions.rb +158 -0
  94. data/lib/rcas/q_summation.rb +308 -0
  95. data/lib/rcas/q_zeilberger.rb +199 -0
  96. data/lib/rcas/random.rb +506 -0
  97. data/lib/rcas/rational_function.rb +186 -0
  98. data/lib/rcas/recurrence.rb +323 -0
  99. data/lib/rcas/render.rb +431 -0
  100. data/lib/rcas/results.rb +192 -0
  101. data/lib/rcas/scalar.rb +219 -0
  102. data/lib/rcas/series.rb +726 -0
  103. data/lib/rcas/simplify.rb +649 -0
  104. data/lib/rcas/solve.rb +2002 -0
  105. data/lib/rcas/special.rb +163 -0
  106. data/lib/rcas/statistics.rb +175 -0
  107. data/lib/rcas/steps.rb +835 -0
  108. data/lib/rcas/summation.rb +532 -0
  109. data/lib/rcas/trig.rb +264 -0
  110. data/lib/rcas/van_hoeij.rb +241 -0
  111. data/lib/rcas/vector.rb +175 -0
  112. data/lib/rcas/vector_calculus.rb +411 -0
  113. data/lib/rcas/version.rb +5 -0
  114. data/lib/rcas/zeilberger.rb +358 -0
  115. data/lib/rcas.rb +91 -0
  116. data/package.json +8 -0
  117. metadata +206 -0
data/README.md ADDED
@@ -0,0 +1,267 @@
1
+ <p align="center">
2
+ <img src="assets/rcas-logo.jpeg" alt="rcas - Ruby Computer Algebra System" width="480"><br>
3
+ <em>Computer Algebra To Fiddle Around With</em>™
4
+ </p>
5
+
6
+ # rcas
7
+
8
+ A computer algebra system that lives inside Ruby. Symbols are indeterminates,
9
+ the ordinary operators build expression trees, and irb is the REPL:
10
+
11
+ ```
12
+ $ bin/rcas
13
+ rcas> e = (x + 1) * (1 - x)
14
+ => (x + 1)*(1 - x)
15
+ rcas> e.expand
16
+ => 1 - x**2
17
+ rcas> integrate(exp(x) * sin(x), x)
18
+ => -(cos(x)*exp(x))/2 + exp(x)*sin(x)/2
19
+ rcas> solve(x**2 - 2, x)
20
+ => [-2**(1/2), 2**(1/2)]
21
+ ```
22
+
23
+ A minute of it, from exact arithmetic to typeset answers:
24
+
25
+ <p align="center">
26
+ <img src="assets/rcas-intro.gif" alt="a minute of rcas: exact arithmetic, calculus, solving, typeset output" width="840">
27
+ </p>
28
+
29
+ The longer tour through everything rcas can do is an eight-minute video,
30
+ [on YouTube](https://youtu.be/cdB88qxeqL8); the file itself is
31
+ [rcas-tour.mp4](https://github.com/no-dashes/rcas/releases/download/screencasts/rcas-tour.mp4),
32
+ kept with the releases rather than in the repository, so a clone stays small.
33
+ Both are built from a script of input lines by
34
+ [tools/screencast](tools/screencast) - the script is replayed against a real
35
+ session, so what you see is what rcas prints.
36
+
37
+ Every function explains itself, with the mathematics, the method and the
38
+ sources it follows:
39
+
40
+ ```
41
+ rcas> doc(:factor)
42
+ factor(obj, extension: nil, recombination: nil)
43
+ factor(x**2 - 1), factor(360), factor(f, extension: sqrt(2)); recombination: :van_hoeij, :zassenhaus or :auto
44
+ also: e.factor
45
+ maths: Write a polynomial as a unit times powers of irreducible factors,
46
+ over the integers or rationals (or an algebraic extension), or an
47
+ integer as a product of primes. The factorization is unique.
48
+ method: Squarefree decomposition [Yun76], factoring modulo a prime by
49
+ Cantor-Zassenhaus [CZ81], Hensel lifting of that factorization
50
+ and recombination - by subsets [Zas69], or for many modular
51
+ factors by van Hoeij's lattice [vHo02]; ...
52
+ sources: [Yun76] D. Y. Y. Yun, On square-free decomposition algorithms,
53
+ Proc. SYMSAC '76, ACM 1976, 26-35.
54
+ https://doi.org/10.1145/800205.806320
55
+ ...
56
+ ```
57
+
58
+ This file covers installation and getting a session running. Everything
59
+ about *using* rcas, from expressions and calculus to polynomial rings,
60
+ finite fields, linear algebra and differential equations, is in
61
+ [MANUAL.md](MANUAL.md), whose transcripts are checked by the test suite.
62
+ What rcas does *not* do is listed in
63
+ [MANUAL.md, What is not implemented](MANUAL.md#what-is-not-implemented);
64
+ how it is built and how it compares with Sage, SymPy, MuPAD and Maxima is
65
+ in [DESIGN.md](DESIGN.md). How it was made, and how it was checked, is at
66
+ the [end of this file](#how-and-why).
67
+
68
+ ## Requirements
69
+
70
+ - Ruby 3.3 or newer (developed on 3.3.10; the suite also passes under
71
+ 4.0, whose default parser is Prism). No gems are needed for the core
72
+ library or `bin/rcas`; everything is standard library.
73
+ - Big-number performance benefits from a Ruby built with GMP
74
+ (`ruby -e 'p Integer::GMP_VERSION'` shows whether yours is); factoring
75
+ large polynomials is noticeably slower without it.
76
+
77
+ Optional, only for the typeset output and the chat front end:
78
+
79
+ - Plots need nothing: `plot(sin(x))` draws in any terminal, `plot3d(x*y, x:
80
+ -2..2, y: -2..2)` draws a surface in one, and `save("f.svg")` writes a
81
+ picture. `plot(...).to_png` and `show` use the same Chrome as below.
82
+ - The window front end `bin/rcas-app` borrows a browser engine instead of
83
+ shipping one: it needs a Google Chrome, Chromium, Brave or Microsoft Edge
84
+ on the machine (`RCAS_BROWSER` names another), and `npm install` for the
85
+ KaTeX it typesets with. Nothing is bundled and nothing goes over the
86
+ network; see MANUAL.md, Appendix C.
87
+ - Typeset pictures (`show`, `to_png`, and `bin/rcas-chat`): either `node`
88
+ plus `npm install` in the project directory (fetches KaTeX, see
89
+ `package.json`) and a local Google Chrome / Chromium, or a TeX
90
+ installation with `latex` and `dvipng`. Pictures display inline in iTerm2.
91
+ - Optional and off unless you set it up: with the `anthropic` gem and
92
+ credentials in `ANTHROPIC_API_KEY` (or a profile from `ant auth login`),
93
+ `bin/rcas-chat` also answers questions in plain language. Without them
94
+ the chat is a plain CAS front end and shows nothing about it.
95
+
96
+ ## Installing and running it
97
+
98
+ rcas is a gem with no dependencies beyond the Ruby it runs on (`irb` and
99
+ `bigdecimal` are named because Ruby 3.4 and later bundle them rather than
100
+ build them in):
101
+
102
+ ```
103
+ $ gem build rcas.gemspec && gem install ./rcas-0.2.0.gem
104
+ $ rcas # the same three programs as below, on your PATH
105
+ ```
106
+
107
+ or run it from a checkout, which is what the rest of this file assumes:
108
+
109
+ ```
110
+ $ git clone https://github.com/no-dashes/rcas && cd rcas
111
+ $ bin/rcas # irb with rcas loaded: bare names are variables
112
+ $ bin/rcas-chat # terminal front end with typeset output
113
+ $ bin/rcas-app # a window: a worksheet of In/Out cells (--install for the Dock)
114
+ ```
115
+
116
+ Inside `bin/rcas`, an undefined bare name such as `x` (or `α`, `β₁`: any
117
+ Ruby identifier) becomes the indeterminate `:x`, the functions (`sin`,
118
+ `integrate`, `solve`, ...) and the constants (`PI`/`π`, `E`, `I`, `oo`/`∞`,
119
+ `NN ZZ QQ RR CC`) are in scope, and `hold { ... }` keeps input unevaluated. See MANUAL.md, "Sessions and
120
+ setup", for the details.
121
+
122
+ **Caveat.** This is otherwise a plain irb, with one deliberate departure:
123
+ Kernel's printers `p`, `pp`, `j` and `jj` are undefined in the session so
124
+ that `p` can be an indeterminate (a prime, say). Print with `puts`, `print`
125
+ or `Kernel.p(expr)` instead. The same holds in `bin/rcas-chat`.
126
+
127
+ ## Using the library from Ruby
128
+
129
+ ```ruby
130
+ require "rcas"
131
+
132
+ e = (:x + 1) * (1 - :x) # symbols are indeterminates
133
+ e.expand # => 1 - x**2
134
+ RCAS.integrate(RCAS.sin(:x), :x) # => -cos(x)
135
+
136
+ include RCAS::Functions # bare sin, integrate, solve, ...
137
+ include RCAS::Sets # NN ZZ QQ RR CC
138
+ include RCAS::Constants # PI E I OO
139
+ ```
140
+
141
+ `lib/rcas.rb` is the only entry point; it requires the rest of `lib/rcas/`.
142
+
143
+ ## Files and settings
144
+
145
+ rcas itself keeps no state. `bin/rcas-chat` and `bin/rcas-app` write to
146
+ `~/.rcas` (another directory with `RCAS_HOME`):
147
+
148
+ | path | contents |
149
+ |---|---|
150
+ | `~/.rcas/settings.json` | your defaults: output mode, backend, scale, theme, wrap width, model, fallbacks |
151
+ | `~/.rcas/sessions/*.json` | one file per chat session: transcript, conversation with Claude and the session's settings, saved after every input (`RCAS_SESSION_DIR` moves the directory) |
152
+ | `~/.rcas/history` | the input history of the chat prompt |
153
+ | `~/.rcas/app/` | the browser profile of the `bin/rcas-app` window, so that it is a separate process from your browsing |
154
+ | `/tmp/rcas/` | pictures of typeset output while a session runs; a session deletes the pictures it created when it ends (`RCAS_CACHE_DIR` moves the directory) |
155
+
156
+ Defaults are changed in four ways, in increasing precedence:
157
+ `~/.rcas/settings.json`, environment variables, command-line flags, and
158
+ `/` commands inside a session, which are also remembered in that
159
+ session's file and restored by `--resume`. The easiest way to fill
160
+ `settings.json` is to set things up in a session and run `/settings save`;
161
+ `/settings` shows the values in force and what the file says, `/settings
162
+ reset` deletes the file. The file is plain JSON:
163
+
164
+ ```json
165
+ {
166
+ "output": "latex",
167
+ "backend": "katex",
168
+ "scale": 1.5,
169
+ "theme": "dark",
170
+ "plotstyle": "image"
171
+ }
172
+ ```
173
+
174
+ | setting | environment | flag | in the session |
175
+ |---|---|---|---|
176
+ | output mode: `text`, `tex` (picture only), `both`, `latex` (text + source). Default: `both` in iTerm2 when a renderer is installed, `text` otherwise | `RCAS_TEX_INLINE=0` forces text | `--output=MODE`, `--tex`, `--no-tex` | `/output MODE` |
177
+ | typesetting backend `katex` or `latex` (default: whichever is installed, KaTeX first) | `RCAS_TEX_BACKEND` | `--backend=katex\|latex` | `/backend katex\|latex` |
178
+ | picture zoom, colour theme | `RCAS_TEX_SCALE`, `RCAS_TEX_THEME=light\|dark` | | `/scale N`, `/theme dark\|light` |
179
+ | how plots are shown: `text` (braille art, the default) or `image` (a picture, where the terminal and Chrome allow it) | `RCAS_PLOT_STYLE` | | `/plotstyle text\|image` |
180
+ | print `ℤ`, `π`, `∞` instead of `ZZ`, `pi`, `oo` (off by default) | `RCAS_UNICODE=1` | | `/unicode on\|off` |
181
+ | number the session's lines in the prompt, `rcas[3]> ` (on by default; `In[3]` and `Out[3]` work either way) | `RCAS_NUMBERED=0` turns it off | | `/numbered on\|off` |
182
+ | line width for wrapping long results (default: terminal width) | `RCAS_TEX_WRAP`, `COLUMNS` | | |
183
+ | plain-language questions (optional, see above): credentials | `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN` | | |
184
+ | their model (default `claude-opus-5`) and server-side fallback on refusal; settings keys `model`, `fallbacks` | `RCAS_MODEL`, `RCAS_FALLBACKS=0` | `--model ID` | `/model ID`, `/fallbacks on\|off` |
185
+ | helper binaries for KaTeX rendering | `RCAS_NODE`, `RCAS_CHROME`, `RCAS_KATEX_DIR` | | |
186
+ | colours off | `NO_COLOR` | `--no-color` | |
187
+ | location of settings, history and sessions | `RCAS_HOME` (default `~/.rcas`) | | |
188
+
189
+ Everything in the first column except colours and the KaTeX helpers can be
190
+ stored in `settings.json` under the keys `output`, `backend`, `scale`,
191
+ `theme`, `wrap`, `plotstyle`, `unicode`, `numbered`, `model`, `fallbacks`.
192
+
193
+ Sessions: `-c` / `--continue` reopens the most recent one, `-r` / `--resume`
194
+ opens a picker, `--resume NAME` (or an id prefix, or a list number) goes
195
+ straight to one; inside a session `/sessions`, `/rename NAME`, `/save FILE`
196
+ and `/reset`. The full command list is in MANUAL.md, Appendix B.
197
+
198
+ ## Tests
199
+
200
+ ```
201
+ $ ruby -S rake
202
+ ```
203
+
204
+ runs the whole suite, including `test/manual_test.rb`, which executes every
205
+ `rcas>` transcript in MANUAL.md and compares the printed results. The task
206
+ sets `RCAS_STRICT=1`: where the library catches an error to answer "not
207
+ decided here", a `NoMethodError` or `NameError` is re-raised instead,
208
+ because that is a bug and not mathematics. Set it yourself when running a
209
+ single file (`RCAS_STRICT=1 ruby -Ilib -Itest test/solve_test.rb`).
210
+
211
+ The core suite needs nothing beyond the standard library. A few tests
212
+ drive optional parts and skip, with the reason, when those are missing:
213
+ the chat tests that script a Claude conversation need the `anthropic`
214
+ gem, `test/js/app_race.js` (the worksheet's Enter key, run against the
215
+ real `app.js`) needs `node`, and the parser test needs Ruby 3.4 or later.
216
+
217
+ ## Documentation
218
+
219
+ - [MANUAL.md](MANUAL.md): the user manual, with a table of contents,
220
+ worked examples for every feature, a reference of functions, the
221
+ [list of what is not implemented](MANUAL.md#what-is-not-implemented),
222
+ and appendices on typeset output, `rcas-chat` and `rcas-app`.
223
+ - [DESIGN.md](DESIGN.md): the design - what `==` means, when rcas
224
+ rewrites, the canonical form, domains, how undecidable questions are
225
+ handled, a comparison with Sage, SymPy, MuPAD and Maxima, and the
226
+ invariants and algorithms behind it.
227
+ - [CITATION.cff](CITATION.cff): how to cite rcas; `LICENSE`: MIT.
228
+
229
+ ## How and why?
230
+
231
+ I did some research in computer algebra, using MuPAD mostly. Since I left
232
+ university I always missed the topic, but never had the time to dig into
233
+ it again. And since I use ruby all the time, I considered implementing a
234
+ CAS core in ruby, but never got past the playing around stage.
235
+
236
+ With Claude, I now was able to outsource the nitty gritty details and only
237
+ focus on my ideas on *how* such a thing could be built. To be precise
238
+ about who did what:
239
+
240
+ - **Designed by me:** the shape of the system - a CAS that extends Ruby
241
+ instead of inventing a language, with Ruby symbols as the indeterminates,
242
+ Ruby operators building the trees and irb as the REPL; MuPAD's
243
+ `hold`/`eval` and domains as values; honest unevaluated answers instead
244
+ of guesses; the vocabulary; which features exist and in what order; and
245
+ the decisions where computer algebra systems disagree (principal roots
246
+ and `surd`, complete solutions over the complex numbers, Karr's
247
+ convention for reversed sums, and the others in
248
+ [DESIGN.md](DESIGN.md#settled-design-decisions)).
249
+ - **Generated by Claude:** almost all of the code, the tests and the
250
+ manual, under that direction. 107 of the first 129 commits carry a
251
+ Claude co-author line.
252
+ - **Checked by:** 1284 tests (`ruby -S rake`), with property checks
253
+ where the mathematics offers one - an antiderivative is differentiated
254
+ back, an ODE solution substituted, a closed-form sum evaluated at small
255
+ n; the manual itself, whose 961 `rcas>` lines the suite runs and compares
256
+ with the printed results line for line; rounds of outside review that
257
+ went looking for wrong answers, where every counterexample was
258
+ reproduced and now has a regression test of its own
259
+ (`test/review*_test.rb`); and sources: every non-trivial algorithm names
260
+ where it comes from in its code, and 87 of the 89 references in
261
+ [MANUAL.md, section 4](MANUAL.md#4-sources) carry a link (a DOI for 25
262
+ of them).
263
+
264
+ **Beware:** this is a personal project, not a verified system. It is
265
+ tested hard and it refuses rather than guesses where it can tell, but it
266
+ can still give wrong answers. Check anything that matters by a second
267
+ route.
data/bin/rcas ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
5
+ require "rcas"
6
+ require "rcas/irb"
7
+
8
+ puts "rcas #{RCAS::VERSION} - symbols are indeterminates: try (x + 1) * (1 - x)"
9
+ RCAS::IRB.start(self)
data/bin/rcas-app ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # A desktop window for rcas: a worksheet of numbered In/Out cells, typeset
5
+ # results and inline plots, in a borrowed browser engine. `rcas-app --help`.
6
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
7
+ require "rcas/app"
8
+
9
+ exit RCAS::App.start(ARGV).to_i
data/bin/rcas-chat ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # A Claude-Code-style front end for rcas: type Ruby, get typeset results in
5
+ # iTerm2, ask Claude questions in plain language. `rcas-chat --help`.
6
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
7
+ require "rcas/chat"
8
+
9
+ exit RCAS::Chat.start(ARGV).to_i