Меня зовут Артур Валиев. Недавно мне пришлось объяснять племяннику совершенно страшную математическую конструкцию:
Ну то есть страшную примерно настолько, насколько вообще способно быть страшным линейное уравнение. Я сначала, совершенно по-взрослому, приготовился объяснить: «Переносим четвёрку вправо с противоположным знаком...» — и в этот момент сам себя остановил.
А почему?
Почему четвёрка, пересекая знак равенства, внезапно меняет знак? Что это вообще за портал такой? Слева она была +4, пролетела через = — и вышла оттуда уже как -4.
Если ребёнок спросит «почему?», ответ «ну такое правило» звучит подозрительно даже для человека, который давно окончил школу. А если спросить ещё раз «почему?» — внезапно обнаруживается довольно большая нора.
Так начался MathRoots.
Я вообще никогда нормально не понимал учителя у доски
Здесь, наверное, стоит сделать небольшое признание. В моей юности я практически не помню случаев, когда учитель объяснял что-то у доски, а я сидел и думал: «О! Всё понятно». Обычно происходило наоборот. Учитель что-то написал, класс дружно закивал, я тоже на всякий случай покивал, а потом приходил домой и начинал буквально археологические раскопки.
Почему здесь минус? Откуда появилась двойка? Почему здесь можно сократить, а здесь нельзя? Почему дробь вдруг перевернулась? Почему при раскрытии скобок поменялись знаки? Почему вообще разрешено делать то, что мы сейчас делаем?
Ответы приходилось собирать кусочками: из учебника, из другого учебника, у знакомых, из примеров, иногда просто начиная с ответа в конце задачника и пытаясь восстановить весь путь назад.
И спустя много лет я понял довольно простую вещь. Возможно, мне плохо давалась не сама математика. Возможно, мне плохо давался формат передачи математики.
Фраза «перенеси слагаемое за знак равенства с противоположным знаком» очень компактна. Для человека, который уже понимает алгебру, это прекрасное сокращение. Но ребёнок слышит буквально следующее:
То есть знак равенства превращается в какой-то математический телепорт, который меняет знаки у пролетающих через него чисел.
И самое интересное начинается позже. Сегодня ребёнок запомнил, что +4 можно каким-то образом сделать -4. Завтра перед ним: 2x = 6
И здесь внезапно оказывается, что двойку уже нельзя «перенести с минусом». Нужно делить. Потом появляется:
и тройку почему-то надо умножать. Возникает набор отдельных жестов, которые нужно узнавать по внешнему виду задачи.
Мне захотелось попробовать построить объяснение наоборот: не учить жестам, а докапываться до причины.
Никакого переноса не существует
Вернёмся к нашему:
Представим обычные чашечные весы. На левой чаше находятся две одинаковые закрытые коробки неизвестной массы и ещё четыре гири по одному килограмму. На правой — десять таких же гирь. Весы находятся в равновесии.
Вот, собственно, и весь смысл знака =. Это не стрелка вычисления и не приглашение начать переносить что-то справа налево. Это утверждение: слева сейчас столько же, сколько справа.

Мы хотим узнать массу одной коробки. Четыре гири слева мешают, поэтому хочется их убрать. Но если снять четыре гири только с левой чаши, равновесие нарушится. Значит, снимаем одинаковый вес с обеих сторон:
Получаем: 2x = 6
Никакая четвёрка никуда не переходила. Мы просто выполнили одинаковую операцию с двумя равными величинами и сохранили равенство.
Теперь слева две одинаковые коробки, справа — шесть килограммов. Делим обе части на две одинаковые группы:
и получаем:
Можно сразу замкнуть петлю и проверить:
Всё сошлось.
И вот это уже не совсем «правило решения одного уравнения». Ребёнок получил модель: равенство — это баланс; если меняешь одну сторону, нужно выполнить эквивалентное изменение другой стороны.
Намного позже это можно назвать равносильным преобразованием, свойством равенства и так далее. Но сначала есть физическая модель, которую можно потрогать головой.
Для программиста я бы вообще описал это словом инвариант. Мы можем сколько угодно преобразовывать состояние системы, пока сохраняется главное условие: левая часть остаётся равна правой.
После этого «перенос через равно» становится всего лишь удобным синтаксическим сахаром.
И тут программист во мне окончательно испортил урок
После объяснения с весами я подумал: а почему математическая задача вообще должна представляться как линейный список шагов?
Обычно учебник выглядит примерно так:
Шаг 1 Шаг 2 Шаг 3 Шаг 4 Ответ
Но в программировании сложные системы мы так почти никогда не воспринимаем. У функции есть зависимости, у пакета есть зависимости, у бага есть root cause, одна абстракция строится поверх другой.
Почему бы математическое знание не показать таким же образом?
Так появилась главная идея MathRoots:

