AngouriMath
AngouriMath.Core.Transformations
Classes within the AngouriMath.Core.Transformations namespace
RewriteRecording
Summary
Collects the rewrites that fire while it is open, so that an answer can be asked how
it was reached rather than only what it is.
Remarks
Off unless asked for, and off is free: with no recording open, applying a rule set
costs one ambient read more than it did before — per rule set, not per node — and
allocates nothing. That is the condition
#746 puts on
every layer above the tree, and it is why this is a scope rather than a setting that
something might leave on.
Per flow, like Settings: the recording belongs to the call rather
than to the thread running it. It survives anawait , and work
started under it — including on another thread — reports to it. A recording opened
inside a task is invisible to that task's siblings and to whatever started it.
Order is not guaranteed once work is parallel. Steps from one flow keep the
order they fired in, but two flows recording into the same open recording interleave
however they happen to run. The single-threaded case — which is what
Simplify(System.Int32) is — is unaffected.
What this is not. It records rewrites — which is what
#28 asks for —
and not everything Simplify(System.Int32) does. Simplification also
expands, factorises, divides polynomials, minimises boolean expressions and then
*chooses* among the candidates by a complexity metric; the steps below are the
rewrites, in the order they fired, across every candidate that was generated,
including the ones that lost. Reading them as a route from the input to the returned
answer would be reading in something that is not there.
Example
using AngouriMath; using AngouriMath.Core.Transformations; using var recording = RewriteRecording.Start(); var simplified = ((Entity)"a / (b / c)").Simplify(); foreach (var step in recording.Steps) Console.WriteLine(step);RewriteRules
Summary
The rewrite rule sets this library ships, as data: named, described, attributed with
what they claim, and enumerable through All.
Remarks
Registration is explicit and static — there is no assembly scanning and no
Activator , so the registry survives trimming and NativeAOT, and
All is in a fixed order that does not depend on hashing, reflection or
which type happened to be loaded first.
Every rule set the simplifier applies is registered here, and the simplifier reaches
them through this registry rather than throughPatterns directly. That is what
lets an account of what the simplifier did to an expression be a complete one: a set
reachable only by its method has no name to report and nothing to attribute a step to,
so a derivation built while some sets were still unregistered would quietly omit
whatever they had done.
Every entry is declared SoundUnderAssumptions. That is a claim
about what has been argued, not about what is true — nothing here checks a tier, so
the registry starts conservative and promoting an entry means making the case for it.
RewriteRuleSet
Summary
A named, attributable group of rewrites — the unit this library has always written
them in — carrying what it is called, what it claims and how well justified the
claim is, so that the set can be enumerated, tested and referred to by name instead
of only being called.
Remarks
The set, rather than the single pattern -> replacement line, is the unit
here because that is what has been built so far — not because the finer grain
is too expensive. It was asserted here that it would be, on the grounds that each
rule would cost a delegate call per node; measuring it found the opposite, and the
measurement is in
#825: rules
bucketed by the node type they match run as fast as the hand-writtenswitch at realistic set sizes and faster at small ones, because a largeswitch over
distinct node types is compiled into that same dispatch anyway.
What actually stands in the way is transcription: splitting forty switch arms
by hand is forty chances to change a pattern silently. That points at a source
generator over the existing bodies rather than at leaving the rewrites unnamed. See
#746 item 50,
and note that nothing here forecloses it: a set whose rewrites become individually
addressable keeps the same name and the same entry in the registry.
RewriteRuleSetExtensions
Summary
Reading order for ApplyOnce(AngouriMath.Entity).
Remarks
The simplifier applies a dozen rule sets in sequence, and written as calls the
sequence reads inside out. This is the same operation with the expression in front,
so that a pipeline still reads in the order it runs.
RewriteStep
Summary
One rewrite that actually fired: which rule set did it, the subexpression it matched,
and what it put there instead.
Remarks
The subexpression, not the whole expression. A rewrite pass walks the tree bottom-up
and rewrites nodes as it goes, so there is no moment at which a partly-rewritten
whole expression exists to be photographed — reporting one would mean building it,
and it would be a picture of something the engine never held.
Soundness
Summary
How well justified the relation a Transformation claims between its
input and its output is. The three tiers are never blurred: a heuristic labelled as
a proof is a wrong answer with a friendly face.
Remarks
The tier is declared by whoever wrote the transformation, not derived from it.
Nothing in the library checks a declaration today, so a tier is a claim to be argued
with rather than a guarantee to be relied on, and the registry starts conservative
on purpose: tightening a label needs an argument, loosening one does not.
Transformation
Summary
A named mathematical operation that consumes an Entity and produces
one, together with enough about itself — what it claims, how well justified the
claim is — to be inspected and composed rather than only invoked.
Remarks
This is the layer the 1.x entry points sit on:
Simplify(System.Int32), Expand(System.Int32) and
Factorize(System.Int32) are adapters over the transformations named
below, and the algorithms underneath are unchanged. Callers who only want an answer
should keep using those methods; this type is for callers who want to know which
operation produced it, or to build an operation out of others.
Deterministic: the same transformation applied to the same expression under the same
Settings gives the same result. Composition is by explicit
ordering — there is no registry that decides what to run next, and nothing here
consults reflection, so the layer stays trimmable and AOT-publishable.
Experimental. The three concepts — a transformation, its relation, its
soundness tier — are meant to last; the catalogue of factories will grow and the
signatures here may still move. The stable surface is MathS and the
methods on Entity.
Example
using System; using AngouriMath; using AngouriMath.Core.Transformations; Entity expr = "(x + 1) ^ 2"; var result = Transformation.Expansion.Apply(expr); Console.WriteLine(result.Output); Console.WriteLine(result.Relation); Console.WriteLine(result.Soundness);
Prints
1 + 2 * x + x ^ 2 Equivalence SoundUnderAssumptionsTransformationRelation
Summary
What a Transformation claims about its output relative to its input.
Without this, Soundness would be meaningless: "sound" is only a
statement about some relation, and the relation is not the same one for every
operation.
TransformationResult
Summary
What one application of a Transformation produced: the input, the
output if there was one, and which transformation was asked.
Remarks
A struct, so that routing an ordinarySimplify orDifferentiate call
through this layer costs no allocation.
Angouri © 2019-2023 · Project's repo · Site's repo · Octicons · Transparency · 1953 pages online