Overview of sygnm architecture
Leading computer algebra systems aim to provide a complete development environment to the user, complete with their own programming language and graphical user interface.
However, these development environments are limited when compared to the support, documentation and tooling which most general purpose programming languages posses. Portability and ease of integration with other software systems also suffers as a consequence. Users are forced to learn a new (and often proprietary) programming environment just to use the mathematical software.
Another problem is that currently there are very few libraries for mathematical symbolic manipulation which are designed to be called from other software and do not force the use of an interactive interface.
sygnm is an attempt at solving these problems.
The aim of sygnm is to solve problems which are considered "traditionally" as mathematical, and to implement functions, algorithms and data structures which are needed in order to attain this goal. sygnm is not a general purpose programming environment. It was not designed for file manipulation, web services, video processing and other not strictly mathematical tasks.
The two main ways to use sygnm is an interactive "calculator" mode and as a library from some general purpose programming language. Interactive mode is designed for prototyping and mathematical exploration. The user can access sygnm functionality through multiple (graphical or command line) interfaces. The user inputs mathematical expressions in a simplified language which are then evaluated. User defined functions and some control structures are supported, however this is not a complete programming environment and should not be used as such (e.g. there are no way to write to arbitrary files, communicate over the network, or to import code from other files). The other way is using sygnm as a mathematical library from a general purpose programming language (e.g. C++ or Python). In this mode of operation the user writes programs in the usual way, and calls into the sygnm framework when advanced mathematical algorithms are needed. There is no need to run sygnm as a separate process in this mode, it can be used as a traditional library. In both modes of operation the full functionality of the sygnm framework is available to the user.
The main components of the sygnm framework are: the core, the mathematical packages and the user interfaces. These components can be compiled separately. Mathematical packages can be loaded selectively at runtime, however it is also possible to compile them and the core into a single file to make shipping sygnm as a library easier.
All mathematical functionality, even the most basic functions and data structures are implemented in packages. The implementation language is (a subset of) C++, however package contents (functions, data types, etc.) are defined in simple package description files, from which a code generator automatically produces C++ files and Python bindings. To implement new sygnm functions, the user only needs to fill out the stubs produced by the code generator.
sygnm also features a unique I/O architecture. It can communicate through various low-level I/O interfaces (e.g. using stdin/stdout or listening on a network interface). It can use different parsers and renderers to interpret input and display results. I/O interfaces, parsers and renderers can be loaded from packages and selected at runtime. If sygnm is used as a library, it is still possible but not necessary to use this I/O system, since mathematical expressions can also be built and evaluated directly.
sygnm is open source, free software. Closed source software, besides being ethically questionable, is not suitable for mathematical research, since there is no way for users to examine the algorithms used, to make sure about the correctness of results, to fix bugs in the source code or customize it. With sygnm, the user is in complete control of the software: they can examine, modify and redistribute the source code (according to the terms of the AGPLv3+ license). sygnm does not depend on any network services or remote components: the user can install sygnm on their computer in its entirety.
sygnm is built on top of many other open source software and libraries. When selecting dependencies, care is taken to only depend on mature, portable and generally high quality software.
Performance is important, however it is not the primary consideration: functionality, simplicity, ease-of-use and portability are also important. sygnm is a general purpose system with a wide range of functionality, thus it will never be as fast specialized, hand-written, low-level code. sygnm should offer performance comparable to other general purpose systems.
Computations in the sygnm framework are not interactive by default. If there is insufficient information to complete the computation or unrecoverable errors occur, computation is stopped until further user input. All errors are reported, except if error reporting is explicitly disabled. If a result is only correct with further assumptions, these assumptions should always be communicated to the user. Users errors should never cause the termination of the sygnm system. Undefined behavior should be avoided. When used as a library, errors in sygnm should not cause the termination of the host software. Mathematical errors (incorrect results) are the most serious type of errors, they should be avoided at all costs.
The definition of mathematical data types should follow the mathematical constructions where possible; however the realities of computer programming should be taken into account. Many times it is not possible to both strictly follow the mathematical construction and achieve good performance. In these cases performance is preferred.
sygnm implements a dynamic runtime type system with parametric polymorphism based on typeclasses and generic functions. New types can be added or constructed at runtime. Function overloading is also resolved at runtime. However, this type system is optional. If sygnm is used as a library, it is possible to get around the type system and directly call function implementations if the argument types are known; this way any performance overhead can be avoided at the cost of having to know types at compile time. For more information, see Objects, types and function overloading and Expression trees and evaluation.
Parallelization is the task of package creators, however the management of parallelization resources (thread count settings, OpenCL settings, etc.) are the task of the sygnm core system. Packages should use the central parallelization management.
Assumptions about the user of the sygnm framework:
- The user knows the necessary mathematical concepts
- The user has basic computer skills
- The user who creates packages has basic programming skills
sygnm core never creates network connections. sygnm does not collect, store, process or transmit any data about the system it runs on, the hardware environment, user habits, errors or any other external information. There is no telemetry of any kind in the sygnm system.
The core system and I/O architecture
The main parts of sygnm core:
- Initialization and deinitialization, loading objects from packages
- Handling of configuration and parallelization resources
- Runtime "type system", runtime resolution of overloaded functions
- Expression tree evaluation
- Expression tree rewriting
- Miscellaneous utilites
All other functionality is implemented in packages (see Packages) and user interfaces.
In interactive mode of operation, I/O in sygnm works like this:
- Initialize sygnm core and load packages
- Start the I/O interface specified in the configuration
- Receive user input
- Parse user input into a sygnm expression tree using the parser specified in the configuration
- Evaluate the expression tree
- Render the result using the renderer specified in the configuration
- Send the output to the user
- Deinitialize and shut down when the user is finished
An I/O interface is an object which is responsible for all communication with the "outside world". It is possible to write I/O interfaces which read input from the command line, from files or from the network, etc.
Parsers are objects which receive user input as text and create an expression tree from it. The used parser essentially determines the language which sygnm uses to communicate with its users. This means that even in interactive operation, sygnm does not have a single language - it can use any available parser (although there is a default parser which is suitable for most use cases). Similarly, renderers are objects which receive an expression tree and render it into an output format (not necessarily text). Although sometimes parsers and renderers come in pairs, they do not depend on each other so any parser can be used with any renderer.
Since I/O interfaces, parsers and renderers implement standard interfaces, they can be combined freely which gives the sygnm I/O architecture its power and flexibility.
I/O interfaces, parsers and renderers are all loaded from packages, which makes it is easy to create and use new ones.