# CA **Repository Path**: mirrors_floatdrop/CA ## Basic Information - **Project Name**: CA - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-24 - **Last Updated**: 2026-05-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README Computer Algebra System for .NET Framework ================================ # Introduction # A computer algebra system (CAS) is a software program that facilitates symbolic mathematics. The core functionality of a CAS is manipulation of mathematical expressions in symbolic form. Usually, to perform such manipulations, the original data are represented as syntax trees and then they are transformed using some rules. The main aim of this project is to provide flexible and comfortable way to specify such transformation rules. Many CAS systems are developed either small research projects and enterprise software. However, no one is implemented in .NET framework, which is a modern programming technology, widely used for research, education and software development. To our knowledge, only one .NET solution exists, named Math.NET. However, it could hardly considered as a full-fledged computer algebra system. Transformation rules are not programmed as a separate entity, and are substituted by Visitor pattern that processes nodes in a tree according to its function. This decision hampers the system's expanding, because addition of new operations demands alterations in the existed code. Moreover, even operations like the differentiation of the exponential function are still not implemented. To develop a computer algebra system, we need to build convenient and reliable framework for rules definition and application. Such frameworks are the core part of all existed CAS. In this work, we present our solution for this task, based on .NET framework. We do not have an objective to write enterprise computer algebra software, because the market already has many solutions. However, we believe that our solution will be useful in research area, because it gives an opportunity to work with symbolic computations with a modern and effective programming languages. Also, as we will see below, .NET framework and C# language provides several syntax features, which facilitate definition of transformational rules. The usage such features for transformation rules programming gives a fresh look on symbolic computations, and could be resulted in new approaches to computer algebra systems. # Rule definition # Application of the rule can be subdivided into the three stages. In *sampling* stage, the system that applies rules (which will be called *driver* below) selects some tree-like structure from the syntax tree, and presents its nodes as a tuple. In *selection* stage, the driver sort out the tuples that do not meet the specified criteria. In third stage, called *modification*, the driver transforms the tree according to the rule. In the most widespread case, the rule processes one tree. For such *unary* rules, the original tree is copied, and then the copy is rearranged according to rule. In some cases, the rule processes more than one tree. For example, in logical interference modus ponens rule accepts two trees *A → B* and *A* and produces *B*. In this case, new tree is to be created and built with nodes copies from selected tuple. Since the driver always copies the nodes before manipulation, the corectness of initial trees is preserved. ## Sampling ## To perform the sampling stage, we should specify the tree-like structure we search in a tree. Also, we need to map the nodes in the structure into a tuple of nodes. We used query strings of our own syntax to do that. Let us demonstrate the syntax of query string with the following example. Consider syntax tree in the Figure 1. In the Table 1, we present various query string, along with corresponded selections and comments. 
| Query String | Tuples | Comment |
|---|---|---|
| A | (1) | The root of the tree |
| ?A | (1),(2),(3),(4),(5),(6) | An arbitrary node in a tree |
| ?A(B) | (5,6) | An arbitrary node, that has only one child, and this child |
| ?A(B,C) | (1,2,5), (2,3,4) | An arbitrary node in a tree with its two children in fixed order |
| ?A(.B,.C) | (1,2,5), (1,5,2), (2,3,4), (2,4,3) | An arbitrary node with its two children in unconditioned order |
| ?A(.B) | (1,2), (2,3), (2,4), (5,6) | An arbitrary node with its one child |
| ?A(?B) | (1,2), (1,3), (1,4), (1,5), (1,6), (2,3), (2,4), (5,6) | An arbitrary node with its arbitrary descendant |
| ?A(?B(?C)) | (1,2,3), (1,2,4), (1,5,6) | An arbitrary node, its descendant and descendant of the descendant |
| ?A(?B(C,D)) | (1,2,3,4) | An arbitrary node that has a descendant with two child |
Rule.SelectWhere, which takes array of INode, generates IEnumerable<SelectOutput> and passes this enumeration to delegate where
with type Func<SelectOutput,WhereOutput>. This delegate verify the matching of the tuple to the filter and generates WhereOutput object, corresponding to the filtered tuple.
## Modification ##
When selection stage is over, we obtain several tuples that could be modified in the modification stage. However, only one of them will be actually processed, because application of the rule may invalidate other tuples.
Therefore, modification stage processes only one of the selected tuples. We have developed a "clean" modification, which does not affect the initial trees. Instead, in the modification stage we create a copy of selected
trees, and perform modification on the copy. To do that, we must find the roots of nodes, presented in a given tuple, clone them, and further process a newly created tuple with a corresponding clones of nodes.
For this functionality responds method Rule.Apply, which takes WhereOutput object. Than it makes copy of this object through method WhereOutput.MakeSafe and passes this copy to
delegate apply, where modification performs.
## Creating new rule ##
Full rule definition looks like this:
```csharp
Rule
.New("+0", StdTags.Algebraic, StdTags.Simplification, StdTags.SafeResection)
.Select(AnyA[ChildB, ChildC])
.Where<Arithmetic.Plus<double>, Constant<double>, INode>(z => z.B.Value == 0)
.Mod(z => z.A.Replace(z.C.Node));
```
This rule looks for subtrees *X+0* or *0+X* and replaces them with *X*. We have already defined a few collections of rules to implement some functionality and further we will tell you what exactly
you can do with the system to date.
# Simplification and Differentiation #
You can find rules for simplification and differentiation in classes AlgebraicRules and DifferentiationRules accordingly. To simplify expression with existing rules use method
ComputerAlgebra.Simplify like this:
```csharp
ExpressionComputerAlgebra.Differentiate:
```csharp
ExpressionSimplificationDemo, DifferentiateDemo, and in test classes SimpleTests, DifferentiationTest
# Regression #
The first aim of our research was symbolic regression task, where we used simplification rules to improve the existed solutions of evolutionary symbolic computations. In symbolic regression, genetic algorithm processes
expressions with mutation and crossover, and gradually creates the expression that fits experimental data. Constants in expressions are found also by mutation. We improve this part of algorithm with standard well-known
numerical regression. Suppose the algorithm has found function *F(x1,...,xn)* as the potential solution. Let *Φ(x1,...,xn,c1,...,cm)* be a
function *F* where constants are replaced with arguments *ci*. Let *E(c1,...,cm)* be an error function:

where the set  is the experimental data. With differentiation rules, we can calculate
 and improve *ci*
with gradient descent so *Φ* fits experimental data better. This technique is experimentally tested and proved to be better than finding constants with genetic algorithm.
We have decided to split evolutionary algorithms and symbolic computation, so now you can use numerical regression regardless of the genetic algorithm. To do that you should create new instance of
RegressionAlgorithm class and call method Run(). The constructor of RegressionAlgorithm takes expression, experimental data, accurance and initial step for gradient descent.
You can find the examples of this in RegressionDemo project and RegressionTests class.
# Resolution #
The resolution technique is very simple:
1. Find two clauses containing the same predicate, where it is negated in one clause but not in the other.
2. Perform a unification on the two predicates. (If the unification fails, you made a bad choice of predicates. Go back to the previous step and try again.)
3. If any unbound variables which were bound in the unified predicates also occur in other predicates in the two clauses, replace them with their bound values (terms) there as well.
4. Discard the unified predicates, and combine the remaining ones from the two clauses into a new clause, also joined by the ∨ operator.
All predicates must be in Skolem normal form, therefore we needs some tool to define quantifier-free part of such predicates. To do that we have generated several methods and constants. So now, we can define
formulas in the following form:
```csharp
ExpressionUnificationService class. It's very simple, so we will not describe it here.
The main part of this technique, the resolution rule, is implemented as standard rule of this system:
```csharp
Rule
.New("Resolve", StdTags.Inductive, StdTags.Logic, StdTags.SafeResection)
.Select(A[ChildB], C[ChildD])
.WhereModificator method perfoms a unification on the two predicates and combine the remaining ones from the two clauses into a new clause.
To get list of possible resolvents of two predicates you must use the method ComputerAlgebra.Resolve like this:
```csharp
ExpressionResolutionDemo and in test class ResolutionTests