Любая сложная задача имеет корни.
Вместо линейной инструкции я решил представлять задачу как граф понятий. Внизу находятся наиболее фундаментальные вещи, выше — свойства операций, затем алгебраические конструкции, промежуточные состояния и, наконец, сама цель.
Для 2x + 4 = 10 это условно выглядит так:
Layer 4 x = 3 ▲ Layer 3 2x = 6 ▲ Layer 2 Деление обеих частей на 2 ▲ Layer 1 Вычитание 4 с обеих сторон ▲ Layer 0 Сохранение равенства
И здесь появилась мысль, которая мне нравится больше всего: если человек не понимает верхний узел, необязательно ещё десять раз объяснять верхний узел. Возможно, проблема находится на три уровня ниже.
Математика как dependency graph
Возьмём совсем простое:
Мы говорим: делим на три и получаем x = 4.
Ребёнок спрашивает: «Почему делим?» — потому что перед x стоит коэффициент. «А что такое коэффициент?» — число, на которое умножается переменная. «А откуда я должен знать, что 3x — это умножение?»
И вот мы уже спускаемся ниже.
То есть перед нами три одинаковые группы. Если три одинаковые группы вместе дают 12, одна группа должна давать:
Получается цепочка:
сложение ↓ повторяющееся сложение ↓ умножение ↓ коэффициент ↓ обратная операция ↓ деление ↓ линейное уравнение
Такие связи в MathRoots я начал называть мостами понятий. Сложение ведёт к умножению. Умножение — к степени. Степень — к логарифму. Равенство — к физическому балансу.
Например:
можно сначала объяснить не академическим определением логарифма, а обычным вопросом: в какую степень нужно возвести 2, чтобы получить 8?
И после этого страшный log внезапно оказывается обратным вопросом к уже знакомой операции.
Мне вообще кажется важным, чтобы формула появлялась после возникновения вопроса, а не наоборот. Когда сначала дают формулу, а потом пытаются убедить ученика, что ему очень интересно узнать её смысл, последовательность немного странная.
Поэтому интерфейс получился не совсем как у учебника
Когда знания превращаются в граф, обычная страница с текстом начинает немного мешать. Поэтому центральным интерфейсом стал большой интерактивный холст — что-то вроде Infinite Canvas.
По нему можно двигаться, приближать и отдалять отдельные ветви, открывать узлы и смотреть, на каких понятиях они построены.
Причём я захотел сделать не просто zoom, при котором карточка становится больше или меньше, а семантический зум. На большом отдалении подробности исчезают и остаётся общий рисунок дерева. При приближении появляются названия тем и формулы. Ещё ближе — объяснения, упражнения, зависимости и дополнительные инструменты.
На одном масштабе пользователь видит:
●────●────● │ ●────●
На другом тот же узел уже превращается примерно в такое:
[Сохранение равенства] a = b ↓ a - c = b - c Почему это допустимо? Попробовать на весах Мини-упражнение Связанные понятия
То есть масштаб меняет не столько размер пикселей, сколько количество показываемого смысла.
Когда деревья становятся большими, это довольно сильно спасает от стены карточек.
Кнопка «Почему?» оказалась интереснее кнопки «Ответ»

