Skip to content
This repository has been archived by the owner on Mar 26, 2019. It is now read-only.

Bug fix #1

Open
wants to merge 162 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
162 commits
Select commit Hold shift + click to select a range
844083f
Initialize clock_eval
CerielJacobs Mar 12, 2019
c548a2d
Bug fix: modified set while an iterator was working on it
CerielJacobs Mar 12, 2019
478cd0b
modified benchmark code
Mar 15, 2019
10e5df1
Merge branch 'master' of github.com:karmaresearch/laser-plus-plus
Mar 15, 2019
d3c5177
integrated restricted ordered chase algorithm into program evaluation
Apr 4, 2019
cbca036
extended rule parser syntax to support rules that have an existential…
Apr 5, 2019
88371a7
Initial working version of Existential quantifier
Apr 9, 2019
2a0edbb
proper implementation of restrictive chase
Apr 9, 2019
5cf7537
Existential formula supports Time Reference as child. Testcases for E…
Apr 11, 2019
808804b
more testcases
Apr 16, 2019
bcf1ffd
fixed bug in GroundingTable
Apr 16, 2019
9c32f87
Existential formulas now support conjunctions in the head of the rule
Apr 17, 2019
cf81643
added testcase for existential based on the example in the paper
Apr 18, 2019
400e32b
before spliting chase algorithms
Apr 23, 2019
c00e04c
skolem chase
Apr 23, 2019
5f1e044
work on restricted chase implementation
Apr 24, 2019
14b138f
restricted chase implementation
Apr 25, 2019
431a585
fixed bug in restrictive chase. more minor changes. work in progress
Apr 26, 2019
68dd1af
Refactoring Rule for better performance and design. Work in progress
Apr 26, 2019
c869144
Rule refactoring complete. Oblivious Chase added
Apr 29, 2019
0fc36c8
Rule can identify bound variables.
Apr 29, 2019
fc6ab09
new Skolem Chase implementation
Apr 29, 2019
8f0e802
new Restricted Chase implementation. Failing some tests a.t.m
Apr 29, 2019
621c5dd
Fixed restricted chase
Apr 29, 2019
01792b6
cleanup old existential formula classes
Apr 29, 2019
fabfeab
added Settings class used for selecting chase algorithm
Apr 30, 2019
3d2721c
fixed tests
Apr 30, 2019
cee957b
added command line argument for setting chase algorithm to SimpleApp …
Apr 30, 2019
dde79d1
Fixed simple app
Apr 30, 2019
b053f15
before second tier SNE implementation
May 3, 2019
a4d1f34
second tier SNE
May 3, 2019
f1fb76e
removed hashes from skolem_filter.cpp.
May 4, 2019
e791f2a
README -> updated instructions on using Laser++
May 4, 2019
63adec7
added benchmark.txt
May 4, 2019
c31aa60
eliminated hashes from box. Benchmark results added
May 6, 2019
13e484b
Box optimization and benchmark
May 6, 2019
886d58a
cleaun in Grounding class
May 27, 2019
e4721c6
indexed restricted chase - implementation and benchmark results
May 29, 2019
413b906
tweaks and benchmarks
May 31, 2019
e7b3603
fixed bug: the benchmark application was not writing any output to files
May 31, 2019
54a5c51
fixed conjunction out of memory bug
May 31, 2019
d34ab09
clean-up
May 31, 2019
d054426
fixed tests failing because conjunction evaluation result vector was …
Jun 3, 2019
7ed4178
benchmarks
Jun 3, 2019
25a90ee
conjunction using std::accumulate when computing hashes
Jun 4, 2019
e5870c6
.
Jun 4, 2019
724599c
chnaged scripts to reduce build times
Jun 4, 2019
955a11b
for benchmarking
Jun 5, 2019
c2b1588
more benchmarks and optimizations in Indexed Filter
Jun 6, 2019
83e788b
more benchmarking
Jun 6, 2019
e2720aa
benchmarks
Jun 17, 2019
47e8f1b
work in progress - query answering
Jun 21, 2019
287ebce
working prototype of query answering for simple atomic queries
Jun 24, 2019
c4abc7e
restructuring
Jun 24, 2019
bd7f3e3
fixed laser hanging on query requests
Jun 24, 2019
09ef165
demo application: initial commit
Jun 24, 2019
51dfab5
Removed benchmarking and demo applications. Added tests back to Laser…
Jul 24, 2019
a0a80f8
performance improvements - Rule::make_atom_fact
Aug 5, 2019
ba41bcc
performance improvements - Rule::make_atom_fact
Aug 5, 2019
c223475
minor performance tweaks
Aug 5, 2019
223542b
re-organised project to accomodate for acyclicity conditions
Aug 6, 2019
1d4a1a1
fixed bug in Rule copy constructor
Aug 7, 2019
e4596d1
updated Readme.md
Aug 7, 2019
3a5012a
work on smfa - computing critical instance
Aug 7, 2019
87cfb8d
compute critical timeline
Aug 8, 2019
d82111b
fix skolem chase: paramenters of skolem functions are now limited to …
Aug 8, 2019
65350fa
naive SMFA implementation
Aug 12, 2019
425105a
fixed NaiveSMFA bugs
Aug 12, 2019
d2fdd33
acyclicity testcases
Aug 12, 2019
5c9442c
implemented event-based inertia operator support. Added testcases. Fi…
Aug 14, 2019
57ebac5
some work on math atoms
Aug 16, 2019
03c37d7
some work on math atoms - fix
Aug 16, 2019
e120a05
restricted chase inertia operator - work in progress
Aug 19, 2019
114f8b1
restricted chase inertia operator - work in progress
Aug 19, 2019
ad31b03
restricted chase inertia operator - done
Aug 19, 2019
4fea440
changed evaluation steps - step incremented after all rules are fired…
Aug 20, 2019
9082aff
changed a testcase
Aug 21, 2019
7641125
changed a testcase
Aug 21, 2019
6348841
changed a testcase
Aug 21, 2019
9525e0e
added testcase
Aug 21, 2019
d5d6ba6
fixed restricted chase + testcases
Aug 22, 2019
f5572f4
fix cmake for DAS-5
Aug 23, 2019
1495b59
fix cmake for DAS-5
Aug 23, 2019
7b5c61a
fix cmake for DAS-5
Aug 29, 2019
051a81c
diamond only considers facts in the datastream
Aug 30, 2019
dd919b3
fixed bugs from testcases
Aug 30, 2019
df96228
Revert "fixed bugs from testcases"
Sep 2, 2019
2d06bcb
Revert "diamond only considers facts in the datastream"
Sep 2, 2019
a4ae37e
fix in script for DAS-5
Sep 2, 2019
b27988e
fix script for DAS-5
Sep 2, 2019
ae0b4fd
fix in script for DAS-5
Sep 2, 2019
4adb0af
grounding deep and shallow clones
Sep 3, 2019
2bbeb87
fix bug in restricted chase
Sep 3, 2019
3780176
labeled nulls use global counter
Sep 4, 2019
41463b6
merging diamond groundings
Sep 4, 2019
5c4916c
improved mergin in diamond
Sep 4, 2019
8e1264e
Revert "improved mergin in diamond"
Sep 4, 2019
478f248
Revert "merging diamond groundings"
Sep 4, 2019
936f171
io manager
Oct 15, 2019
90fca41
refoactoring raw pointers. work in progress, won't compile
Nov 14, 2019
4ec3aea
removed all extended formulas to make refactoring and debugging easy.…
Nov 14, 2019
b8f07b4
more refactoring. work in progress, won't compile
Nov 14, 2019
2e43c3c
removed all chase filters except oblivious chase. Will add them back …
Nov 14, 2019
7b8643e
removed module Service. Will add it back after refactoring
Nov 14, 2019
49b6ac6
removed module Acyclicity. Will add it back after refactoring
Nov 14, 2019
4c1876d
fixed memory management in Atom and Formula
Nov 19, 2019
3a12e9d
memory management fixes
Nov 19, 2019
8fd1799
fixed conjunction and chase
Nov 22, 2019
be34e8b
added back acyclicity
Nov 25, 2019
0a71920
added back service module
Nov 25, 2019
39e1c7e
added back formulas and tests. Passes all tests. No leaks are possible.
Nov 26, 2019
da3cac0
fixed bug in parser
Nov 26, 2019
96827ca
fixed bug where time reference would not return values from the past
Nov 27, 2019
6fc4665
work
Dec 7, 2019
c839531
reasoner no longer measures evaluation time
Jan 3, 2020
583803c
fixed bug in conjunction, added testcase
Jan 12, 2020
69a8652
fixed bug in restricted chase
Jan 14, 2020
e018826
using map find instead of count for performance
Jan 16, 2020
59a3207
performance improvements to conjunction
Jan 16, 2020
3bd949a
printing count conclusions
Jan 17, 2020
2e33885
fixed budy waiting on output thread. Changed labeled null string cons…
Jan 17, 2020
3261fad
work on new restricted implementation
Jan 18, 2020
8a29060
more work on new restricted chase
Jan 18, 2020
2db7d05
more work on restricted chase
Jan 18, 2020
9aad4ef
more work on restricted chase
Jan 19, 2020
7262d6a
more work on restricted chase
Jan 19, 2020
482fbc3
restricted chase
Jan 19, 2020
209b6e0
printing stats
Jan 19, 2020
9ed098f
added Threads library back
Jan 19, 2020
d98d6ea
fixed restricted chase bug not re-using facts derived by other rules …
Jan 19, 2020
97c9208
restricted filter was not actually filtering anything
Jan 20, 2020
0282e20
fix adding too many facts to database
Jan 20, 2020
3223d56
removed debug statements
Jan 20, 2020
c4bf54f
computing runtimes for each time ponit
Jan 20, 2020
ebcb7b5
merge
Jan 20, 2020
507c143
some fixes
Jan 30, 2020
8c430b2
some refactoring
Jan 31, 2020
6c28f60
checkpoint
Feb 1, 2020
f366290
work on formulas
Feb 1, 2020
ef33703
work on changing GT to distinguish between old and new facts
Feb 3, 2020
87e7172
Revert "work on changing GT to distinguish between old and new facts"
Feb 3, 2020
23ecc91
Revert "work on formulas"
Feb 3, 2020
3823af8
diamond grounding table update
Feb 3, 2020
8c30c1c
refactoring to allow for math atoms
Feb 5, 2020
03b0109
rule built with list of atoms
Feb 5, 2020
7b6bdaa
Revert "rule built with list of atoms"
Feb 5, 2020
595c4e9
Revert "refactoring to allow for math atoms"
Feb 5, 2020
061b85b
minor fix
Feb 5, 2020
0fa1d1f
implemented math - assignment atom
Feb 5, 2020
46bba06
math - work in progress
Feb 7, 2020
9cc99b2
math - work in progress
Feb 7, 2020
ee41a9c
Merge branch 'master' of github.com:karmaresearch/laser-plus-plus
Feb 7, 2020
721b26b
math atom
Feb 8, 2020
14bd11b
working math assignment
Feb 8, 2020
110fdd1
work on math - algebra atom
Feb 9, 2020
42a844e
fixes for algebra
Feb 10, 2020
aececb8
algebra values are represented as integers instead of doubles
Feb 11, 2020
d57da6d
implementation of condition atoms
Feb 11, 2020
9beaf7d
conditions suport for string values
Feb 11, 2020
4a93200
reasoner counts conclusions
Feb 19, 2020
5354c53
string pool for grounding
Feb 20, 2020
b37839c
Revert "string pool for grounding"
Feb 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 15 additions & 19 deletions .projections.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,18 @@
"type": "laser-example-header",
"alternate": "src/example/{}.cpp"
},
"include/service/*.h": {
"type": "laser-service-header",
"alternate": "src/service/{}.cpp"
},
"include/rule/*.h": {
"type": "laser-rule-header",
"alternate": "src/rule/{}.cpp"
},
"include/acyclicity/*.h": {
"type": "laser-acyclicity-header",
"alternate": "src/acyclicity/{}.cpp"
},



