csb6 / Backtrack

A C++17 library with Prolog-like functionality (Work-In-Progress)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Backtrack

Backtrack is a single-header C++ library intended to serve as a rules engine along the lines of Prolog. Currently, facts and rules similar to those in Prolog can be defined, as well as queries without variables, but support for backtracking and queries such as predicate(X,5) are not yet supported.

I see the irony of naming a library backtrack without supporting backtracking, but my intention is to eventually support it in a way similar to Prolog. For now, think of the name as me backtracking on the implication that this library supports backtracking!

Installation

The only file you need is backtrack.hpp. Simply #include it into any source/header file.

This library is written in C++17.

Usage

Creating a database

The main class is Database. You can create as many databases as you like, but typically using just one is most useful so that knowledge stays centralized. Here is a possible instantiation of a database:

	#include "backtrack.hpp"

	Database<const char*, int, float> db;

The first parameterized type, N, is the type used to represent the names of the facts and rules. Strings work great for creating names quickly, but using an enum class called FactName or something similar is recommended to minimize memory usage and reduce the range of possible fact/rule names.

The last two parameterized types represent the possible types, A and B, of any arguments used in facts and rules.

Note: While A and B cannot be the same type, and A and B must be a different type than N. This enforces a clear separation between what is a fact/rule name and what is an argument.

Facts and rules can have as many overloads as you like, just like in Prolog you can have nameA(A)., nameA(A,B)., and name(5,6). all in the same database. However, all facts and rules must have at least 1 argument, meaning that you can not define an zero-argument rule like nameA. in Prolog. Since C++ supports constants and enums, it should be possible to make a nameA constant or enum for the same purpose as it would be used in Prolog.

Adding facts to the database

Facts are added by calling a member function on your database instance. The following code adds two facts equivalent to P(8,6) and Y(5) in Prolog.

	db.add("P", new Fact<int,float>(8, 6.0));
	db.add("Y", new Fact<int,float>(5.0));

The first argument is the name of the fact, and it must be the same type as the N type specified in the Database's constructor. The second argument is a Fact object, which must be parameterized with the same <A,B> as the A and B used in the Database constructor.

The arguments given to a Fact will be evaluated when added and will added immediately to the database, so be sure that the arguments fed to the constructor are the values you would like the Fact to use. You can specify as many arguments as like, as long as they are all of type A or B.

Additionally, type-checking is enforced through use of templates, so the compiler will let you know if you use arguments of types other than A or B.

Querying the database

As seen in the last example, the () operator overload, db(), can query the database with a given request, and the database will indicate if the query is true or false based on its current knowledge. Here is an example of a simple query, equivalent to the Prolog query ?- isPositive(1):

	db("isPositive", 1);

The first argument is the name of the rule/fact to look for; the second argument is the first argument passed to the rule/fact. This function would return true if there was some fact or rule named "isPositive" that evaluated to true given an input of 1.

I hope you find the library useful and/or interesting!

About

A C++17 library with Prolog-like functionality (Work-In-Progress)

License:GNU General Public License v3.0


Languages

Language:C++ 99.9%Language:Shell 0.1%