1 //
2 //  cMigrationMatrix.cc
3 //  Avida-Core
4 //
5 //  Created by Chad Byers on 2/16/12.
6 //  Copyright (c) 2012 Michigan State University. All rights reserved.
7 //
8 
9 #include "cMigrationMatrix.h"
10 
11 #include "avida/core/Feedback.h"
12 #include "cInitFile.h"
13 #include "cString.h"
14 #include "cStringUtil.h"
15 
cMigrationMatrix()16 cMigrationMatrix::cMigrationMatrix(){
17 
18 };
19 
~cMigrationMatrix()20 cMigrationMatrix::~cMigrationMatrix(){
21 
22 }
23 
GetOffspringCountAt(int from_deme_id,int to_deme_id)24 int cMigrationMatrix::GetOffspringCountAt(int from_deme_id, int to_deme_id){
25   assert(from_deme_id >= 0 && from_deme_id < m_offspring_migration_counts.GetSize());
26   assert(to_deme_id >= 0 && to_deme_id < m_offspring_migration_counts[from_deme_id].GetSize());
27   return m_offspring_migration_counts[from_deme_id][to_deme_id];
28 };
29 
GetParasiteCountAt(int from_deme_id,int to_deme_id)30 int cMigrationMatrix::GetParasiteCountAt(int from_deme_id, int to_deme_id){
31   assert(from_deme_id >= 0 && from_deme_id < m_parasite_migration_counts.GetSize());
32   assert(to_deme_id >= 0 && to_deme_id < m_parasite_migration_counts[from_deme_id].GetSize());
33   return m_parasite_migration_counts[from_deme_id][to_deme_id];
34 };
35 
AlterConnectionWeight(const int from_deme_id,const int to_deme_id,const double alter_amount)36 bool cMigrationMatrix::AlterConnectionWeight(const int from_deme_id, const int to_deme_id, const double alter_amount){
37   m_migration_matrix[from_deme_id][to_deme_id] += alter_amount;
38   m_row_connectivity_sums[from_deme_id] += alter_amount;
39   double row_sum = 0.0;
40   for(int col = 0; col < m_migration_matrix[from_deme_id].GetSize();col++){
41     row_sum += m_migration_matrix[from_deme_id][col];
42   }
43   if(m_migration_matrix[from_deme_id][to_deme_id] < 0.0 || row_sum <= 0.0){
44     return false;
45   }
46   else
47     return true;
48 };
49 
GetProbabilisticDemeID(const int from_deme_id,cRandom & p_rng,bool p_is_parasite_migration)50 int cMigrationMatrix::GetProbabilisticDemeID(const int from_deme_id,cRandom& p_rng,bool p_is_parasite_migration){
51     assert(0 <= from_deme_id && from_deme_id < m_migration_matrix.GetSize());
52     double row_range_sum = 0.0;
53     double rand_dbl_value_in_range = p_rng.GetDouble(m_row_connectivity_sums[from_deme_id]);
54     for(int col = 0; col < m_migration_matrix[from_deme_id].GetSize(); col++){
55         rand_dbl_value_in_range -= m_migration_matrix[from_deme_id][col];
56         if(rand_dbl_value_in_range <= 0.0){
57             if(p_is_parasite_migration)
58               m_parasite_migration_counts[from_deme_id][col] += 1;
59             else
60               m_offspring_migration_counts[from_deme_id][col] += 1;
61 
62             return col;
63         }
64     }
65     // Should never get to this point
66     assert(false);
67 };
68 
Load(const int num_demes,const cString & filename,const cString & working_dir,bool p_count_parasites,bool p_count_offspring,bool p_is_reload,Feedback & feedback)69 bool cMigrationMatrix::Load(const int num_demes, const cString& filename, const cString& working_dir,bool p_count_parasites, bool p_count_offspring, bool p_is_reload, Feedback& feedback){
70   m_migration_matrix.ResizeClear(0);
71   m_row_connectivity_sums.ResizeClear(0);
72   cInitFile infile(filename, working_dir);
73   if (!infile.WasOpened()) {
74     for (int i = 0; i < infile.GetFeedback().GetNumMessages(); i++) {
75       switch (infile.GetFeedback().GetMessageType(i)) {
76         case cUserFeedback::UF_ERROR:
77           feedback.Error(infile.GetFeedback().GetMessage(i));
78           break;
79         case cUserFeedback::UF_WARNING:
80           feedback.Warning(infile.GetFeedback().GetMessage(i));
81           break;
82         default:
83           feedback.Notify(infile.GetFeedback().GetMessage(i));
84       }
85     }
86     feedback.Error("failed to load migration matrix '%s'", (const char*)filename);
87     return false;
88   }
89 
90   tSmartArray<double> f_temp_row;
91   for (int line_id = 0; line_id < infile.GetNumLines(); line_id++) {
92     // Load the next line from the file.
93     f_temp_row.ResizeClear(0);
94     cString f_curr_line = infile.GetLine(line_id);
95     double f_row_sum = 0.0;
96     while(!f_curr_line.IsEmpty()){
97       double val = f_curr_line.Pop(',').AsDouble();
98       if(val < 0.0){
99         feedback.Error("Cannot have a negative connection in connection matrix");
100         return false;
101       }
102       f_row_sum += val;
103       f_temp_row.Push(val);
104     }
105     if(f_row_sum == 0.0){
106       feedback.Error("Cannot have a row sum of 0.0 in connection matrix");
107       return false;
108     }
109     else{
110       m_row_connectivity_sums.Push(f_row_sum);
111     }
112     m_migration_matrix.Push(f_temp_row);
113   }
114 
115   if(num_demes != m_migration_matrix.GetSize()){
116     feedback.Error("The number of demes in the migration matrix (%i) did not match the NUM_DEMES (%i) parameter in avida.cfg.",m_migration_matrix.GetSize(),num_demes);
117     return false;
118   }
119   for(int f_row = 0; f_row < m_migration_matrix.GetSize(); f_row++){
120     if(m_migration_matrix[f_row].GetSize() != m_migration_matrix.GetSize()){
121       feedback.Error("The number of columns in row %i did not match total number of demes",f_row);
122       return false;
123     }
124     if(m_migration_matrix[f_row].GetSize() != num_demes){
125       feedback.Error("The number of demes in the migration matrix (%i) did not match the NUM_DEMES (%i) parameter in avida.cfg.",m_migration_matrix.GetSize(),num_demes);
126       return false;
127     }
128   }
129 
130   if(p_count_parasites && !p_is_reload){
131     m_parasite_migration_counts.Resize(num_demes, tSmartArray<int>(num_demes,0));
132     ResetParasiteCounts();
133   }
134 
135   if(p_count_offspring && !p_is_reload){
136     m_offspring_migration_counts.Resize(num_demes, tSmartArray<int>(num_demes,0));
137     ResetOffspringCounts();
138   }
139 
140   return true;
141 }
142 
Print()143 void cMigrationMatrix::Print(){
144     for(int row = 0; row < m_migration_matrix.GetSize(); row++){
145         for(int col = 0; col < m_migration_matrix[row].GetSize(); col++){
146             std::cout << m_migration_matrix[row][col];
147             if(col + 1 < m_migration_matrix[row].GetSize())
148                 std::cout << ",";
149         }
150         std::cout << std::endl;
151     }
152 };
153 
ResetParasiteCounts()154 void cMigrationMatrix::ResetParasiteCounts(){
155   for(int row = 0; row < m_parasite_migration_counts.GetSize(); row++){
156     for(int col = 0; col < m_parasite_migration_counts[row].GetSize(); col++){
157       m_parasite_migration_counts[row][col] = 0;
158     }
159   }
160 };
161 
ResetOffspringCounts()162 void cMigrationMatrix::ResetOffspringCounts(){
163   for(int row = 0; row < m_offspring_migration_counts.GetSize(); row++){
164     for(int col = 0; col < m_offspring_migration_counts[row].GetSize(); col++){
165       m_offspring_migration_counts[row][col] = 0;
166     }
167   }
168 };
169