Одна из моих любимых идей в MathRoots — кнопка «Почему я могу это сделать?»
Большинство обучающих решений прекрасно отвечает на вопрос: «Что делать дальше?» Но гораздо интереснее вопрос: «Почему мне вообще разрешено выполнить этот шаг?»
Причём объяснение зависит от человека.
Возьмём распределительный закон:
Десятилетнему ребёнку его можно показать на коробках: есть две коробки, в каждой банан и три яблока. Значит, всего два банана и шесть яблок.
Школьнику уже можно сказать про распределительное свойство умножения.
Если хочется формальности — уйти в свойства алгебраических структур.
А программисту можно сказать примерно так: мы преобразуем AST выражения, применяя множитель ко всем дочерним узлам, но сохраняем семантическую эквивалентность результата.
Условно:
Когда я впервые сформулировал такое объяснение, понял, что именно его самому хотел бы услышать много лет назад.
Мне всегда было проще понять фразу:
«Это преобразование дерева выражения с сохранением результата»
чем:
«Запомни правило раскрытия скобок».
Потом появился математический debugger
И здесь профессиональная деформация программиста окончательно победила.
Если программа упала на пятнадцатом уровне стека вызовов, мы ведь не запускаем одну и ту же функцию ещё пятьдесят раз в надежде, что она «натренируется». Мы ищем root cause.
Почему с математической ошибкой нельзя поступать так же?
Так появился Gap Finder / Stuck Debugger.

Предположим, ученик ошибается при решении какого-то уравнения. Вместо того чтобы сразу показать правильный ответ, можно пройти вниз по зависимостям текущего шага.
Ошибка здесь ↓ проверяем зависимость ↓ здесь всё понятно ↓ ещё ниже ↓ ага
И выяснить, например, что проблема вообще не в линейных уравнениях. Человек просто не до конца понимает отрицательные числа.
Тогда вместо двадцатого уравнения подряд ему можно дать маленькую проверку:
Если именно здесь обнаруживается пробел, сначала закрывается он, а затем человек возвращается к исходной задаче.
Для себя я называю это когнитивным долгом. Он очень похож на технический. Небольшая проблема в фундаменте долго может не мешать. Поверх неё строятся новые уровни абстракций, потом ещё новые, и однажды вся конструкция становится настолько шаткой, что человек делает вывод: «Наверное, у меня просто не математический склад ума».
Хотя где-нибудь очень глубоко остался всего один непонятый кирпич.
В MathRoots под это есть отдельный поиск пробелов и журнал трудных концепций, чтобы проблема не исчезала после закрытия текущей задачи, а постепенно формировалась карта слабых мест.
Одними графами ребёнка долго не удержишь
Поэтому появилась визуальная лаборатория. Сейчас там девять интерактивных симуляторов.

