Overview

As it was mentioned earlier, this implementation is built as a shared library (nars.dll on Windows, libnars.so on Linux/Android, and libnars.dylib on OSX) and it is written entirely in C++. The client application can be written in any language that can bind C-style library interface. The library provides a very simple interface with just four API functions. Two of them is used for creating and destroying an instance of a Nars class and the rest two function provides input an output to the system. As a language for the communication with the system as well for internal representation, the Narsese language is used.

Getting started

The binaries of the library is available on the Download section of this website. It is important to choose the right version for your platform.

Let's try this simple example in Narsese, which demonstrate the deduction inference rule:

1
2
3
4
5

// deduction


(M P).

(S M).

(S P)?

Open any text editor, create a new file and set encoding to UTF-8 without BOM. Then copy and paste this example and save it as "test.nars".

Sample code in C++

The following program reads Narsese code from the input file and print the result to the standard output.

#include "narsi.h"
#include <fstream>
#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>
#include <string>

using namespace std;

// Test class to try the Nars library interface
class Test {
	Nars* nars; // instance of the system
	atomic<bool> done;
	std::thread listenerThread;

protected:

	// process output in a separate thread
	void listener() {
		const size_t size = 15000; // max size of buffer
		char buffer[size];         // output buffer

		// listen to the system, and print out available outputs
		while (!done) {
			buffer[0] = 0;
			size_t _size = size;

			// wait, till answer is available
			if (::get(nars, buffer, _size, true, -1, 0)) {
                if (buffer[0] == '<' && buffer[1] == 't') {
                    uint32_t time = *(uint32_t*)&buffer[3];
                    uint32_t cycles = *(uint32_t*)&buffer[3 + sizeof(uint32_t)];
                    cout << "// Elapsed time: " << to_string(time) << " μs, cycles: " << to_string(cycles) << ".\n";
                }
				else if (buffer[0] == '<' && buffer[1] == 'e') {
					cout << &buffer[12];
				}
				else if (buffer[0] == '<' && buffer[1] == 'q') {
					cout << &buffer[3];
				}
				else if (buffer[0] != '<') {
					cout << buffer << endl; // print output
				}
			}
		}
	}
public:
	Test() : done(false) {

		// create an instance of the system (class Nars) with n processing channel and
		// m threads (for inference engine)
		nars = ::create_object(1, 1);

		// start listening for outputs of the system
		listenerThread = thread(&Test::listener, this);
	}

	~Test() {
		done = true;           // stop listener loop
		// destroy instance of the Nars, if still listening unblock and release resources
		::destroy_object(nars);
		listenerThread.join(); // wait to listener thread to finish
	}

	// process Narsese sentences on channel 0
	void process(unique_ptr<char []> sentence, unsigned int lineNumber) { ::process(nars, sentence.get(), lineNumber, 0); }
};

int main(int argc, char** argv)
{
	/*
	// example of a Narsese input
	// must be encoded in UTF-8, every sentence must be separated by a new line and input must terminate with a '\0'
	const char* input = "// deduction \n"
	"(M → P).\n"
	"(S → M).\n"
	"(S → P)?\n";
	Test test;              // test class with the system
	test.process(input, 1); // process input, line numbering strats with 1 (for reporting syntax errors)

	getchar();

	return 0;
	*/

	if (argc != 2) {
		cout << "Error: Wrong numbers of arguments.\n";
		cout << "Usage: nars.exe input_file.nars\n";
		return -1;
	}

	// location of the input Narsese file as an argument
	// must be encoded in UTF-8, every sentence must be separated by a new line
	ifstream in(argv[1]);
	if (in) { // opening file success

		// get length of file:
		in.seekg(0, ios::end);
		unsigned int length = (unsigned int) in.tellg();
		in.seekg(0, ios::beg);

		auto data = make_unique<char []>(length + 1);  // allocate input buffer
		in.read(data.get(), length);				   // read the input from the file
		data[in.gcount()] = 0;						   // null termination - important !!!!

		Test test;									   // test class with an instance of NARS
		test.process(move(data), 1);				   // process input, line numbering starts with 1 (for reporting syntax errors)

		in.close();									   // close input file

		cout << "\nTo quit press any key...\n\n";
		getchar();

		return 0;
	}

	cout << "Error: file \'" << argv[1] << "\' could'n be openned.\n"; 
	return -2;
}

