Skip to content
David Bryson edited this page Jan 17, 2014 · 1 revision

Subpopulation migration in Avida is supported by the assignment of "migration weights" for connections between subpopulations. The migration "topology" between subpopulations is defined through reading in a connection-weight matrix in the following format: 
 

# BEGIN
# All text beyond the '#' character in a file is a comment and will not be read in by Avida
# Subpop:        [0]       [1]      [2]     [3]
                       5.0,   0.10,   0.0,   4.0    # [0]      Row[0].Sum = 9.10
                       3.0,   0.20,   0.8,   2.0    # [1]      Row[1].Sum = 6.00
                       7.0,   0.30,   0.0,   1.0    # [2]      Row[2].Sum = 8.30
                       2.0,   1.30,   9.0,   0.0    # [3]      Rom[3].Sum = 12.30
# END


What this file means
: The above un-commented text shows a simple 4-line file with each line containing 4 comma-separated values. Each row in the connection matrix contains all the connection weights *from* subpopulation[row] to other subpopulations that are indexed by column. For example, the connection weight between Subpopulation[1] and Subpopulation[2] is 0.8 where the from-subpopulation is row index 1 and to-subpopulation is column index 2. By setting each of these weights, you can specify what the appropriate migration probability will be from a given subpopulation to another subpopulation. Internally, when a migration event is going to occur from a given subpopulation (let's assume Subpopulation[1]), Avida will sum up the values in row 1 of the connectivity matrix (3.0 + 0.20 + 0.8 + 2.0 = 6.00) and generate a random number between: 0 and Row[1].Sum. This random number will be used to determine which subpopulation the organism will migrate into using a "roulette selection" protocol where each connection is represented by its weight's proportion of the sum.  As you may have noticed, the sum of a row does not have to equal 1.0 as a typical probability matrix does. The probability matrix would be an exclusive subset of the type of connectivity matrices you can use under this setup. 
Restrictions for this file (and why):

  1. The number of rows must equal the number of demes which must equal the number of columns in each row - This assumes that you will provide a connection weight value for every subpopulation pair possible. This is easier to read for both us as researchers and the computer/programmer :)
  2. A row's sum cannot equal 0.0 - Minimally, there must be a path for migration to occur and the control/null case is that the organism remains in its own subpopulation.  Therefore, to use the migration matrix but turn migration among subpopulations OFF, one can simply supply the identity matrix where the diagonal is the only non-zero value (or just not use the migration matrix method ). 
  3. A matrix entry cannot be negative - Intuitively, a negative migration value does not carry much meaning when trying to determine where an organism will migrate to and therefore, this will not be allowed.

 

To turn on and use subpopulation migration, the following configuration parameters in *avida.cfg* will need to be set appropriately: 

(1) MIGRATION_FILE -- This config setting should be set to the migration file name that you want Avida to initialize with. Note: This file must be contained in the same working directory as your avida.cfg, events.cfg, and other Avida-related files. This setting is only used by Avida when the DEMES_MIGRATION_METHOD is set to use the migration matrix, otherwise a dummy value can be left here. 

(2) NUM_DEMES - This value specifies the total number of subpopulations in the run and it is *critical* that your MIGRATION_FILE's connectivity matrix have NUM_DEMES rows and that each row has NUM_DEMES columns. 

(3) DEMES_MIGRATION_RATE - This value can be between 0.0 and 1.0 and essentially specifies the "success rate" that a triggered migration event will actually take place. When set to 0.0, migration will *never* occur and when set to 1.0, a triggered migration rate will *always* succeed and use the DEMES_MIGRATION_METHOD. If this value was set to 0.50, for example, it would mean that a migration event would trigger but that 50% of the time the actual migration action would not occur. 

(4) DEMES_MIGRATION_METHOD - This config setting should be set to 4 to use the new connection matrix setup. Rather than the pre-built migration methods (Any other deme, Eight neighboring demes, Two adjacent demes in list, etc.), the "4" setting specifies to use the weights within the migration matrix to determine where an organism should migrate to. 

 