Самый очевидный — те самые чашечные весы. Можно нарушить баланс и увидеть, что произошло, а не просто прочитать ещё один абзац о свойствах равенства.
Есть парабола:
где можно менять a, b, c и сразу видеть, как двигаются корни и меняется форма графика.
Есть тригонометрический круг, теорема Пифагора, дроби, степени и логарифмы, системы прямых и векторы.
Отдельно мне нравится лаборатория производной. Вместо того чтобы сразу обрушить на человека:
сначала можно показать две точки на графике и секущую между ними. Затем уменьшать расстояние между точками и наблюдать, как секущая постепенно превращается в касательную.
После этого предел уже отвечает на возникший визуальный вопрос, а не появляется как магическая конструкция из учебника.
И да, потом сюда всё-таки добрались нейросети
Первоначально мне хотелось построить именно концепцию представления знаний. Но довольно быстро выяснилось, что вручную сделать деревья на огромный объём математики — хороший способ закончить проект примерно к пенсии.
Поэтому появился AI Decomposer.
Пользователь может дать произвольную задачу, а модель должна не просто вернуть готовый ответ, а попытаться разложить её на структуру:
цель ↑ промежуточные шаги ↑ необходимые правила ↑ базовые понятия
Например, текстовая задача про два поезда сначала раскладывается на расстояние, скорость и время. Потом появляется понятие скорости сближения, затем уравнение и только в самом конце численный ответ. В проектной модели даже обычная задача на движение раскладывается по тем же слоям — от фундаментальных понятий до проверки результата.
Мне хотелось, чтобы нейросеть здесь была не столько машиной:
«реши мне домашнюю работу»,
сколько архитектором графа знаний.
Есть и ручной Tree Builder: можно создавать узлы самостоятельно, связывать их, писать формулы в TeX и делиться готовыми деревьями.
При этом привязываться к одному AI-провайдеру я не хотел. Поэтому есть серверный режим и BYOK — Bring Your Own Key. Можно подключить разные API или OpenAI-compatible endpoint, вплоть до локальной модели. Пользовательские ключи в BYOK-режиме задуманы так, чтобы храниться локально в браузере и не записываться в PostgreSQL.
Нейросети помогали делать и сам MathRoots
Здесь тоже не буду изображать человека, который месяцами вручную высекал каждый <div> из гранита.
Основную концепцию — дерево, корни, слои, поиск фундаментального пробела — я набросал сам. А интерфейс, дизайн, варианты взаимодействия и часть логики уже активно добивал с помощью нейросетей.
Это оказалось интересным опытом.
AI довольно легко отвечает на просьбу:
Сделай красивую карточку.
Заметно сложнее становится, когда вопрос звучит так:
Что должно произойти, если пользователь уменьшил граф до 30%, провалился в зависимость третьего уровня, включил режим диагностики, закрыл его и должен вернуться ровно в то состояние холста, где находился?
Красивые первые 80% интерфейса сейчас действительно можно получить удивительно быстро. Последние 20%, где появляется связность продукта, его поведение и куча неприятных мелочей, всё ещё требуют много ручного мышления.
В MathRoots нейросети в итоге оказались сразу в двух ролях: как инструмент разработки и как часть самого продукта.
Немного рекурсии.
Ещё одна школьная мина: -3²
Когда я уже полез во всё это глубже, вспомнилась другая замечательная проблема:
и:
В первом случае:
Во втором:
Разница — пара скобок, но смысл полностью меняется.
То же самое с 2x, 2(3) и (x+1)(x-1). Для взрослого человека неявное умножение давно стало почти невидимым. Для ребёнка 2x далеко не обязательно автоматически означает:
Поэтому появился инспектор математического синтаксиса. Он разбирает выражение как AST и пытается показать, какой оператор к чему относится, где находится скрытое умножение, как работает приоритет операций и почему скобки меняют структуру выражения.
Опять профессиональная деформация. Но если IDE способна показать программисту, почему его выражение распарсилось не так, как он ожидал, почему математический интерфейс не может делать примерно то же самое?
Что внутри технически
Я специально не хотел превращать образовательный эксперимент в распределённую систему из сорока семи микросервисов, Kubernetes и Kafka для вычисления 2 + 2.
Стек сейчас довольно земной: React 19, TypeScript, Vite, Tailwind CSS, KaTeX, Node.js + Express и PostgreSQL. Сам холст работает как интерактивная карта, связи между узлами рисуются векторно, а формулы рендерятся через KaTeX. В проектном обзоре отдельно описаны семантический зум, SVG-связи и режим фокуса на выбранной цепочке понятий.
Есть пошаговый тренажёр с набором задач, проверкой промежуточных шагов и подсказками.
На своем домене я добавил простую openroute модель, но даже без авторизации любой пользователь может подключить что-то свое. Либо развернуть все у себя. Поэтому отдельно пришлось подумать о стоимости AI которыми пользователи захотят использовать. Если десять человек попросят разобрать одно и то же:
немного обидно десять раз платить модели за размышления над судьбой четвёрки.
Поэтому в архитектуре предусмотрен кэш: запрос нормализуется, из него считается SHA-256, после чего можно проверить, не разбиралась ли такая задача раньше. Если ответ уже есть, его можно вернуть из базы без нового запроса к модели.
А можно просто поставить у себя
Проект я выложил открыто на GitHub
Живую версию можно пощупать здесь (Десктоп, мобильной версии нет)
Разворачивается через Docker Compose. В минимальном варианте:
git clone https://github.com/vaalimusic/mathroots.git cd mathroots docker compose up -d --build
После этого приложение доступно на:
http://localhost:3000
Вместе с приложением поднимается PostgreSQL.
Сам проект распространяется по MIT, так что его можно спокойно разбирать, менять, использовать для своих экспериментов или отправлять pull request'ы.
Я не пытаюсь заменить школу
Здесь важная оговорка. Я не педагог и не утверждаю, что нашёл какой-то единственно правильный способ преподавать математику.
MathRoots для меня прежде всего эксперимент с представлением знания.
Мне интересно, что произойдёт, если вместо:
Тема 1 Тема 2 Тема 3 Контрольная Тема 4
показать человеку:
[сложная задача] / \ / \ [понятие] [понятие] | | [основа] [основа] \ / [фундамент]
И если при любой непонятной операции дать возможность задать бесконечно детский вопрос:
Почему?
Не «какое правило здесь применяется?», а именно:
Почему это истинно?
Мне кажется, это довольно разные вопросы.
Самый неожиданный результат
Когда я начинал, мне казалось, что я делаю приложение для школьников.
А потом несколько раз поймал себя на том, что сам открываю очередной узел и мысленно задаю ему тот же вопрос: «А почему?»
И обнаруживается забавная вещь. Ты умеешь выполнять операцию. Быстро решаешь пример. Помнишь правило. Можешь даже объяснить его кому-нибудь другими словами.
Но стоит пройти вниз по дереву до самого основания — и иногда появляется мысль:
А вот об этом я, кажется, никогда особенно не задумывался.
Наверное, в этом и осталась для меня главная идея MathRoots.
Не обязательно делать математику проще. Иногда достаточно сделать видимыми ступеньки, через которые мы привыкли перепрыгивать.
А началось всё с совершенно безобидного:
и попытки объяснить ребёнку, почему четвёрка вдруг должна поменять знак.
Если захотите пощупать проект:
Демо: https://math.everty.ru/
GitHub: https://github.com/vaalimusic/mathroots
Особенно интересно было бы услышать преподавателей: где такой граф действительно помогает понять материал, а где я, как программист, слишком увлёкся превращением школьной математики в dependency graph.
Ну и если кто-нибудь знает, кто первым придумал говорить детям, что числа «переходят через равно и меняют знак», — расскажите.
Потому что никаких порталов там всё-таки нет.
Комментарии (7)