After compiling this C++ code, run it from the command line:


The output should be:

1
2

// Elapsed time: 74 μs, cycles: 1.

(S P). <1.00, 0.81>

Reference material

This is the printout of the narsi.h header file showing all details needed to build your own client program:

#include "stddef.h"

#if defined WIN32 && defined DLL
    #ifdef NARS_EXPORTS
        #define NARS_API __declspec(dllexport)
    #else
        #define NARS_API __declspec(dllimport)
    #endif
#elif defined  __GNUC__ >= 4 && defined DLL
        #define NARS_API __attribute__ ((visibility ("default")))
        //#define NARS_API_LOCAL __attribute__ ((visibility ("hidden")))
#else
    #define NARS_API // default - empty, for a standalone application
#endif

class Nars;

extern "C" {
	// create Nars object
	NARS_API Nars* create_object(unsigned int numOfChannel, unsigned int numOfThreads); 

	// destroy nars object
	NARS_API void destroy_object(Nars* object); 

	// process NAL sentences
	NARS_API void process(Nars* object, const char* sentence, unsigned int lineNumber, unsigned int channel); 

	// get answer if available (or wait for it)
	NARS_API bool get(Nars* object, char* buffer, size_t& size, bool wait, int timeout, unsigned int channel); 
}

#endif

Syntax:

NARS_API Nars* create_object(unsigned int numOfChannel, unsigned int numOfThreads);

Description:

Creates a new Nars object, which represents the (NARS) system itself.

Parameters:

  • numOfChannel - number of independent processing channels. Channels share the same memory (knowledge base of NARS), but all stages of processing are run in parallel.
  • numOfThreads - number of threads for inference engine per channel.

Syntax:

NARS_API void destroy_object(Nars* object);

Description:

This function cleans up the memory and releases all resources used by Nars object.

Parameters:

  • object - pointer to the instance of the Nars class returned by create_object function.

Syntax:

NARS_API void process(Nars* object, const char* sentence, unsigned int lineNumber, unsigned int channel);

Description:

Process Nal sentences in Narsese encoded by UTF-8 character set. This is an input to the NARS system.

Parameters:

  • object - instance of the Nars class representing the system itself.
  • sentence - an input buffer containing one or more sentences in Narsese separated by a new line and encoded in UTF-8 to be processed by the system.
  • lineNumber - this is only important while debugging. The system can report syntax errors on the output, this number refers to the first sentence in a sentence buffer.
  • channel - the channel id, where sentences from the buffer should be proceed. Number of channel are defined by create_object

Syntax:

NARS_API bool get(Nars* object, char* buffer, size_t& size, bool wait, int timeout, unsigned int channel);

Description:

Get the output from the system in Narsese language encoded by UTF-8. This is the output from the system.

Parameters:

  • object - instance of the Nars class representing the system itself.
  • buffer - pointer to a buffer, where the results will be stored after a successful call.
  • size - the size of the input buffer buffer.
  • wait - signalize, if the operation should return immediately (false), or wait until some output is available.
  • timeout - time-out in milliseconds if parameter wait is set to true. Otherwise is not applicable.
  • channel - the channel id, from where the output is expected.

Return value:

If the call was successful, the return value is true, and buffer contain output from the system encoded in UTF-8 and terminated by '\0' - if it is a pure text and the parameter size contains the size of returned data.

Showcases

Background Image

Header Color

:

Content Color

: