This code is a work in progress
Welcome to FunDB - a fast, lightweight, and extensible on-disk database for storing and retrieving symbolic functions.
FunDB is a unique database built in C++ that distinguishes itself by storing mathematical functions rather than discrete data points. Using the powerful SymEngine library for symbolic manipulation, it allows you to save and load complex expressions and evaluate them at runtime.
The core of FunDB is a persistent on-disk hash table, which provides extremely fast lookups by function name. This makes it ideal for applications that require quick, symbolic function retrieval without the overhead of a traditional database.
- Symbolic Storage: Stores mathematical expressions as strings, which can be re-evaluated on the fly.
- High Performance: Uses an efficient, custom hash table for fast lookups.
- Small Footprint: A lightweight solution built on a simple file-based architecture.
- C++ Powered: Built with modern C++ standards for performance and reliability.
- Extensible: Easily adaptable for a wide range of symbolic-driven applications.
inc/: Contains all public header files, includingfun.h(for the Function class) anddb.h(for the Database class).src/: Contains the C++ source code files.main.cppdemonstrates the usage of the database, whilefun.cppanddb.cppcontain the implementations for the Function and Database classes, respectively.CMakeLists.txt: The CMake build configuration file.conanfile.txt: Dependencies to be installed using theconanpackage manager.
FunDB stores data in two separate files: a data file (.dat) and an index file (.idx).
- Data File: This is a simple append-only file that stores the serialized function data, including the function's name, symbols, and the expression itself as a string compatible by SymEngine.
- Index File: This file acts as a persistent hash table for fast lookups. The index uses a hash of the function's name to find the byte offset of the corresponding function in the data file. To handle hash collisions, it employs linear probing.
This design allows for fast key-value lookups while keeping the data storage simple and efficient for symbolic functions.
Here is a simple example of how to use the FunDB::Database class in your own c++ code to save and load a function.
#include <fundb/fun.h>
#include <fundb/db.h>
#include <iostream>
#include <unordered_map>
#include <symengine/expression.h>
#include <symengine/symbol.h>
int main() {
FunDB::Database db{};
db.clear(); // Start with a clean database
// Create a new function
SymEngine::Expression expr = SymEngine::symbol("x") * 2 + SymEngine::symbol("y") * 3;
FunDB::Function my_func{"linear_fn", {"x", "y"}, expr};
// Save the function to the database
db.save_function(my_func);
// Look up and evaluate the stored function
std::unordered_map<std::string, double> values = {{"x", 10.0}, {"y", 5.0}};
float result = FunDB::evaluate_stored_function(db, "linear_fn", values);
std::cout << "Evaluation result: " << result << std::endl; // Expected output: 35
return 0;
}To build the project and run the main.cpp example, you will use Conan for dependency management and CMake for the build system.
First, ensure you have Conan and CMake installed. Then, follow these steps:
conan install . --output-folder=build --build=missing
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build .
./my_appThe above will also create a server executable in the build/ dir. Execute the server from the build directory. It will start listening for requests on port 6374.
./my_app_serverYou should see a message in the console indicating that the server is listening on port 6374 (by default).
You can now use curl or any other HTTP client to interact with the server's API endpoints.
Store a new function: Send a POST request to the /store endpoint with a JSON payload containing the function's name, expression, and a list of symbols.
curl -X POST -H "Content-Type: application/json" -d '{"name": "linear_func", "symbols": ["x", "y"], "expression": "2*x + 3*y"}' http://localhost:6374/storeLoad a function: Send a GET request to the /load/ endpoint, where is the function's name.
curl http://localhost:6374/load/linear_funcEvaluate a function: Send a POST request to the /evaluate endpoint with the function's name and a JSON object of values for its symbols.
curl -X POST -H "Content-Type: application/json" -d '{"name": "linear_func", "values": {"x": 10, "y": 5}}' http://localhost:6374/evaluate