mikhanoid
09.09.2026 03:22Не работает :) Ввёл в качестве цели решение задачи 2x^3 + 4x^2 + 10x + 18 = 15, оно вместо этого начло разбирать решение x^2 - 5x + 6 = 0.
Интерфейс тоже кривой. Не смог вернуться из дерева разбора задачки в начало. Прогресс сохраняется где-то в печеньках, пришлось поэтому запускать из другого профиля, чтобы порешать другую задачу.
Ну, и то, что 3x = x + x + x - оно как бы с точки зрения пояснения того, что есть такое умножение в корне не верно.

isa75
09.09.2026 03:22Как раз детям в школе очень долго и подробно объясняют почему число при переносе в другую часть равенства меняет знак. Странно что автор с этим затрудняется...

4730635
09.09.2026 03:22Автор не затрудняется, он объясняет тем, кто затрудняется, что можно и по-другому увидеть решение. Довольно большое число учеников уже на подходе к ОГЭ забывают поменять знак.

engine9
09.09.2026 03:22По-моему очень элегантно! Удивительно, но и мне зашло, хотя я не школьник давно.

Hait
09.09.2026 03:22Мне кажется, что первая визуализация только путает. "Гири" должны быть одинаковые на обеих сторонах.
А то слева они оранжевые и большие, а справа зеленые и маленькие
lamerok
Классно, но интерфейс..... Для ребёнка это перебор, мне кажется.
ИМХО, нужно задачки выносить отдельно, делать более крупными вопросы и давать возможность ребенку попробовать решить, без подсказок.