[Avida-SVN] r3049 - in branches/movement: documentation source/main
welsberr at myxo.css.msu.edu
welsberr at myxo.css.msu.edu
Mon Dec 15 13:13:27 PST 2008
Author: welsberr
Date: 2008-12-15 16:13:27 -0500 (Mon, 15 Dec 2008)
New Revision: 3049
Modified:
branches/movement/documentation/environment.html
branches/movement/source/main/cEnvironment.cc
branches/movement/source/main/cEnvironment.h
Log:
Added ResourcePeak to cEnvironment
Modified: branches/movement/documentation/environment.html
===================================================================
--- branches/movement/documentation/environment.html 2008-12-15 16:56:07 UTC (rev 3048)
+++ branches/movement/documentation/environment.html 2008-12-15 21:13:27 UTC (rev 3049)
@@ -21,8 +21,8 @@
This is the setup file for the task/resource system in Avida.
</p>
<p>
-Five main keywords are used in this file, RESOURCE, REACTION, CELL, MUTATION,
-and SET_ACTIVE. Their
+Six main keywords are used in this file, RESOURCE, REACTION, CELL, MUTATION,
+RESOURCEPEAK, and SET_ACTIVE. Their
formats are:
</p>
<pre>
@@ -30,6 +30,7 @@
<a href="#REACTION">REACTION</a> reaction_name task [process:...] [requisite:...]
<a href="#CELL">CELL</a> resource_name:cell_list[:flow]
<a href="#MUTATION">MUTATION</a> name trigger scope type rate
+ <a href="#RESOURCEPEAK">RESOURCEPEAK</a> resource_name[:options]
<a href="#SET_ACTIVE">SET_ACTIVE</a> type name new_status(default=true)
</pre>
@@ -850,5 +851,120 @@
<hr />
<p><a href="index.html">Return to the Index</a></p>
+<h3>RESOURCEPEAK Command</h3>
+<p>
+Allows user to compactly specify a spatially distributed peak in a resource.
+</p>
+<p>
+The syntax for the ResourcePeak command is:
+</p>
+ <pre><a name="RESOURCEPEAK">RESOURCEPEAK</a> resource_name[:options]</pre>
+
+<blockquote>
+<p>
+Where <code>resource_name</code> is a unique name of the resource.
+This name should be used by the <code>REACTION</code> to define which
+resource is consumed/created by a reaction. This command sets all
+relevant properties of all grid cells, and thus will nullify any
+previous <code>CELL</code> commands for the resource specified.
+</p>
+<p>
+Where <code>options</code> is a colon delimited list of factors that
+modify the resource. The following chart specifies these options.
+</p>
+<p>
+ResourcePeak can define two regimes of linearly decreasing
+resources. The peak itself is defined by grid cell coordinates. Inflow
+is defined for this peak, for the minimum inflow at the maximally
+distant grid cell, and an intermediate inflow at a specified distance
+from the peak. This defines a circular region around the peak with
+higher resource inflow, and the remainder of the grid gets a linearly
+decreasing amount of inflow of the resource as distance increases from
+the peak.
+</p>
+<p>
+This environment command sets properties for every cell in the
+grid. The user should be aware that this will require much more memory
+space than a global resource. As a practical matter, resource
+gradients in the range of [0..1] should have the reaction set to use
+"pow" as the type.
+</p>
+</blockquote>
+<div align="center">
+<p> </p>
+<h3>Table 1: <span>ResourcePeak Options</span></h3>
+<table border="1" cellpadding="2">
+<tr>
+ <th>Argument</th>
+ <th>Description</th>
+ <th>Default</th>
+</tr>
+<tr>
+ <td class="resall">peakx</td>
+ <td>The X coordinate of the resource peak</td>
+ <td>1/2 of "world_x" or middle of the ordinate</td>
+</tr>
+<tr>
+ <td class="resall">peaky</td>
+ <td>
+ The Y coordinate of the resource peak
+ </td>
+ <td>
+ 1/2 of "world_y" or middle of the abscissa
+ </td>
+</tr>
+<tr>
+ <td class="resall">initres</td>
+ <td>
+ The initial abundance of the resource in the population at the
+ start of an experiment. The initial amount is spread evenly to
+ each cell in the world grid.
+ </td>
+ <td>1.0</td>
+</tr>
+<tr>
+ <td class="resall">spread</td>
+ <td>
+ The <i>radius</i> in grid cell units of the region centered on the
+ resource peak where a higher resource inflow is maintained.
+ </td>
+ <td>8.0</td>
+</tr>
+<tr>
+ <td class="resall">maxflow</td>
+ <td>
+ The resource inflow rate at the resource peak.
+ </td>
+ <td>0.2</td>
+</tr>
+<tr>
+ <td class="resall">minflow</td>
+ <td>
+ The resource inflow that a grid cell at a distance from the
+ resource peak equal to that of a diagonal across the grid would
+ receive.
+ </td>
+ <td>0.001</td>
+</tr>
+<tr>
+ <td class="resall">joinflow</td>
+ <td>
+ The resource inflow at the point of change between the local peak
+ resource and the global gradient.
+ </td>
+ <td>maxflow * 0.333333</td>
+</tr>
+<tr>
+ <td class="resall">outflow</td>
+ <td>
+ The global rate of outflow from all cells in the grid.
+ </td>
+ <td>0.5</td>
+</tr>
+</table>
+
+<hr />
+<p><a href="index.html">Return to the Index</a></p>
+
</body>
</html>
Modified: branches/movement/source/main/cEnvironment.cc
===================================================================
--- branches/movement/source/main/cEnvironment.cc 2008-12-15 16:56:07 UTC (rev 3048)
+++ branches/movement/source/main/cEnvironment.cc 2008-12-15 21:13:27 UTC (rev 3049)
@@ -548,6 +548,203 @@
return true;
}
+// @WRE: environment method to set up a resource peak
+bool cEnvironment::LoadResourcePeak(cString desc)
+/*****************************************************************************
+
+ RESOURCEPEAK resource_name:peakx=nn:peaky=nn:spread=nn.nn:initres=nn.nn:minflow=nn.nn:maxflow=nn.nn:outflow:nn.nn:joinflow=nn.nn
+
+ allows a resource peak to be specified in the configuration.
+ There are a bunch of parameters, but it is less work than setting it up by
+ specifying each CELL in the environment file.
+
+ peakx, peaky : the coordinates in the grid where the peak of the spatial
+ resource is located
+ spread : The distance from the peak where a higher resource gradient is
+ in effect
+ initres : the initial amount of resource in each cell
+ minflow, maxflow : the minimum and maximum inflow values. Highest at the
+ peak, linearly decreasing in two ranges: within the "spread" value, and
+ from "spread" to the edges of the grid
+ joinflow : the amount of inflow at distance "spread"
+ outflow : proportion of resource that exits each cell when updated
+
+ ASCII representation of a resource peak on a 7x7 grid, peak at [3,3]:
+
+ . . . , . . .
+ . + + + + + .
+ . + * * * + .
+ , + * @ * + ,
+ . + * * * + .
+ . + + + + + .
+ . . . , . . .
+
+ *****************************************************************************/
+{
+ // Define some variables
+ const int world_x = m_world->GetConfig().WORLD_X.Get();
+ const int world_y = m_world->GetConfig().WORLD_Y.Get();
+
+ // Set of defaults for values
+ int tmp_peakx = world_x / 2;
+ int tmp_peaky = world_y / 2;
+ double tmp_initres = 1.0; // Initial resource amount
+ double tmp_spread = 8.0; // grid unit radius from peak inflow to joinflow
+ double tmp_maxflow = 0.2; // peak inflow
+ double tmp_minflow = 0.001; // minimum inflow
+ double tmp_joinflow = tmp_maxflow * 0.33333333; // inflow at change between local peak and global gradient
+ double tmp_outflow = 0.5; // : outflow from cell
+ int gx = 0;
+ int gy = 0; // : coordinates of current grid cell
+
+ // Echo the input string
+ cout << "LoadResourcePeak: " << desc << endl;
+
+ // Parsing the input
+ cResource* this_resource;
+ while (desc.GetSize() > 0) {
+ cString cur_resource = desc.PopWord();
+ const cString resname = cur_resource.Pop(':');
+
+ cout << "..PopWord: " << cur_resource << "; ..Pop':': " << resname << endl;
+
+ /* if this resource has not been already created go ahead and create it and
+ set some default global values */
+ if (! resource_lib.DoesResourceExist(resname)) {
+ this_resource = resource_lib.AddResource(resname);
+ this_resource->SetInitial(0.0);
+ this_resource->SetInflow(0.0);
+ this_resource->SetOutflow(0.0);
+ this_resource->SetGeometry("GRID");
+ this_resource->SetInflowX1(-99);
+ this_resource->SetInflowX2(-99);
+ this_resource->SetInflowY1(-99);
+ this_resource->SetInflowY2(-99);
+ this_resource->SetOutflowX1(-99);
+ this_resource->SetOutflowX2(-99);
+ this_resource->SetOutflowY1(-99);
+ this_resource->SetOutflowY2(-99);
+ this_resource->SetXDiffuse(0.0);
+ this_resource->SetXGravity(0.0);
+ this_resource->SetYDiffuse(0.0);
+ this_resource->SetYGravity(0.0);
+ this_resource->SetDemeResource("false");
+ } else {
+ this_resource = resource_lib.GetResource(resname);
+ }
+
+ while (cur_resource.GetSize() != 0) {
+ cString var_entry = cur_resource.Pop(':');
+ cString var_name;
+ cString var_value;
+ const cString var_type =
+ cStringUtil::Stringf("resource '%s'", static_cast<const char*>(resname));
+
+ // Parse this entry.
+ if (!ParseSetting(var_entry, var_name, var_value, var_type)) {
+ return false;
+ }
+
+ // Got the parts for this option, now recognize it
+ if (var_name == "peakx") {
+ cout << "..peakx recognized" << endl;
+ if (!AssertInputInt(var_value, "peakx", var_type)) return false;
+ tmp_peakx = var_value.AsInt();
+ if ((0 > tmp_peakx) || (world_x < tmp_peakx)) return false; // Sanity check on input value
+ cout << "..peakx = " << tmp_peakx << endl;
+ }
+ else if (var_name == "peaky") {
+ cout << "..peaky recognized" << endl;
+ if (!AssertInputInt(var_value, "peaky", var_type)) return false;
+ tmp_peaky = var_value.AsInt();
+ if ((0 > tmp_peaky) || (world_y < tmp_peaky)) return false; // Sanity check on input value
+ cout << "..peaky = " << tmp_peaky << endl;
+ }
+ else if (var_name == "initres") {
+ cout << "..initres recognized" << endl;
+ if (!AssertInputDouble(var_value, "initres", var_type)) return false;
+ tmp_initres = var_value.AsDouble();
+ cout << "..initres = " << tmp_initres << endl;
+ }
+ else if (var_name == "spread") {
+ cout << "..spread recognized" << endl;
+ if (!AssertInputDouble(var_value, "spread", var_type)) return false;
+ tmp_spread = var_value.AsDouble();
+ cout << "..spread = " << tmp_spread << endl;
+ }
+ else if (var_name == "maxflow") {
+ cout << "..maxflow recognized" << endl;
+ if (!AssertInputDouble(var_value, "maxflow", var_type)) return false;
+ tmp_maxflow = var_value.AsDouble();
+ cout << "..maxflow = " << tmp_maxflow << endl;
+ }
+ else if (var_name == "minflow") {
+ cout << "..minflow recognized" << endl;
+ if (!AssertInputDouble(var_value, "minflow", var_type)) return false;
+ tmp_minflow = var_value.AsDouble();
+ cout << "..minflow = " << tmp_minflow << endl;
+ }
+ else if (var_name == "joinflow") {
+ cout << "..joinflow recognized" << endl;
+ if (!AssertInputDouble(var_value, "joinflow", var_type)) return false;
+ tmp_joinflow = var_value.AsDouble();
+ cout << "..joinflow = " << tmp_joinflow << endl;
+ }
+ else if (var_name == "outflow") {
+ cout << "..outflow recognized" << endl;
+ if (!AssertInputDouble(var_value, "outflow", var_type)) return false;
+ tmp_outflow = var_value.AsDouble();
+ cout << "..outflow = " << tmp_outflow << endl;
+ }
+ else {
+ cerr << "Error: Unknown variable '" << var_name
+ << "' in resource '" << resname << "'" << endl;
+ return false;
+ }
+ }
+ desc = cur_resource;
+ }
+
+ // The parsing of parameters is now done. Time to set up the cells individually.
+
+ // @WRE: First, clear out previous spatial resource definitions
+ // this_resource->ClearCellResourceList(); // No such method now. I thnk BB had such a method at one point.
+ // Find max distance; take that as diagonal across world grid
+ double d1 = EuclideanDistance2D(0,0,world_x,world_y);
+
+ // Variables to hold cell X and Y coordinates
+ int cx = 0;
+ int cy = 0;
+ double thisdistance = 0.0;
+ double thisinflow = 0.0;
+
+ // @WRE: Now, go over all cells and set them according to parameters
+ for (int i=0; i < (world_x * world_y); i++) {
+ // Determine coordinates for this cell
+ cx = i % world_x;
+ cy = i / world_x;
+
+ // Calculate distance from cell to peak inflow cell
+ thisdistance = EuclideanDistance2D(tmp_peakx,tmp_peaky,cx,cy);
+ // Calculate inflow amount conditionally based on distance
+ if (thisdistance <= tmp_spread) { // Local ramp to peak resource inflow
+ thisinflow = LinMap(thisdistance,0.0,tmp_spread,tmp_maxflow,tmp_joinflow);
+ } else { // Global ramp to joinflow
+ thisinflow = LinMap(thisdistance,0.0,d1,tmp_joinflow,tmp_minflow);
+ }
+
+ cout << "..cell xy=[" << cx << "," << cy << "] initres=" <<
+ tmp_initres << " cell inflow=" << thisinflow << " cell outflow=" <<
+ tmp_outflow << endl;
+
+ cCellResource tmp_cell_resource(i,tmp_initres,
+ thisinflow, tmp_outflow);
+ this_resource->AddCellResource(tmp_cell_resource);
+ }
+
+ return true;
+}
+
bool cEnvironment::LoadReaction(cString desc)
{
// Make sure this reaction has a description...
@@ -765,6 +962,7 @@
else if (type == "MUTATION") load_ok = LoadMutation(line);
else if (type == "SET_ACTIVE") load_ok = LoadSetActive(line);
else if (type == "CELL") load_ok = LoadCell(line);
+ else if (type == "RESOURCEPEAK") load_ok = LoadResourcePeak(line);
else {
cerr << "Error: Unknown environment keyword '" << type << "." << endl;
return false;
@@ -1006,7 +1204,7 @@
} else {
// Otherwise we're using a finite resource
const int res_id = in_resource->GetID();
-
+
assert(resource_count[res_id] >= 0);
assert(result.GetConsumed(res_id) >= 0);
consumed = resource_count[res_id] - result.GetConsumed(res_id);
@@ -1304,3 +1502,33 @@
return true;
}
+// @WRE: helper method to allow easy linear interpolation
+// Given a domain interval [dlow..dhigh] and a corresponding range
+// interval [rlow..rhigh], and a value in the domain, dy, return the
+// linearly interpolated range value for dy. Note that dy need not be
+// in the interval [dlow..dhigh].
+double cEnvironment::LinMap(double dy, double dlow, double dhigh, double rlow, double rhigh)
+{
+ double ry;
+
+ if (dlow != dhigh) {
+ ry = (dy - dlow) * ((rhigh - rlow) / (dhigh - dlow)) + rlow;
+ } else {
+ ry = 0.0;
+ }
+ return ry;
+}
+
+// @WRE: helper method to get euclidean distances from grid coordinates
+// Given points [x1,y1] and [x2,y2], return the Euclidean distance between
+// them.
+double cEnvironment::EuclideanDistance2D(int x1, int y1, int x2, int y2)
+{
+ double ed = 0.0;
+ int xs = abs(x1 - x2);
+ int ys = abs(y1 - y2);
+
+ ed = sqrt((xs * xs) + (ys * ys));
+
+ return ed;
+}
Modified: branches/movement/source/main/cEnvironment.h
===================================================================
--- branches/movement/source/main/cEnvironment.h 2008-12-15 16:56:07 UTC (rev 3048)
+++ branches/movement/source/main/cEnvironment.h 2008-12-15 21:13:27 UTC (rev 3049)
@@ -107,6 +107,8 @@
bool LoadCell(cString desc);
bool LoadReaction(cString desc);
bool LoadMutation(cString desc);
+ // @WRE: Add environment option to define a spatial resource peak
+ bool LoadResourcePeak(cString desc);
bool LoadSetActive(cString desc);
@@ -170,6 +172,9 @@
bool SetResourceInflow(const cString& name, double _inflow );
bool SetResourceOutflow(const cString& name, double _outflow );
+ // @WRE: helper methods for resource peak method
+ double LinMap(double dy, double dlow, double dhigh, double rlow, double rhigh);
+ double EuclideanDistance2D(int x1, int y1, int x2, int y2);
};
More information about the Avida-cvs
mailing list