Expand All @@ -46,29 +54,17 @@
"type": "laser-example-source",
"alternate": "include/example/{}.h"
},
"src/service/*.cpp": {
"type": "laser-service-source",
"alternate": "include/service/{}.h"
},
"src/rule/*.cpp": {
"type": "laser-rule-source",
"alternate": "include/rule/{}.h"
},



"app_bench/include/*.h": {
"type": "benchapp-header",
"alternate": "app_bench/src/{}.cpp"
},
"app_bench/src/*.cpp": {
"type": "benchapp-source",
"alternate": "app_bench/include/{}.h"
},

"app_simple/include/*.h": {
"type": "simpleapp-header",
"alternate": "app_simple/src/{}.cpp"
},
"app_simple/src/*.cpp": {
"type": "simpleapp-source",
"alternate": "app_simple/include/{}.h"
"src/acyclicity/*.cpp": {
"type": "laser-acyclicity-source",
"alternate": "include/acyclicity/{}.h"
},

}
53 changes: 16 additions & 37 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,68 +1,47 @@
cmake_minimum_required(VERSION 3.7)

# comment out the following 2 lines to use system's default C/C++ compiler
# comment out the following lines to use system's default C/C++ compiler
# set(CMAKE_C_COMPILER "clang")
# set(CMAKE_CXX_COMPILER "clang++")
# set(CMAKE_C_COMPILER "gcc")
# set(CMAKE_CXX_COMPILER "g++")

