еще немного повозимся с тождествами — следующая серия начинается с того, что
(a+b)²/(a-c)(b-c)+(b+c)²/(b-a)(c-a)+(c+a)²/(c-b)(a-b) = 1
дальше
(a+b)⁴/(a-c)(b-c)(a-d)(b-d) + … = 2
а дальше количество слагаемых быстро (квадратично) растет, но по крайней мере первые суммы легко посчитать на компьютере:
понятно ли, что за последовательность возникает? можете ли это доказать?
(бонус для любителей геометрии: на самом деле, sum2(2) считает количество прямых через 2 точки на плоскости, sum2(3) — через 4 прямые общего в положения в пространстве… и так далее)
а как эти тождества обобщить (скажем, в прошлой серии тождеств вместо монома в числителе можно было написать любой многочлен подходящей степени)?
(a+b)²/(a-c)(b-c)+(b+c)²/(b-a)(c-a)+(c+a)²/(c-b)(a-b) = 1
дальше
(a+b)⁴/(a-c)(b-c)(a-d)(b-d) + … = 2
а дальше количество слагаемых быстро (квадратично) растет, но по крайней мере первые суммы легко посчитать на компьютере:
def sum2(n):
m = 2*n-2
R = PolynomialRing(QQ, 'x', n+1)
x = R.gens()
return sum(
(x[i]+x[j])^m / prod((x[i]-x[k])*(x[j]-x[k])
for k in range(n+1) if k != i and k != j)
for j in range(n+1) for i in range(j)
)
for n in range(2,6+1): print(n,sum2(n))
понятно ли, что за последовательность возникает? можете ли это доказать?
(бонус для любителей геометрии: на самом деле, sum2(2) считает количество прямых через 2 точки на плоскости, sum2(3) — через 4 прямые общего в положения в пространстве… и так далее)
а как эти тождества обобщить (скажем, в прошлой серии тождеств вместо монома в числителе можно было написать любой многочлен подходящей степени)?
👍2🔥1
как проверить формулу на картинке?
самая понятная формула, выражающая объем тетраэдра через его ребра, дается определителем Кэли–Менгера:
для полиномиальности здесь сразу вычисляется не объем, а его квадрат… но формуле от Маркелова и этого недостаточно, так как в определение «переменных третьего поколения» (a, b, c, d) через «переменные второго поколения» входят квадратные корни
но если раскрыть скобки в числителе, то останутся только квадраты этих товарищей, а также произведение abcd (которое тоже полином от «переменных второго поколения»)
после этих ухищрений
но вопрос, что всё это значит — можно ли выражениям типа b+c+d-a придать какой-то геометрический смысл, скажем, как это происходит в формуле Герона — остается
мб кто-то в комментариях научит
самая понятная формула, выражающая объем тетраэдра через его ребра, дается определителем Кэли–Менгера:
CM = matrix([
[0, 1, 1, 1, 1],
[1, 0, U**2, V**2, w**2],
[1, U**2, 0, W**2, v**2],
[1, V**2, W**2, 0, u**2],
[1, w**2, v**2, u**2, 0 ]
])
V2_CM = det(CM)/288
для полиномиальности здесь сразу вычисляется не объем, а его квадрат… но формуле от Маркелова и этого недостаточно, так как в определение «переменных третьего поколения» (a, b, c, d) через «переменные второго поколения» входят квадратные корни
но если раскрыть скобки в числителе, то останутся только квадраты этих товарищей, а также произведение abcd (которое тоже полином от «переменных второго поколения»)
X, x = (w-U+v)*(U+v+w), (U-v+w)*(v-w+U)
Y, y = (u-V+w)*(V+w+u), (V-w+u)*(w-u+V)
Z, z = (v-W+u)*(W+u+v), (W-u+v)*(u-v+W)
a2 = x*Y*Z
b2 = y*Z*X
c2 = z*X*Y
d2 = x*y*z
abcd = X*Y*Z*x*y*z
num2 = (
2*(a2*b2+a2*c2+a2*d2+b2*c2+b2*d2+c2*d2)
- (a2**2+b2**2+c2**2+d2**2)
+ 8*abcd
)
V2_markelov = num2/(192*u*v*w)**2
после этих ухищрений
V2_CM - V2_markelov.expand() действительно дает нольно вопрос, что всё это значит — можно ли выражениям типа b+c+d-a придать какой-то геометрический смысл, скажем, как это происходит в формуле Герона — остается
мб кто-то в комментариях научит
👍7🔥3
контекст для предыдущего — такого рода как выше объяснение (неполное, текст на картинке взят из книги Блинкова «Учимся на чужих ошибках») формулы Герона
вообще теорема Гильберта о нулях говорит, что многочлен с точностью до умножения на константу определяется своими нулями… правда (не обсуждая даже, почему для какой-то степени S есть полиномиальная формула) тут желательно рассматривать многочлен для всевозможных значений переменных, причем комплексных
например, в формуле для площади нет сомножителя abc — разве площадь не обращается в ноль, когда одна из сторон становится нулевой? а вот,у прямоугольного треугольника с катетами 1 и i площадь ненулевая, но гипотенуза имеет нулевую длину
что хуже, длина отрезка в этом комплексном мире вообще не определена (чему равна длина отрезка от -i/2 до +i/2: +i или -i?), определен только ее квадрат (то же можно сказать и про саму площадь, кстати)
похожая вещь происходит с формулой для объема тетраэдра — казалось бы, если для площадей граней тетраэдра выполняется равенство S1=S2+S3+S4, то он вырождается, так что формула для объема должна раскладываться на кучу множителей… а в реальности определитель Кэли-Менгера представляет собой неприводимый многочлен!
но всё-таки чего-то в духе рассуждения на картинке для объема тетраэдра хотелось бы… и в этом смысле формула им. Маркелова привлекает наличием факторизации
вообще теорема Гильберта о нулях говорит, что многочлен с точностью до умножения на константу определяется своими нулями… правда (не обсуждая даже, почему для какой-то степени S есть полиномиальная формула) тут желательно рассматривать многочлен для всевозможных значений переменных, причем комплексных
например, в формуле для площади нет сомножителя abc — разве площадь не обращается в ноль, когда одна из сторон становится нулевой? а вот,
что хуже, длина отрезка в этом комплексном мире вообще не определена (чему равна длина отрезка от -i/2 до +i/2: +i или -i?), определен только ее квадрат (то же можно сказать и про саму площадь, кстати)
похожая вещь происходит с формулой для объема тетраэдра — казалось бы, если для площадей граней тетраэдра выполняется равенство S1=S2+S3+S4, то он вырождается, так что формула для объема должна раскладываться на кучу множителей… а в реальности определитель Кэли-Менгера представляет собой неприводимый многочлен!
но всё-таки чего-то в духе рассуждения на картинке для объема тетраэдра хотелось бы… и в этом смысле формула им. Маркелова привлекает наличием факторизации
👍11
вот таблица ответов (количества склеек многоугольника в поверхности разного рода) от программы выше — что можно в ней увидеть?
в такой “нумерологии” нередко помогает обращать внимание на делимости
вот например если посмотреть на первую колонку, то бросается в глаза, что 14 и 42 делятся на 7, 132 и 429 на 11… раз у соседних чисел есть большой общий делитель, можно попробоват посмотреть на их частные
получаем 1, 2, 2 1/2, 2 4/5, 3, 3 1/7, 3 1/4, 3 1/3, 3 2/5, 3 5/11, 3 1/2… — видно, что числа не очень далеки от целых, а именно становятся целыми при умножении на n+1 (тут тоже особенно помогает обратить внимания на числа типа 7, 11)
если на n+1 домножить, то получится… ну сами попробуйте — мб со школьниками — после этого легко придумать гипотезу про формулу
конечно, про числа Каталана и так многие знают, но абсолютно тот же трюк можно проделать со второй колонкой…
а можно посмотреть по-другому: когда в колонках рядом стоят числа 5 и 10, 14 и 70, 42 и 420, 132 и 2310, то естественно попробовать одно на другое поделить — и если это сделать (и еще умножить на 2 для целочисленности), получается 1, 4, 10, 20, 35, 56… (думаю, и без спойлера понятно, что это ; )
но можно посмотреть и куда-то еще… вот, скажем, на верхние числа в колонках… тут даже без компьютера бросается в глаза число 225225
1001 = 7.11.13, а значит, 225225 = 15².1001 = 3.5.7.11.13.15 недалеко ушло от двойного факториала… как и, например, 21… в общем, тоже закономерность нетрудно распознать
если замечаете в такой таблице что-то еще — пишите
в такой “нумерологии” нередко помогает обращать внимание на делимости
вот например если посмотреть на первую колонку, то бросается в глаза, что 14 и 42 делятся на 7, 132 и 429 на 11… раз у соседних чисел есть большой общий делитель, можно попробоват посмотреть на их частные
получаем 1, 2, 2 1/2, 2 4/5, 3, 3 1/7, 3 1/4, 3 1/3, 3 2/5, 3 5/11, 3 1/2… — видно, что числа не очень далеки от целых, а именно становятся целыми при умножении на n+1 (тут тоже особенно помогает обратить внимания на числа типа 7, 11)
если на n+1 домножить, то получится… ну сами попробуйте — мб со школьниками — после этого легко придумать гипотезу про формулу
конечно, про числа Каталана и так многие знают, но абсолютно тот же трюк можно проделать со второй колонкой…
а можно посмотреть по-другому: когда в колонках рядом стоят числа 5 и 10, 14 и 70, 42 и 420, 132 и 2310, то естественно попробовать одно на другое поделить — и если это сделать (и еще умножить на 2 для целочисленности), получается 1, 4, 10, 20, 35, 56… (
но можно посмотреть и куда-то еще… вот, скажем, на верхние числа в колонках… тут даже без компьютера бросается в глаза число 225225
1001 = 7.11.13, а значит, 225225 = 15².1001 = 3.5.7.11.13.15 недалеко ушло от двойного факториала… как и, например, 21… в общем, тоже закономерность нетрудно распознать
если замечаете в такой таблице что-то еще — пишите
❤1👍1🤔1
вчера на уроке хотел быстренько показать как выглядят слагаемые в det(AB) по сравнению с det(A)det(B)
но не смог заставить sage раскрыть скобки не сокращая одинаковые члены
в качестве работы над ошибками написал сегодня это на коленке просто в питоне — получилось так:
можно запустить — и посмотреть, что как с чем сокращается
***
понравилось, что вот все эти определения «многочлен — это формальная сумма мономов…» и т.п. здесь реально работают
но не смог заставить sage раскрыть скобки не сокращая одинаковые члены
в качестве работы над ошибками написал сегодня это на коленке просто в питоне — получилось так:
from itertools import permutations
from functools import reduce
def sgn(perm):
inv = sum(perm[i] > perm[j] for i in range(len(perm)) for j in range(i+1, len(perm)))
return -1 if inv % 2 else 1
def mult_terms(A, B):
for As, Ams in A:
for Bs, Bms in B:
yield (As*Bs,Ams+Bms)
def mtrx(label, n):
return [ [ [ (1, [f"{label}{i+1}{j+1}"]) ] for j in range(n) ] for i in range(n) ]
def mtrxAB(l1,l2, n):
return [ [ [ (1, [f"{l1}{i+1}{s+1}", f"{l2}{s+1}{j+1}"]) for s in range(n) ] for j in range(n) ] for i in range(n) ]
def det_terms(mtrx):
n = len(mtrx)
for sigma in permutations(range(n)):
for inner_sign, factors in reduce(mult_terms, [ mtrx[i][sigma[i]] for i in range(n) ]):
yield (sgn(sigma)*inner_sign, factors)
def print_terms(terms):
for s, ms in terms:
print(f"{'+' if s>0 else '-'} {'.'.join(sorted(ms))}")
N = 3
detA = list(det_terms(mtrx("a", N)))
detB = list(det_terms(mtrx("b", N)))
print_terms(mult_terms(detA, detB))
print("---")
print_terms(det_terms(mtrxAB("a","b", N)))
можно запустить — и посмотреть, что как с чем сокращается
***
понравилось, что вот все эти определения «многочлен — это формальная сумма мономов…» и т.п. здесь реально работают
❤4
предыдущий код можно обернуть в классы для мономов и полиномов, начиная с чего-нибудь в духе
у такого умножения мономов есть нейтральный элемент и оно (операционально) коммутативно
тут занятно, что хотя изначальная идея была класть в vars набор строк (имен переменных) — в коде от этого осталось мало следов, можно пользоваться и любыми другими типами, print(Monomial((2,1))) работает без проблем
в качестве математической интермедии можно посмотреть, что за множество мы получим, если разрешим в качестве меток (‘имен переменных’) не строки, а произвольные числа
теорема Виета говорит, что Monomials<ComplexNumbers> (буду дальше писать тип vars в угловых скобках; и давайте считать, что разрешен только sgn=1) — это по сути то же, что упорядоченные наборы чисел (т.е. чтобы это увидеть, можно попросить repr печатать значения элементарных симметических многочленов от vars)
любителям геометрии приятнее смотреть не на ℂ, а на ℂ с добавленной точкой '∞' — и примерно то же рассуждение говорит, что Monomials от такого образования суть точки комплексных проективных пространств
если еще отождествить Monomial(0) с нейтральным элементом Monomial(), то все эти проективные пространства склеятся в одно большое красивое ℂP∞
в ту же игру можно играть не только с ℂP¹ aka S², но и с другими топологическими пространствами — если в качестве меток разрешить точки топологического пространства X (и одну из точек объявить нейтральным элементом), то получается определение групп гомологий без всяких комплексов и т.п.: просто H_n(X) = π_n ( Monomials<X> )
называется теорема Дольда–Тома
упражнение для любителей геометрии: разобраться, как выглядит пространство Monomials<RP²>
class Monomial:
def __init__(self, vars, sgn=1):
self.vars = tuple(vars)
self.sgn = sgn
def __mul__(self, other):
return Monomial(self.vars + other.vars,self.sgn * other.sgn)
def __repr__(self):
return f"{'-+'[self.sgn > 0]} {'.'.join(sorted(map(repr,self.vars))) or '1'}"
def __eq__(self, other):
return repr(self) == repr(other)
у такого умножения мономов есть нейтральный элемент и оно (операционально) коммутативно
> print(Monomial(("y",))*Monomial(("x",))*Monomial() == Monomial(("x","y")))
True
тут занятно, что хотя изначальная идея была класть в vars набор строк (имен переменных) — в коде от этого осталось мало следов, можно пользоваться и любыми другими типами, print(Monomial((2,1))) работает без проблем
в качестве математической интермедии можно посмотреть, что за множество мы получим, если разрешим в качестве меток (‘имен переменных’) не строки, а произвольные числа
теорема Виета говорит, что Monomials<ComplexNumbers> (буду дальше писать тип vars в угловых скобках; и давайте считать, что разрешен только sgn=1) — это по сути то же, что упорядоченные наборы чисел (т.е. чтобы это увидеть, можно попросить repr печатать значения элементарных симметических многочленов от vars)
любителям геометрии приятнее смотреть не на ℂ, а на ℂ с добавленной точкой '∞' — и примерно то же рассуждение говорит, что Monomials от такого образования суть точки комплексных проективных пространств
если еще отождествить Monomial(0) с нейтральным элементом Monomial(), то все эти проективные пространства склеятся в одно большое красивое ℂP∞
в ту же игру можно играть не только с ℂP¹ aka S², но и с другими топологическими пространствами — если в качестве меток разрешить точки топологического пространства X (и одну из точек объявить нейтральным элементом), то получается определение групп гомологий без всяких комплексов и т.п.: просто H_n(X) = π_n ( Monomials<X> )
называется теорема Дольда–Тома
упражнение для любителей геометрии: разобраться, как выглядит пространство Monomials<RP²>
🔥2🤯2❤1
смотрел видео ниже
кто учит школьников алгебре — могут оценить, что всплывают родные всем темы преобразований графиков функций (в т.ч. с модулями), поворотов в координатах и т.п. — а при этом в результате получается что-то прикольное
попробовать сделать что-то своё можно на twigl.app (например)
кто учит школьников алгебре — могут оценить, что всплывают родные всем темы преобразований графиков функций (в т.ч. с модулями), поворотов в координатах и т.п. — а при этом в результате получается что-то прикольное
попробовать сделать что-то своё можно на twigl.app (например)
Forwarded from Канал Ивана Дианова
Записал настоящий обучающий видос, с музыкой, скринкастом и объясняющими демками.
Ютуб youtu.be/zblepnHHCSA
ВК vkvideo.ru/video-230304511_456239017
Ютуб youtu.be/zblepnHHCSA
ВК vkvideo.ru/video-230304511_456239017
🔥3👍1
This media is not supported in your browser
VIEW IN TELEGRAM
на недавнем семинаре учителей коллега Шноль показывал между делом решето Эратосфена, где на разных шагах числа не просто вычеркивают, а красят разными цветами
подумал, что это повод попробовать что-то сделать в manim — вот так примерно получилось
процессне очень понравился, честно говоря — в т.ч. тем, что компилируются простейшие картинки безумно долго (на моем простейшем материале приходится ждать ~минуту, чтобы посмотреть результат мельчайшего изменения… как это работает на сложной анимации и не таком хорошем железе, страшно подумать)
код наверное положу в комментарии
но лучше посмотреть не на код, а на то, как (визуально) расположены кружки одного цвета — получается похоже на прогулки на торе из статьи Гаянэ Паниной в новом Квантике, вот можно в kvantik.com/issue/pdf/2025-11_sample.pdf посмотреть
подумал, что это повод попробовать что-то сделать в manim — вот так примерно получилось
процесс
код наверное положу в комментарии
но лучше посмотреть не на код, а на то, как (визуально) расположены кружки одного цвета — получается похоже на прогулки на торе из статьи Гаянэ Паниной в новом Квантике, вот можно в kvantik.com/issue/pdf/2025-11_sample.pdf посмотреть
🔥10❤2
(в порядке лытдыбра)
пытался разобраться с применениями тождества тройного произведения Якоби — вот можно посмотреть, как оно выглядит:
его можно применять к товарищам типа θ(q):=Σq^{n^2} — а степени такой суммы считают представления чисел в виде суммы квадратов и т.д.
но это пока с трудом идет
что давно знаю — что из тройного произведения следует пентагональная теорема Эйлера, позволяющая быстро вычислять количества разбиений (способов представить число N в виде суммы слагаемых, порядок которых не важен)
// ранее про разбиения: https://news.1rj.ru/str/compmathweekly/40
про этот сюжет можно прочитать в брошюре «Диаграммы Юнга, плоские разбиения и знакочередующиеся матрицы» Е.Смирнова, https://mccme.ru/free-books/dubna/smirnov-asm.pdf
для разминки написал соответствующее вычисление:
(и действительно,
пытался разобраться с применениями тождества тройного произведения Якоби — вот можно посмотреть, как оно выглядит:
from sage.all import *
N = 10
q, Z = var('q'), var('Z')
J = prod((1-q**(2*m))*(1+q**(2*m-1)*Z**2)*(1+q**(2*m-1)*Z**(-2))
for m in range(1, N+1))
print(J.series(q,2*N+1))
его можно применять к товарищам типа θ(q):=Σq^{n^2} — а степени такой суммы считают представления чисел в виде суммы квадратов и т.д.
но это пока с трудом идет
что давно знаю — что из тройного произведения следует пентагональная теорема Эйлера, позволяющая быстро вычислять количества разбиений (способов представить число N в виде суммы слагаемых, порядок которых не важен)
// ранее про разбиения: https://news.1rj.ru/str/compmathweekly/40
про этот сюжет можно прочитать в брошюре «Диаграммы Юнга, плоские разбиения и знакочередующиеся матрицы» Е.Смирнова, https://mccme.ru/free-books/dubna/smirnov-asm.pdf
для разминки написал соответствующее вычисление:
penta = concat [[(p,s), (p+m,s)] | m <- [1..],
let (p,s) = (m*(3*m-1) `div` 2, (-1)^(m+1))]
partn = 1 : [sum [s*(partn !! (n-p)) | (p,s) <- pents] | n <- [1..],
let pents = takeWhile ((<= n) . fst) penta]
(и действительно,
partn !! 500, скажем, мгновенно отвечает 2300165032574323995027)Telegram
Компьютерная математика Weekly
Матпраздник прошел, попробуем вернуться к компьютерным развлечениям
сколькими способами число N можно представить в виде суммы?
(разбиения 1+2 и 2+1 и т.п. считаются одинаковыми)
начать эксперименты можно и с примитивного перебора — например, такого:
…
сколькими способами число N можно представить в виде суммы?
(разбиения 1+2 и 2+1 и т.п. считаются одинаковыми)
начать эксперименты можно и с примитивного перебора — например, такого:
…
(продолжая предыдущее)
положим φ(q)=(1-q)(1-q²)(1-q³)…
если раскрыть все скобки, то чудесным образом почти всё сокращается (про это и говорит упоминаемая выше пентагональная теорема Эйлера) — это можно видеть в первой строчке таблицы
и что получается при раскрытии скобок для φ³, тоже хорошо видно (и это, как и пентагональную теорему Эйлера, несложно вывести из тождества тройного произведения Якоби)
дальше жизнь усложняется, но кое-что еще заметить можно
скажем, для 8-й степени
коэффициенты при q^{4k+3} сразу обращаются в ноль, а коэффициенты при q^{4k+1} делятся на 8, причем если разделить, то получится последовательность -1, 8, -20, 0, 70, -64, -56, 0, 125, которую мы уже видели… (понятно где, да?)
серьезные люди уже давно бы изучилимодулярные формы (и если хотите написать комментарий с этой т.з., то не стесняйтесь, пожалуйста), но я пока продолжу играть в ненаучную нумерологию…
положим φ(q)=(1-q)(1-q²)(1-q³)…
если раскрыть все скобки, то чудесным образом почти всё сокращается (про это и говорит упоминаемая выше пентагональная теорема Эйлера) — это можно видеть в первой строчке таблицы
и что получается при раскрытии скобок для φ³, тоже хорошо видно (и это, как и пентагональную теорему Эйлера, несложно вывести из тождества тройного произведения Якоби)
дальше жизнь усложняется, но кое-что еще заметить можно
скажем, для 8-й степени
коэффициенты при q^{4k+3} сразу обращаются в ноль, а коэффициенты при q^{4k+1} делятся на 8, причем если разделить, то получится последовательность -1, 8, -20, 0, 70, -64, -56, 0, 125, которую мы уже видели… (понятно где, да?)
серьезные люди уже давно бы изучили
Как численно найти корни многочлена?
Если корни сильно разной величины, x₁≫x₂≫x₃≫…, то k-й элементарный симметрический многчлен неотличим от произведения k самых больших иксов, так что любой корень — это примерно отношение соседних коэффициентов многочлена.
Если числа изначально разные по модулю, то чтобы их «раздвинуть» достаточно возвести все их в большую степень. Если P(x) многочлен, то P(√x) конечно не многочлен… зато P(√x)P(-√x) — вполне себе многочлен, а его корни суть квадраты корней исходного. После нескольких таких итераций корни становятся достаточно различными, чтобы работала идея из предыдущего абзаца.
Такой способ предлагал Лобачевский (впрочем до него видимо Данделен), а мне про это рассказал коллега Бахарев.
На коленке реализовал это так:
— и действительно работает… но близко к корням (модулям корней) так не подойдешь (точность растет медлено, а потом вообще происходит катастрофа). Вроде есть какие-то модификации, которые улучшают ситуацию.
Впрочем, уже грубая оценка для всех корней видимо полезна — метод Ньютона, наоборот, сходится очень быстро, но если начинать итерации рядом с корнем (и действительно, пара итераций Лобачевского + пара итераций Ньютона для каких-то многочленов у меня работает прекрасно).
// Ранее здесь про метод Ньютона: https://news.1rj.ru/str/compmathweekly/27 (и далее по ссылкам)
Если корни сильно разной величины, x₁≫x₂≫x₃≫…, то k-й элементарный симметрический многчлен неотличим от произведения k самых больших иксов, так что любой корень — это примерно отношение соседних коэффициентов многочлена.
Если числа изначально разные по модулю, то чтобы их «раздвинуть» достаточно возвести все их в большую степень. Если P(x) многочлен, то P(√x) конечно не многочлен… зато P(√x)P(-√x) — вполне себе многочлен, а его корни суть квадраты корней исходного. После нескольких таких итераций корни становятся достаточно различными, чтобы работала идея из предыдущего абзаца.
Такой способ предлагал Лобачевский (впрочем до него видимо Данделен), а мне про это рассказал коллега Бахарев.
На коленке реализовал это так:
def absroots(poly,N=5):
poly, d = np.array(poly,dtype=np.float64), len(poly)-1
signs = np.ones(d+1)
signs[1::2] *= -1
for _ in range(N):
poly *= 1/poly[-1]
poly = np.convolve(poly,poly*signs)[::2]
return np.array([(-poly[k]/poly[k+1])**(1/(2**N))
for k in range(d)])
— и действительно работает… но близко к корням (модулям корней) так не подойдешь (точность растет медлено, а потом вообще происходит катастрофа). Вроде есть какие-то модификации, которые улучшают ситуацию.
Впрочем, уже грубая оценка для всех корней видимо полезна — метод Ньютона, наоборот, сходится очень быстро, но если начинать итерации рядом с корнем (и действительно, пара итераций Лобачевского + пара итераций Ньютона для каких-то многочленов у меня работает прекрасно).
// Ранее здесь про метод Ньютона: https://news.1rj.ru/str/compmathweekly/27 (и далее по ссылкам)
Telegram
Компьютерная математика Weekly
0.
здесь уже обсуждалось, что если функция достаточно хорошая, то уравнение f(x)=0 можно быстро приближенно решать при помощи метода Ньютона
если x — приближенное значение корня, то рядом ним график функции недалеко ушел от касательной, поэтому в качестве…
здесь уже обсуждалось, что если функция достаточно хорошая, то уравнение f(x)=0 можно быстро приближенно решать при помощи метода Ньютона
если x — приближенное значение корня, то рядом ним график функции недалеко ушел от касательной, поэтому в качестве…
🔥9❤3🤯1
Компьютерная математика Weekly
для недавно присоединившихся — некоторые старые посты: * про быстрое вычисление числа пи * про подсчет разбиений на доминошки и логарифмический масштаб * про то как нарисовать снежинку и дерево
несколько достаточно доступных сюжетов для недавно присоединившихся:
* экспериментальное вычисление пи в экселе
https://news.1rj.ru/str/compmathweekly/76
* что будет, если возвести многочлен в большую степень?
https://news.1rj.ru/str/compmathweekly/81
* знаете ли вы, как выглядит график синуса?
https://news.1rj.ru/str/compmathweekly/89
( предыдущий выпуск: https://news.1rj.ru/str/compmathweekly/64 )
* экспериментальное вычисление пи в экселе
https://news.1rj.ru/str/compmathweekly/76
* что будет, если возвести многочлен в большую степень?
https://news.1rj.ru/str/compmathweekly/81
* знаете ли вы, как выглядит график синуса?
https://news.1rj.ru/str/compmathweekly/89
( предыдущий выпуск: https://news.1rj.ru/str/compmathweekly/64 )
1❤4🔥4
можно ли сравнить две функции за конечное время?
если вы написали две функции, которые определены на бесконечном множестве, то кажется очевидным, что нельзя написать программу, которая только применяя эти функции (не имея доступа к их коду) проверит за конечное время, равны ли они (в математическом смысле: совпадают ли они во всех точках) — и всё же иногда это возможно!
функции мы будем рассматривать на множестве Кантора, т.е. на бесконеных последовательностях 0 и 1
т.к. мы пишем программу — и функции на последовательностях, и сами последовательности у нас будут, конечно, только вычислимые; кроме того, они будут всюду определенные (можно написать
мы хотели бы сравнить две функции из Cantor, т.е., если угодно, написать функцию
если функции НЕ равны, то это уж точно можно понять за конечное время, т.к. любые вычислимые функции на Cantor зависят только от какого-то числа первых битов — это проявление компактности канторовского множества, из-за которой любая непрерывная функция на нем равномерно непрерывна (ср. с натуральными числами, где легко придумать вычислимую функцию которая никаким фиксированным количеством первых битов не определяется!)
но, на первый взгляд, если функции равны, то невозможно понять, до какого момента надо их сравнивать
и всё же можно за конечное время установить не только неравенство, но и равенство:
здесь функция forsome проверяет, существует ли точка множества Кантора, в которой верно p (что само по себе не менее удивительно, чем проверка равенства функций… и собственно через такой «бесконечный поиск за конечное время» равенство мгновенно переписывается), а find находит точку, в которой верно p, если таковая есть
при этом определение find через forsome крайне прямолинейное: «если существует пример с первым битом 0, то первый бит равен 0, иначе первый бит равен 1 (а дальше применяем find для определения оставшихся битов)»… и кажется, что пока ничего особо не сделано — но вот такое короткое (и вроде бы тоже довольно тавтологичное) определение forsome чудесным образом позволяет “вытянуть себя за волосы из болота”
мб позже будет комментарий, как это работает — но сразу оставлю ссылку на источник — Martin Escardo по диссертации Ulrich Berger'а; и спасибо коллеге Раскину за объяснения
хочу еще отметить, что это история не про хаскелл, можно напрячься и на питоне (например) переписать — но тут приятно, что синтаксис хорошо соответствует (некоторой) математике
если вы написали две функции, которые определены на бесконечном множестве, то кажется очевидным, что нельзя написать программу, которая только применяя эти функции (не имея доступа к их коду) проверит за конечное время, равны ли они (в математическом смысле: совпадают ли они во всех точках) — и всё же иногда это возможно!
функции мы будем рассматривать на множестве Кантора, т.е. на бесконеных последовательностях 0 и 1
т.к. мы пишем программу — и функции на последовательностях, и сами последовательности у нас будут, конечно, только вычислимые; кроме того, они будут всюду определенные (можно написать
type Cantor = Natural -> Bit, но надо иметь в виду, что если такая функция для числа 17 не определена, то она не задает элемент множества Кантора)мы хотели бы сравнить две функции из Cantor, т.е., если угодно, написать функцию
equal :: Eq y => (Cantor -> y) -> (Cantor -> y) -> Bool (здесь написано, что если для типа y определено сравнение, то equal сравнивает две функции Cantor→y)если функции НЕ равны, то это уж точно можно понять за конечное время, т.к. любые вычислимые функции на Cantor зависят только от какого-то числа первых битов — это проявление компактности канторовского множества, из-за которой любая непрерывная функция на нем равномерно непрерывна (ср. с натуральными числами, где легко придумать вычислимую функцию которая никаким фиксированным количеством первых битов не определяется!)
но, на первый взгляд, если функции равны, то невозможно понять, до какого момента надо их сравнивать
и всё же можно за конечное время установить не только неравенство, но и равенство:
data Bit = Zero | One
deriving (Eq)
type Natural = Integer
type Cantor = Natural -> Bit
(#) :: Bit -> Cantor -> Cantor
x # a = \i -> if i == 0 then x else a(i-1)
forsome :: (Cantor -> Bool) -> Bool
find :: (Cantor -> Bool) -> Cantor
forsome p = p(find p)
find p = first # find(p . (first #))
where first = if forsome(p . (Zero #)) then Zero else One
equal :: Eq y => (Cantor -> y) -> (Cantor -> y) -> Bool
equal f g = not(forsome(\a -> f a /= g a))
здесь функция forsome проверяет, существует ли точка множества Кантора, в которой верно p (что само по себе не менее удивительно, чем проверка равенства функций… и собственно через такой «бесконечный поиск за конечное время» равенство мгновенно переписывается), а find находит точку, в которой верно p, если таковая есть
при этом определение find через forsome крайне прямолинейное: «если существует пример с первым битом 0, то первый бит равен 0, иначе первый бит равен 1 (а дальше применяем find для определения оставшихся битов)»… и кажется, что пока ничего особо не сделано — но вот такое короткое (и вроде бы тоже довольно тавтологичное) определение forsome чудесным образом позволяет “вытянуть себя за волосы из болота”
мб позже будет комментарий, как это работает — но сразу оставлю ссылку на источник — Martin Escardo по диссертации Ulrich Berger'а; и спасибо коллеге Раскину за объяснения
хочу еще отметить, что это история не про хаскелл, можно напрячься и на питоне (например) переписать — но тут приятно, что синтаксис хорошо соответствует (некоторой) математике
❤10🔥4🤯3
Компьютерная математика Weekly pinned «несколько достаточно доступных сюжетов для недавно присоединившихся: * экспериментальное вычисление пи в экселе https://news.1rj.ru/str/compmathweekly/76 * что будет, если возвести многочлен в большую степень? https://news.1rj.ru/str/compmathweekly/81 * знаете ли вы, как выглядит…»
как работает код из предыдущего поста, реализующий «поиск за конечное время по множеству Кантора»?
посмотрим еще раз на определение
(напомню, что p это функция из бесконечных последовательностей нулей и единиц в True/False, а функция forsome должна проверять, выполняется ли p хоть в какой-то точке)
в одной ситуации всё понятно сразу: если p определена как константа (вообще не читает свой вход, а возвращает True или False), то ленивый компилятор даже вникать в определение find не будет, а вернет эту константу — и в этом случае forsome работает правильно
пусть теперь p для возвращения значения достаточно прочитать первые N битов последовательности — будем доказывать индукцией по N, что правильно работают и forsome, и
(напомню, что find должен возвращать пример точки, в которой p верно, если такая точка есть; # обозначает конкатенацию)
функция
наконец, для любой вычислимой всюду определенной функции p такое N, что p для ответа достаточно первых N битов последовательности, непременно существует — и это топологическое утверждение: проявление компактности множества Кантора (и вот для функций на натуральных числах aka конечных последовательностях 0 и 1 такое свойство очевидно неверно!)
***
после таких фокусов возникают в голове волшебные картины… вот например: если мы умеем проверять равенство функций в смысле совпадения во всех точках — то можно, казалось бы, для одной задачи написать медленный, но точно правильный алгоритм, а дальше любой другой алгоритм решения той же задачи автоматически верифицировать
и в принципе, действительно, можно, но есть две проблемы
первая — что «всюду определенные функции на множестве Кантора»это довольно узкий и бесполезный класс функций… ну вот по тому, что функция p всегда читает не более N(p) битов уже понятно, что ничего особо интересного так реализовать нельзя, правда же?
вторая — что никакой магии на самом деле нет:вот как реализовать forsome без возвышенных слов и хаскелловских трюков? ну вот p ест поток из единиц и нулей… ждем пока p попросит первый бит, после чего одной копии p даем 0, а другой копии даем 1… если p после этого вернула значение, то понятно, что делать… если не вернула, а просит еще бит, то одной копии дали 00, одной 01… и так далее — компактность (сорри, совсем без слов не обошлось ) гарантирует, что рано или поздно это закончится
видно только, что закончится не очень быстро: мы просто перебираем 2^N двоичных последовательностей… в исходном варианте еще и довольно неэффективно всё организовано — но даже если доработать (в блог-посте по прошлой ссылке обсуждаются варианты), то по сути наша магическая проверка корректности алгоритма сводится к тому, что «всё определено на конечном множестве, ну вот на каждой точке этого конечного множества и сравниваем значение с табличным»
и всё-таки если не в самом алгоритме, то в том, как он описан, я какую-то магию вижу… и еще нравится ощущение, что ghci компилирует практически непосредственно математические определения (более опытные люди пишут, правда, что это очень misleading ощущение )
посмотрим еще раз на определение
forsome p = p(find p)(напомню, что p это функция из бесконечных последовательностей нулей и единиц в True/False, а функция forsome должна проверять, выполняется ли p хоть в какой-то точке)
в одной ситуации всё понятно сразу: если p определена как константа (вообще не читает свой вход, а возвращает True или False), то ленивый компилятор даже вникать в определение find не будет, а вернет эту константу — и в этом случае forsome работает правильно
пусть теперь p для возвращения значения достаточно прочитать первые N битов последовательности — будем доказывать индукцией по N, что правильно работают и forsome, и
find p = frst # find(p.(frst#))
where frst = if forsome(p.(0#)) then 0 else 1(напомню, что find должен возвращать пример точки, в которой p верно, если такая точка есть; # обозначает конкатенацию)
функция
p.(0#) в точке x₁ x₂… возвращает p(0 x₁ x₂…) — поэтому ей достаточно прочитать N-1 бит икса — поэтому если p выполняется для какой-либо последовательности, начинающейся с нуля, то frst=0 и find p возвращает правильный первый бит по предположению индукции для forsome… а остальные биты возвращает правильные по предположению индукции для find (оставшиеся подробности индукции опущу)наконец, для любой вычислимой всюду определенной функции p такое N, что p для ответа достаточно первых N битов последовательности, непременно существует — и это топологическое утверждение: проявление компактности множества Кантора (и вот для функций на натуральных числах aka конечных последовательностях 0 и 1 такое свойство очевидно неверно!)
***
после таких фокусов возникают в голове волшебные картины… вот например: если мы умеем проверять равенство функций в смысле совпадения во всех точках — то можно, казалось бы, для одной задачи написать медленный, но точно правильный алгоритм, а дальше любой другой алгоритм решения той же задачи автоматически верифицировать
и в принципе, действительно, можно, но есть две проблемы
первая — что «всюду определенные функции на множестве Кантора»
вторая — что никакой магии на самом деле нет:
видно только, что закончится не очень быстро: мы просто перебираем 2^N двоичных последовательностей… в исходном варианте еще и довольно неэффективно всё организовано — но даже если доработать (в блог-посте по прошлой ссылке обсуждаются варианты), то по сути наша магическая проверка корректности алгоритма сводится к тому, что «всё определено на конечном множестве, ну вот на каждой точке этого конечного множества и сравниваем значение с табличным»
и всё-таки если не в самом алгоритме, то в том, как он описан, я какую-то магию вижу… и еще нравится ощущение, что ghci компилирует практически непосредственно математические определения (более опытные люди пишут, правда, что это очень misleading ощущение )
Telegram
Компьютерная математика Weekly
можно ли сравнить две функции за конечное время?
если вы написали две функции, которые определены на бесконечном множестве, то кажется очевидным, что нельзя написать программу, которая только применяя эти функции (не имея доступа к их коду) проверит за конечное…
если вы написали две функции, которые определены на бесконечном множестве, то кажется очевидным, что нельзя написать программу, которая только применяя эти функции (не имея доступа к их коду) проверит за конечное…
❤5
пока не спалось — нарисовал фрактал Ньютона прямо в excel
(для многочлена — в данном случае, z³-1 — нарисовано, к какому из его корней сходится метод Ньютона, если начинать с данной точки комплексной плоскости)
это работает благодаря двум возможностям современного экселя, которые, кажется, не особенно известны:
1) есть поддержка комплексных чисел… правда немножко специфическая:
2) есть LAMBDA и даже с поддержкой рекурсии! т.е. можно создать свою функцию NewtonIter и написать в ее определение буквально
(в реальности в определение желательно добавить еще обработку обращения в ноль или почти в ноль знаменателя, но эту техническую деталь опущу)
(для многочлена — в данном случае, z³-1 — нарисовано, к какому из его корней сходится метод Ньютона, если начинать с данной точки комплексной плоскости)
это работает благодаря двум возможностям современного экселя, которые, кажется, не особенно известны:
1) есть поддержка комплексных чисел… правда немножко специфическая:
COMPLEX(1,2) выдает "1+2i" и с т.з. экселя это просто строка, операции типа + или * с ней не работают… зато с такими строками работают отдельные функции типа IMSUM, IMPOWER и т.п. — то есть z-(z³-1)/(3z²) превращается в (несколько мучительное) IMSUB(z, IMDIV(IMSUB(IMPOWER(z, 3), 1), IMPRODUCT(3, IMPOWER(z, 2))))2) есть LAMBDA и даже с поддержкой рекурсии! т.е. можно создать свою функцию NewtonIter и написать в ее определение буквально
LAMBDA(z, n, IF(n <= 0, z, NewtonIter(…, n-1))), где многоточие заменяет формулу из предыдущего пункта(в реальности в определение желательно добавить еще обработку обращения в ноль или почти в ноль знаменателя, но эту техническую деталь опущу)
1🔥19😁2❤1🤯1
производные без анализа
школьники говорят, что на сборах по математике для 11 класса рассказывали про производные многочленов без пределов через «предпроизводную» — тоже дело, но мне больше нравится кое-что другое
что такое производная многочлена P? очень просто: если ε²=0, то P(x+ε)=P(x)+εP'(x)
ср. с обычным «(f(x+ε)-f(x))/ε→f'(x) при ε→0» — только теперь никаких пределов не осталось, только алгебра в кольце чисел вида a+bε с соотношением ε²=0
эту алгебру «дуальных чисел» легко реализовать — вот всё, по сути, что нужно для такого автоматического дифференцирования:
ну технически, если сейчас написать
то вместо производной многочлена в единице мы увидим, что возведение дуальных чисел в степень не определено, умножение дуальных чисел на обычные неопределено, вычитание не определено… более технически полноценное определение класса положу в комментарии
***
в связи с дуальными числами можно говорить еще про разную геометрию — так, если умножение на комплексные числа отвечает за повороты, то дуальные числа реализуют любимые мной перекашивания: exp(εt)(x+yε) = x+(y+xt)ε… а также, говорят, реализуют параболические повороты, но эта часть что-то плохо пока в голову уложилась
школьники говорят, что на сборах по математике для 11 класса рассказывали про производные многочленов без пределов через «предпроизводную» — тоже дело, но мне больше нравится кое-что другое
что такое производная многочлена P? очень просто: если ε²=0, то P(x+ε)=P(x)+εP'(x)
ср. с обычным «(f(x+ε)-f(x))/ε→f'(x) при ε→0» — только теперь никаких пределов не осталось, только алгебра в кольце чисел вида a+bε с соотношением ε²=0
эту алгебру «дуальных чисел» легко реализовать — вот всё, по сути, что нужно для такого автоматического дифференцирования:
class Dual:
def __init__(self, a, b=0):
self.a, self.b = a, b
def __add__(self, other):
return Dual(self.a + other.a, self.b + other.b)
def __mul__(self, other):
return Dual(self.a * other.a, self.a * other.b + self.b * other.a)
def diff(f, x):
return f(Dual(x, 1)).b
ну технически, если сейчас написать
def poly(x):
return x**2-3*x-1
print(diff(poly,1))
то вместо производной многочлена в единице мы увидим, что возведение дуальных чисел в степень не определено, умножение дуальных чисел на обычные неопределено, вычитание не определено… более технически полноценное определение класса положу в комментарии
***
в связи с дуальными числами можно говорить еще про разную геометрию — так, если умножение на комплексные числа отвечает за повороты, то дуальные числа реализуют любимые мной перекашивания: exp(εt)(x+yε) = x+(y+xt)ε… а также, говорят, реализуют параболические повороты, но эта часть что-то плохо пока в голову уложилась
👍5❤3
пока каменный цветок не выходит (положу в комментарии, как это выглядит) — поделюсь ссылкой на компьютерную игру: https://adam.math.hhu.de/#/g/AlexKontorovich/RealAnalysisGame
(первое впечатление:это невыносимо, непонятно как кто-то может в этом формализовывать какие-то содержательные доказательства… но мб у вас получится лучше)
(первое впечатление:
🔥3🤨1
This media is not supported in your browser
VIEW IN TELEGRAM
многим рассказывал¹, как нарисовать «ленивый додекаэдр»: взять куб и поделить каждую грань пополам регулярным образом — как раз получится 6×2=12 граней, 8+12=20 вершин (вершины куба и середины его ребер)… вся комбинаторика получается правильная
если хочется еще и правильной геометрии — нужно просто немного всё продеформировать, это и показано в видео
¹ и даже писал в «Квантике» — см. №9 за 2025 год
***
как такое нарисовать и не перетрудиться? начнем с вершин куба — это просто все точки с координатами ±1
чтобы получить додекаэдр, надо добавить еще 12 вершин… не хочется их все писать руками, но тут есть большая группа симметрий G: можно переставлять координаты по циклу и расставлять знаки — и так все новые вершины можно получить из одной, (φ,0,1/φ)… и что еще приятнее, все грани можно получить из одной
(результат действия элемента g на набор точек f0 — это просто tuple(g(v) for v in f0) — но в faces надо положить не координаты этих точек, а номера соответствующих вершин)
если в качестве phi и psi взять не (±1+√5)/2, а 1, то додекаэдр превратится в куб с дополнительными вершинами в серединах ребер — и такая деформация анимируется в manim примерно в одну строчку
приведу еще код для генерации группы G
(а всё собранное целиком положу в комментарии — с использованием симметрии ~20 строк получилось… ну если с паузами и вращением камеры, то чуть больше)
***
видно, кстати, что в группе G всего 24 элемента, из которых 12 сохраняют ориентацию… а всего в группе I симметрий додекаэдра 12×5=60 вращений — получаем действие I⁺ на 60/12=5 элементах I⁺/G⁺, который дает изоморфизм I⁺≃A₅
конечно, то же можно сказать и более геометрически: G это как раз подгруппа симметрий додекаэдра, сохраняющих вписанный в него куб, а 5-элементное множество I⁺/G⁺ отождествляется с 5 вписанными в додекаэдр кубами («кубы Кеплера») — вот эти кубы I⁺ и переставляет
если хочется еще и правильной геометрии — нужно просто немного всё продеформировать, это и показано в видео
¹ и даже писал в «Квантике» — см. №9 за 2025 год
***
как такое нарисовать и не перетрудиться? начнем с вершин куба — это просто все точки с координатами ±1
from itertools import product
vertices = list(product([-1,1], repeat=3))
чтобы получить додекаэдр, надо добавить еще 12 вершин… не хочется их все писать руками, но тут есть большая группа симметрий G: можно переставлять координаты по циклу и расставлять знаки — и так все новые вершины можно получить из одной, (φ,0,1/φ)… и что еще приятнее, все грани можно получить из одной
v0 = (phi,0,psi)
vertices += [g(v0) for g in G()]
f0 = [(phi,0,-psi),(1,1,-1),(psi,phi,0),(1,1,1),(phi,0,psi)]
faces = [tuple(vertices.index(g(v)) for v in f0) for g in G()]
poly = Polyhedron(vertices, faces)
(результат действия элемента g на набор точек f0 — это просто tuple(g(v) for v in f0) — но в faces надо положить не координаты этих точек, а номера соответствующих вершин)
если в качестве phi и psi взять не (±1+√5)/2, а 1, то додекаэдр превратится в куб с дополнительными вершинами в серединах ребер — и такая деформация анимируется в manim примерно в одну строчку
приведу еще код для генерации группы G
def G():
for signs in product([-1,1], repeat=3):
for r in range(3):
yield lambda x: tuple(x[(i+r)%3]*signs[i] for i in range(3))
(а всё собранное целиком положу в комментарии — с использованием симметрии ~20 строк получилось… ну если с паузами и вращением камеры, то чуть больше)
***
видно, кстати, что в группе G всего 24 элемента, из которых 12 сохраняют ориентацию… а всего в группе I симметрий додекаэдра 12×5=60 вращений — получаем действие I⁺ на 60/12=5 элементах I⁺/G⁺, который дает изоморфизм I⁺≃A₅
конечно, то же можно сказать и более геометрически: G это как раз подгруппа симметрий додекаэдра, сохраняющих вписанный в него куб, а 5-элементное множество I⁺/G⁺ отождествляется с 5 вписанными в додекаэдр кубами («кубы Кеплера») — вот эти кубы I⁺ и переставляет
1🔥17❤9👏2👍1