The file decide.py
contains the code necessary to call your C DECIDE
function
from python code. I wrote this to try and facilitate easier fuzzing of my
team's DECIDE
implementation. If you have any questions about the setup
or usage feel free to ask on the forums. Also, I've tried to add at least
a little documentation to decide.py
so you can always try checking in
there as well.
Before I explain the interface in detail, I need to explain how to generate a
shared library containing your DECIDE
code. Luckily, it's pretty easy. When
you compile any object files, make sure to add the flag: -fpic
and when you
generate the library use the flag -shared
. I've tested and this works on OSX
and Linux when using gcc
or clang
.
For example, if I wanted to build a shared library called _decide.so
(.so
is traditional for shared libraries) from
a single decide.c
source file, I would run the commands:
$ gcc -o decide.o -fpic decide.c
$ gcc -o _decide.so -shared decide.o
Pretty easy. One word of caution though, I'm naming my shared library
_decide.so
because calling decide.so
can conflict with decide.py
.
If both decide.so
and decide.py
are in the same directory, in python,
import decide
will cause an error because shared libraries have precedence
over python files for imports.
An instance of this class represents the DECIDE
code. The instance itself
acts like a function that when passed an Input instance will return an
Output instance that reflects the state of the global variables after the
DECIDE
function has been run.
The argument lib_path
is the path to the shared library containing the
DECIDE
function and variables. Some platforms can be a little finicky about
this path, so try using an absolute path, or add a leading "./" when using
a relative path.
LCM
is a helper class for working with the LCM matrix. It has a single
attribute matrix
that is a 15x15 matrix with the modifications made
using the class's methods. Those methods are LCM.notused(i, j)
,
LCM.andd(i, j)
, and LCM.orr(i, j)
that set the value of lcm[i][j]
to
the value you would expect.
An instance of this class defines the inputs to decide. An example can be seen below.
attribute | description |
---|---|
points |
A list of points. Each point is an (x, y) tuple. |
params |
A dictionary mapping fields of the PARAMETERS structure to values. Any values that are un-specified will be set to their defaults (usually 0). The field names are case-insensitive. |
lcm |
A 15x15 matrix containing the values NOTUSED, ANDD, and ORR. The constants NOTUSED, ANDD, and ORR are defined in decide.py and can be imported. The class LCM provides a higher-level interface for this matrix if needed. |
active |
A 15 item list of booleans that describes which LICs are active. This list becomes the diagonal elements of the PUM. |
This class defines the output of the DECIDE
function. An instance of it is
returned when DECIDE
is called. points
, params
, lcm
and active
are the
same as in the Input
class except they are loaded after DECIDE
has run.
They could be used to check and make sure that DECIDE
doesn't change any
values over its run. The remaining fields are documented below:
attribute | description |
---|---|
pum |
A 15x15 boolean matrix containing the values found in the PUM after DECIDE has ran. |
cmv |
A 15 item list of boolean values from the CMV |
fuv |
A 15 item list of boolean values from the FUV |
launch |
A boolean value matching the value of LAUNCH |
Here's a short example illustrating how you might test lic_1 code.
# Import interface
from decide import Input, Decide, LCM, LIC_COUNT
# Load DECIDE
DECIDE = Decide("./_decide.so")
# Set-upt the test-case
points = [(0, 0), (7.00, 0.00), (4.949747, 4.949747)]
radius = 4.04
expected = False
active = [False] * LIC_COUNT
active[1] = True
# Run the Test
output = DECIDE(Input(points, {"radius1": radius}, LCM().matrix, active))
# Check output
assert output.cmv[1] == expected