Deme Migration Events (can be added in your events.cfg)

  • SetMigrationMatrix - The SetMigrationMatrix event takes one argument/parameter which is the filename of a *new* migration matrix to be used to replace the current one. For example, if a user wanted to "turn off migration at update 10,000", he/she could add a line into events.cfg that reads as follows: "u 10000 SetMigrationMatrix migration2.cfg". At update 10,000, this event would be triggered causing the migration2.cfg file (containing connection values only on the diagonal) to be used. Note: This migration file must adhere to the restrictions stated above, otherwise Avida will report an error and exit mid-run.
  • AlterMigrationConnection - To provide more fine-grained control over how connection weights change, the AlterMigrationConnection event can be used in place of SetMigrationMatrix. This event takes *3* arguments: (1) from-index, (2) to-index, (3) alter_amount. When triggered, this event will go to the weight indexed by [from-index][to-index] and add the alter_amount value to the current weight. Naturally, if you wanted to decrease the current weight, you would simply make the alter_amount argument a negative value. By using the standard event protocol in Avida that has [start:interval:end], it is possible to cause a connection weight to change over a period of time by a certain amount. For example, if a user wanted to "decrease the connection between Subpopulation 0 and Subpopulation 1 by 3 units every 100 updates from update 10,000 to update 20,000" the corresponding event would be: "u [10000:100:20000] AlterMigrationConnection 0  1  -3.0". Note: Every time this event is triggered it will alter the last updated amount for that connection, if the matrix entry value goes negative or if the row's sum becomes 0.0, an error will be flagged and the run will exit. (This will likely need fixing in the future .. but for now keep it in mind)
  • DumpOffspringMigrationCounts - The DumpOffspringMigrationCounts action can be used to output how many organisms have migrated between the subpopulations (demes) in Avida. Each file that is outputted will appear in the data/ folder as follows: counts_offspring_migration.[update].dat.  The [update] will contain the update # at which the file was dumped to the folder. The file is internally structured as a comma-separated (CSV) file containing a total of NUM_DEMES individual lines and each line containing NUM_DEMES comma-separated values (exactly like the MIGRATION_FILE). A 2D index into this CSV matrix (say the Yth CSV-value on line X) returns the number of offspring that migrated from subpopulation X to subpopulation Y. *Note*: After each dump, all migration counts are reset to zero, therefore, if you want the total number of migrations that occurred in the entire run, you would need to sum up the respective values across all files dumped. An example of this command is: "u 100:200:end DumpOffspringMigrationCounts" where the user wanted to "dump the offspring migration counts starting at update 100 for every 200 updates until the end of the run." 
  • DumpParasiteMigrationCounts - The DumpParasiteMigrationCounts action can be used to output how many parasites have migrated between the subpopulations (demes) in Avida. Each file that is outputted will appear in the data/ folder as follows: counts_parasite_migration.[update].dat.  The [update] will contain the update # at which the file was dumped to the folder. The file is internally structured as a comma-separated (CSV) file containing a total of NUM_DEMES individual lines and each line containing NUM_DEMES comma-separated values (exactly like the MIGRATION_FILE). A 2D index into this CSV matrix (say the Yth CSV-value on line X) returns the number of parasites that migrated from subpopulation X to subpopulation Y. *Note*: After each dump, all migration counts are reset to zero, therefore, if you want the total number of parasite migrations that occurred in the entire run, you would need to sum up the respective values across all files dumped. An example of this command is: "u 100:200:end DumpParasiteMigrationCounts" where the user wanted to "dump the parasite migration counts starting at update 100 for every 200 updates until the end of the run."
Hopefully this wiki article is of benefit for others who want to explore migration using Avida. If you have any questions/comments about the implementation, please feel free to contact me (Chad Byers) at byerscha@msu.edu 
 
For Developers: To see where, in the source files, that updates/revisions have been made to support subpopulation migration, use the *Find All* feature in your IDE and search for "MIGRATION_MATRIX"
Clone this wiki locally