project(LaserPP VERSION 0.0.1 LANGUAGES CXX)
project(Laser++ VERSION 0.1.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set( CMAKE_EXPORT_COMPILE_COMMANDS ON )
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

################################### LASER ###################################
include_directories(include/)
include_directories(~/tools/llvm/include/c++/v1/)

file(GLOB LASER_SOURCES
"src/formula/*.cpp"
"src/formula/extended/*.cpp"
"src/util/*.cpp"
"src/rule/*.cpp"
"src/rule/filter/*.cpp"
"src/rule/math/*.cpp"
"src/rule/math/evaluator/*.cpp"
"src/core/*.cpp"
"src/example/*.cpp"
"src/service/*.cpp"
"src/acyclicity/*.cpp"
)

find_package(Threads)

################################## TESTAPP ##################################
include_directories(test/include/)
file(GLOB TESTAPP_SOURCES
"test/src/*.cpp"
)

set(TESTAPP_LASER_SOURCES ${LASER_SOURCES} ${TESTAPP_SOURCES})
add_executable(testapp test/main.cpp ${TESTAPP_LASER_SOURCES})
################################## TESTAPP ##################################
add_executable(testapp test/main.cpp ${LASER_SOURCES})
target_link_libraries(testapp ${CMAKE_THREAD_LIBS_INIT})

################################## BENCHAPP ##################################
include_directories(app_bench/include/)
file(GLOB BENCHAPP_SOURCES
"app_bench/src/*.cpp"
)

set(BENCHAPP_LASER_SOURCES ${LASER_SOURCES} ${BENCHAPP_SOURCES})
add_executable(benchapp app_bench/main.cpp ${BENCHAPP_LASER_SOURCES})
target_link_libraries(benchapp ${CMAKE_THREAD_LIBS_INIT})

################################## SIMPLEAPP ##################################
include_directories(app_simple/include/)
file(GLOB SIMPLEAPP_SOURCES
"app_simple/src/*.cpp"
)

set(SIMPLEAPP_LASER_SOURCES ${LASER_SOURCES} ${SIMPLEAPP_SOURCES})
add_executable(simpleapp app_simple/main.cpp ${SIMPLEAPP_LASER_SOURCES})
target_link_libraries(simpleapp ${CMAKE_THREAD_LIBS_INIT})

################################### TESTS ###################################

find_package(GTest)
if(GTEST_FOUND)
file(GLOB TEST_SOURCES
"test/src/*.cpp"
"test/testcase/*.cpp"
)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(run_test test/test.cpp ${LASER_SOURCES} ${TEST_SOURCES})
target_link_libraries(run_test ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
add_executable(run_gtest test/test.cpp ${LASER_SOURCES} ${TEST_SOURCES})
target_link_libraries(run_gtest ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
endif(GTEST_FOUND)


172 changes: 76 additions & 96 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,21 @@
**Laser++** is a C++ implementation of the [Laser](https://research.vu.nl/en/publications/expressive-stream-reasoning-with-laser) a stream reasoning engine
based on the [LARS logic framework](http://www.kr.tuwien.ac.at/research/projects/dhsr/pub/2015/bdef2015-aaai.pdf)


### Prerequisites
Laser++ requires:
* C++ compiler compliant with C++17 standard (tested on GCC 7.3.0 and
Clang 6.0.0)
* GTest suite (tested on version 1.8.0)
* CMake (minimum version: 3.7, tested on 3.10)

Optional tools:
* gprof (for profiling)
* gdb (for debugging)
* python (for generating benchmark input)
* GTest suite (tested on version 1.8.0) (optional)
* gdb (optional)

## Getting Started

Interact with Laser++ by using the `laser.sh` script.

Build Laser++ by executing:
Build and test Laser++ by executing:
```
./laser.sh b
./laser.sh r
```

Run all test cases by executing:
Expand All @@ -35,35 +30,61 @@ See all options by running:
./laser.sh h
```

### Benchmarking
**Program**

Programs are composed of one or more rules, separated by new-line character '\n'.

Each rule is written as: `head := body`. Both *head* and *body* are formulas.

The simplest type of formula is an Atom, which is composed of a predicate and
some variables, e.g.: `a(X, Y, X)`. In this atom, *a* is the predicate, while
*X*, *Y*, and *Z* are variables.

Benchmarking requires an input file from which the stream will be read.
This file can be generated by using `gen.py` script:
More complex formulas can be represented by adding a unary operator in front
of another
formula, or a binary operator between two formulas.
These operators are written as:
```
python gen.py
Diamond: [D]
Box: [B]
Time Window: [$, size]
Tuple Window: [#, size]
Time reference: [@, time_variable]
Conjunction: &&
```

Benchmark by running:
Please note that the head of a Laser++ rule is limited to conjunctions of atomic
and time reference formulas.
Example program:
```
./laser.sh bench test_name end_time_of_stream number_of_facts_per_timepoint window_size stream_file_path [output_file_path]
u(X) := [#, 1][D]f(X)
f(Y) := [$, 5] [B] e(Y, Y)
a(T, Z) := [@, T] b(Z)
[@, T]c(S) := [@, T] d(S)
i(V, W) := g(W) && h(V)
```

The parameter test_name can be selected from this list:
[*atom*, *diamond*, *box*, *conjunction*, *tref*, *multiatom*, *multiall*,
*atom_window*].
For details on each test, see *app-bench/main.cpp*

The parameter *output_file_path* is optional. In case it is missing, no output
will be written.
**Input Stream**

Example use:
The file containing the input stream needs to start with a line containing two
numbers: the first and last time-point in the stream.
Each line after has the following format: `time-point : facts`. Facts are grounded
atoms separated by commas. Time-points should be in order.
Example input stream:
```
./laser.sh bench atom 1000000 100 0 ~/stream_file.txt
1 14
1 : q(1), p(1), e(a4, b6)
2 : p(2), a(3, 1, 8)
3 :
4 : p(41), q(1)
4 : p(8)
5 : a(4, 8, 12)
12 : a(56, 99, 0), p(1)
```

### Project organization
The code of Laser++ can be found in directories **include** (header files) and **src**
(C++ source files). The project is divided in 4 modules (*core*, *rule*, *forumula*,
The code of Laser++ can be found in directories **include** (header files) and
**src** (C++ source files).
The project is divided in 4 modules (*core*, *rule*, *forumula*,
*util*). Each module can be found in a dedicated sub-directory of *include*
and *src* respectively. The sub-directory *example* contains implementations of
*rule::RuleReader* and *core::IOManager* interfaces.
Expand All @@ -73,20 +94,15 @@ The directory **test** contains contains some test cases which can be found in
hardcoded programs on hard-coded input. The source-code of this application can
be found in *test/main.cpp*.

The directory **app-bench** contains a Laser++-based application. This
application is used for benchmarking the performance of the Laser++ reasoning
engine. It can also be used for profiling.

### Laser++ modules:
### Laser++ modules: (!outdated)

**Core** - handles input-output as well as execution of the Laser++ program.
References modules: Rule, Util.

**Rule** - parses laser programs and evaluates the rules on the input facts
provided by the stream. References modules: Formula, Util.
provided by the stream.

**Formula** - Evaluates the different formulas found in the program and stores
the result. References module Util.
the result.

**Util** - Contains classes useful in other modules such as exceptions, timeline.
Instances of the Grounding class present in this module are used as the basic
Expand All @@ -99,81 +115,45 @@ formulas present in the program being evaluated.
Laser++ is a reasoning engine that can be used to implement systems capable of
real-time semantic inference on stream of data.

In order to implement a reasoning application, the user need only to implement the
`laser::core::IOManager` and `laser::rule::RuleReader` interfaces found in
*include/core/io_manager.h* and *include/rule/rule_reader.h*. This
In order to implement a reasoning application, the user need only to implement
the
`laser::core::IOManager` interface found in
*include/core/io_manager.h*. This
implementation should reflect the application specific needs regarding reading
and parsing of the input stream, as well as formatting and writing of the output
stream. An example of such an implementation can be found in the folder
*include/example* and *src/example*.

Once the *IOManager* and *RuleReader* interfaces are implemented,
Laser comes with a built in *RuleParser* class found in the _rule_ module.
If the application requires a diferent syntax for expressing logic rules,
users can implement their own rule parser instead.

Once the *IOManager* interface is implemented,
an application can use the Laser++
reasoning engine by constructing an instance of the `laser::core::Reasoner` class
found in *include/core/reasoner.h* and *src/core/reasoner.cpp* respectively.
An example application can be found in *app-sample/main.cpp*

### Quick start with Sample reasoning application
Laser stores global settings in the `laser::util::Settings` class.
The class includes settings such as the chase algorithm used to materialize
existentially quantified values.
This settings should be set before parsing the rules and intantiating the
_Reasoner_ class.

The Laser++ source-code includes **Simpleapp**, a Laser++-based application that
is meant as a demo. It can be used to test the Laser++ reasoning
engine on programs and input streams provided in text files. To run this
application first compile Laser++ as well as simpleapp by running `./laser.sh b`,
then execute:
```
cmake-build-release/simpleapp PROGRAM INPUT OUTPUT
```
The three arguments represent the paths to the respective input and output files.
The source code of *Simpleapp* can be found in *app-simple/main.cpp*, as well as
the sub directories *include* and *src* of the *app-simple* directory. Some
sample programs and inputs can be found in *app-simple/samples/*.

**Program**

Programs are composed of one or more rules, separated by new-line character '\n'.
### TODO: example!!!

Each rule is written as: `head := body`. Both *head* and *body* are formulas.

The simplest type of formula is an Atom, which is composed of a predicate and
some variables, e.g.: `a(X, Y, X)`. In this atom, *a* is the predicate, while
*X*, *Y*, and *Z* are variables.
### Debuging

More complex formulas can be represented by adding a unary operator in front of another
formula, or a binary operator between two formulas. The result is an extended
formula. These operators are written as:
Laser++ comes with a testing application.
The source code for this application can be found in the directory
*test/* and can be executed by running:
```
Diamond: [D]
Box: [B]
Time Window: [$, size]
Tuple Window: [#, size]
Time reference: [@, time_variable]
Conjunction: &&
```
Please note that the head of a Laser++ rule is limited to only atomic and time
reference formulas.
Example program:
```
u(X) := [#, 1][D]f(X)
f(Y) := [$, 5] [B] e(Y, Y)
a(T, Z) := [@, T] b(Z)
[@, T]c(S) := [@, T] d(S)
i(V, W) := g(W) && h(V)
./laser.sh r
```

**Input Stream**

The file containing the input stream needs to start with a line containing two
numbers: the first and last time-point in the stream.
Each line after has the following format: `time-point : facts`. Facts are grounded
atoms separated by commas. Time-points should be in order.
Example input stream:
```1 14 "
1 : q(1), p(1), e(a4, b6)
2 : p(2), a(3, 1, 8)
3 :
4 : p(41), q(1)
4 : p(8)
5 : a(4, 8, 12)
12 : a(56, 99, 0), p(1)
The test application runs a series of hardcoded Laser programs on hardcoded input.
This is useful for debuging, as a specific Laser program can be run in GDB.
Simply edit the code in *test/main.cpp*, build and execute:
```
./laser.sh d
```

Loading