269 lines
14 KiB
Markdown
269 lines
14 KiB
Markdown
<p>
|
|
The environment source code consists of several main components: resources,
|
|
reactions, and task triggers, plus the libraries that maintain each of these.
|
|
</p>
|
|
|
|
|
|
<p> </p>
|
|
<h2>Task Entries</h2>
|
|
|
|
<p>
|
|
A task library is composed of a collection of entries, each of which fully
|
|
describes a single task that can be used to trigger reactions.
|
|
</p>
|
|
<pre>
|
|
typedef <span class="class">double</span> (<span class="class">cTaskLib</span>::*<span class="object">tTaskTest</span>)(<span class="class">cTaskContext</span>*) const;
|
|
|
|
class <span class="class">cTaskEntry</span> {
|
|
private:
|
|
<span class="class">cString</span> <span class="object">m_name</span>; <span class="comment">// Short keyword for task</span>
|
|
<span class="class">cString</span> <span class="object">m_desc</span>; <span class="comment">// For more human-understandable output...</span>
|
|
<span class="class">int</span> <span class="object">m_id</span>;
|
|
<span class="class">tTaskTest</span> <span class="object">m_test_fun</span>;
|
|
<span class="class">cString</span> <span class="object">m_info</span>; <span class="comment">// extra info (like the string or whatever to match)</span>
|
|
|
|
public:
|
|
<span class="method">cTaskEntry</span>(const <span class="class">cString</span>& <span class="object">name</span>, const <span class="class">cString</span>& <span class="object">desc</span>, int <span class="object">in_id</span>, <span class="class">tTaskTest</span> <span class="object">test_fun</span>, const <span class="class">cString</span>& <span class="object">info</span>);
|
|
: m_name(name), m_desc(desc), m_id(in_id), m_test_fun(test_fun), m_info(info)
|
|
{
|
|
}
|
|
~<span class="method">cTaskEntry</span>() { ; }
|
|
|
|
const <span class="class">cString</span>& <span class="method">GetName</span>() const { return <span class="object">m_name</span>; }
|
|
const <span class="class">cString</span>& <span class="method">GetDesc</span>() const { return <span class="object">m_desc</span>; }
|
|
const int <span class="method">GetID</span>() const { return <span class="object">m_id</span>; }
|
|
const <span class="class">tTaskTest</span> <span class="method">GetTestFun</span>() const { return <span class="object">m_test_fun</span>; }
|
|
const <span class="class">cString</span>& <span class="method">GetInfo</span>() const { return <span class="object">m_info</span>; }
|
|
};
|
|
</pre>
|
|
|
|
<p>
|
|
Task entries are very straight-forward. They consist of a name, a description,
|
|
a unique ID number, and a method from the task library (cTaskLib) that they
|
|
are associated with. This method looks at the inputs the organism has taken
|
|
in, the values it has output, and returns a number between 0.0 and 1.0
|
|
representing how well the task was performed. Currently, all task tests will
|
|
return an exact zero or one, but fractions are possible if there
|
|
is a quality component associated with the task.
|
|
</p>
|
|
|
|
|
|
<p> </p>
|
|
<h2>Task Libraries</h2>
|
|
|
|
<p>
|
|
Here is an abridged version of the task library class that manages all of the
|
|
individual entries:
|
|
</p>
|
|
|
|
<pre>
|
|
class <span class="class">cTaskLib</span> {
|
|
private:
|
|
<span class="class">Apto::Array</span><<span class="class">cTaskEntry</span>*> <span class="object">task_array</span>;
|
|
|
|
public:
|
|
int <span class="method">GetSize</span>() const { return <span class="object">task_array</span>.<span class="method">GetSize</span>(); }
|
|
|
|
<span class="class">cTaskEntry</span>* <span class="method">AddTask</span>(const <span class="class">cString</span>& <span class="object">name</span>, const <span class="class">cString</span>& <span class="object">info</span>);
|
|
const <span class="class">cTaskEntry</span>& <span class="method">GetTask</span>(<span class="class">int</span> <span class="object">id</span>) const;
|
|
|
|
void <span class="method">SetupTests</span>(<span class="class">cTaskContext</span>& <span class="object">ctx</span>) const;
|
|
inline double <span class="method">TestOutput</span>(const <span class="class">cTaskEntry</span>& <span class="object">task</span>, <span class="class">cTaskContext</span>* ctx) const;
|
|
|
|
private:
|
|
double <span class="method">Task_Echo</span>(<span class="class">cTaskContext</span>* <span class="object">ctx</span>) const;
|
|
double <span class="method">Task_Add</span>(<span class="class">cTaskContext</span>* <span class="object">ctx</span>) const;
|
|
double <span class="method">Task_Sub</span>(<span class="class">cTaskContext</span>* <span class="object">ctx</span>) const;
|
|
|
|
double <span class="method">Task_Not</span>(<span class="class">cTaskContext</span>* <span class="object">ctx</span>) const;
|
|
double <span class="method">Task_Nand</span>(<span class="class">cTaskContext</span>* <span class="object">ctx</span>) const;
|
|
double <span class="method">Task_And</span>(<span class="class">cTaskContext</span>* <span class="object">ctx</span>) const;
|
|
<span class="comment">// ... And a whole bunch more ...</span>
|
|
|
|
};
|
|
</pre>
|
|
|
|
<p>
|
|
The task library contains an array of task entries that define all of the
|
|
rewarded (or otherwise acted upon) tasks in an environment.
|
|
</p>
|
|
<p>
|
|
The <span class="method">TestOutput</span>() method can only be run with
|
|
as <span class="class">cTaskContext</span> object that has been initialized
|
|
with the <span class="method">SetupTests</span> method. It will test the
|
|
specific task passed in and return the 0.0 - 1.0 quality measure of how well
|
|
that task was done with the most recent output.
|
|
</p>
|
|
|
|
<p>
|
|
Below is a sample task-tester implementation:
|
|
|
|
<pre>
|
|
double <span class="class">cTaskLib</span>::<span class="method">Task_Add</span>(<span class="class">cTaskContext</span>* <span class="object">ctx</span>) const
|
|
{
|
|
const int <span class="object">test_output</span> = <span class="object">ctx</span>-><span class="object">output_buffer</span>[0];
|
|
for (<span class="class">int</span> <span class="object">i</span> = 0; <span class="object">i</span> < <span class="object">ctx</span>-><span class="object">input_buffer</span>.<span class="method">GetNumStored</span>(); <span class="object">i</span>++) {
|
|
for (<span class="class">int</span> <span class="object">j</span> = 0; <span class="object">j</span> < <span class="object">i</span>; <span class="object">j</span>++) {
|
|
if (<span class="object">test_output</span> == <span class="object">ctx</span>-><span class="object">input_buffer</span>[<span class="object">i</span>] + <span class="object">ctx</span>-><span class="object">input_buffer</span>[<span class="object">j</span>]) return 1.0;
|
|
}
|
|
}
|
|
return 0.0;
|
|
}
|
|
</pre>
|
|
|
|
<p>
|
|
This case tests to see if the organism has performed an addition operation.
|
|
It compares all pairs of inputs summed together against the most recent
|
|
output of the organism. If there is a match a full reward (1.0) is given.
|
|
If no match is found, no reward is given (0.0).
|
|
</p>
|
|
|
|
<p>
|
|
The <span class="method">SetupTests</span> method performs some
|
|
precomptution for all of the logic tasks, creating the value
|
|
<span class="object">logic_id</span> within the task context. The
|
|
<span class="object">logic_id</span> has 256 possible values, each of which
|
|
can only be associated with a single logic task. These tests look more like:
|
|
</p>
|
|
|
|
<pre>
|
|
double <span class="class">cTaskLib</span>::<span class="method">Task_AndNot</span>(<span class="class">cTaskContext</span>* <span class="object">ctx</span>) const
|
|
{
|
|
const int <span class="object">logic_id</span> = <span class="object">ctx</span>-><span class="object">logic_id</span>;
|
|
if (<span class="object">logic_id</span> == 10 || <span class="object">logic_id</span> == 12 || <span class="object">logic_id</span> == 34 ||
|
|
<span class="object">logic_id</span> == 48 || <span class="object">logic_id</span> == 68 || <span class="object">logic_id</span> == 80) return 1.0;
|
|
return 0.0;
|
|
}
|
|
</pre>
|
|
|
|
<p>
|
|
If the logic ID is on the list, the task has been done, otherwise it hasn't.
|
|
In each case, the outside world needs to request a test of which tasks have
|
|
been performed, and the library just replied with a numerical answer.
|
|
</p>
|
|
|
|
|
|
<p> </p>
|
|
<h2>Building a Reaction</h2>
|
|
|
|
<p>
|
|
The reaction class keeps track of all of the information associated with
|
|
a single possible environmental reaction. Each reaction must have a unique
|
|
name and a unique numerical ID associated with them. In addition to those
|
|
data, a reaction object also has a task that acts as its trigger, a list of
|
|
other requisites that must be met for the trigger to work, and a list of
|
|
processes that will occur if the reaction goes off. The cReaction object
|
|
acts a a single place to store all of this information.
|
|
</p>
|
|
|
|
|
|
<p> </p>
|
|
<h2>Resources</h2>
|
|
|
|
<p>
|
|
Resources are a little more complicated than task entries to manage
|
|
and understand. An object of type <span class="class">cResource</span>
|
|
contains 19 pieces of data, and the associated accessors. Like all of the
|
|
other individual units we have discussed, resources have a unique
|
|
<span class="object">name</span> and numerical
|
|
<span class="object">id</span>. For all resource we store the quantities
|
|
associated with their <span class="object">inflow</span>,
|
|
<span class="object">outflow</span>, and
|
|
<span class="object">initial</span> count (each stored as a
|
|
double) as well as the <span class="object">geometry</span> of that resource.
|
|
|
|
<p>
|
|
For spatial resources we need to be able to describe how a resource
|
|
exists in space so we store data for:
|
|
<ul>
|
|
<li>
|
|
<span class="object">inflowX1</span>,
|
|
<span class="object">inflowX2</span>,
|
|
<span class="object">inflowY1</span>, and
|
|
<span class="object">inflowY2</span> to describe a rectangle where
|
|
resources flow in.
|
|
</li>
|
|
<li>
|
|
<span class="object">outflowX1</span>,
|
|
<span class="object">outflowX2</span>,
|
|
<span class="object">outflowY1</span>, and
|
|
<span class="object">outfowY2</span> for a rectangle where resources
|
|
flow out.
|
|
</li>
|
|
<li>
|
|
<span class="object">cell_list</span> is a list of individual cells with
|
|
their own initial, inflow and outflow values.
|
|
<li>
|
|
<span class="object">xdiffuse</span> and
|
|
<span class="object">ydiffuse</span> describe how fast resources will
|
|
flow from cells of higher amounts of that resource to cells with
|
|
lower amounts of that resource.
|
|
</li>
|
|
<li>
|
|
<span class="object">xgravity</span> and
|
|
<span class="object">ygravity</span> describe the preferential flow of
|
|
resource in a given direction.
|
|
</li>
|
|
</ul>
|
|
<p>
|
|
This class describes the dynamics of a resource, not its current count
|
|
(since, for example, we might want local resources where each cell
|
|
would have its own count). However, every time a
|
|
resource is needed, any changes in its quantity from the last time it was
|
|
used can be calculated using these numbers.
|
|
</p>
|
|
|
|
|
|
<p> </p>
|
|
<h2>Tying it all together: The Environment</h2>
|
|
|
|
<p>
|
|
The cEnvironment class is used to maintain the details of how the environments
|
|
work using the classes described above and a few others. Below is an
|
|
abbreviated version of this class:
|
|
</p>
|
|
|
|
<pre>
|
|
class <span class="class">cEnvironment</span> {
|
|
private:
|
|
<span class="comment">// Keep libraries of resources, reactions, and tasks.</span>
|
|
<span class="class">cResourceLib</span> <span class="object">resource_lib</span>;
|
|
<span class="class">cReactionLib</span> <span class="object">reaction_lib</span>;
|
|
<span class="class">cTaskLib</span> <span class="object">task_lib</span>;
|
|
<span class="class">cInstLib</span> <span class="object">inst_lib</span>;
|
|
<span class="class">cMutationRates</span> <span class="object">mut_rates</span>;
|
|
|
|
public:
|
|
<span class="class">bool</span> <span class="method">Load</span>(const <span class="class">cString</span>& <span class="object">filename</span>);
|
|
|
|
<span class="comment">// Interaction with the organisms</span>
|
|
<span class="class">bool</span> <span class="method">TestOutput</span>(<span class="class">cAvidaContext</span>& <span class="object">ctx</span>, <span class="class">cReactionResult</span>& <span class="object">result</span>, <span class="class">cTaskContext</span>& <span class="object">taskctx</span>,
|
|
const <span class="class">tBuffer</span><int>& <span class="object">send_buf</span>, const <span class="class">tBuffer</span><int>& <span class="object">receive_buf</span>,
|
|
const <span class="class">Apto::Array</span><int>& <span class="object">task_count</span>, const <span class="class">Apto::Array</span><int>& <span class="object">reaction_count</span>,
|
|
const <span class="class">Apto::Array</span><double>& <span class="object">resource_count</span>) const;
|
|
};
|
|
</pre>
|
|
|
|
<p>
|
|
The private data members include all of the libraries needed to specify
|
|
the environment, plus its mutation rates. The
|
|
<span class="method">Load</span>() method takes a filename
|
|
(<kbd>environment.cfg</kbd> by default) and will fill out all of the libraries
|
|
in this environment. The most important feature of this class is the
|
|
<span class="method">TestOutput</span>() method, which takes in all sorts
|
|
of information about the current state of the organism that has just done
|
|
an output and fills out an object of type
|
|
<span class="class">cReactionResult</span> with information about what
|
|
happened. It also directly returns a bool that will indicate if there have
|
|
been any changes at all. The specific information it uses to determine
|
|
the results are the inputs the organism has taken in and the outputs it has
|
|
produced -- both needed to determine what tasks have been done, and therefore
|
|
what reactions may have been triggered. This information is encapsulated in
|
|
the task context <span class="object">taskctx</span>. The organism's
|
|
previous <span class="object">task_count</span> and
|
|
<span class="object">resource_count</span> are also needed to determine
|
|
if the reactions requisites have been met. And finally the
|
|
<span class="object">resource_count</span> available to the organisms is
|
|
needed to determine how much of each resource can be used in the reactions.
|
|
</p>
|