[Avida-cvs] [Avida2-svn] r390 - trunk/source/main

ofria@myxo.css.msu.edu ofria at myxo.css.msu.edu
Thu Nov 10 19:43:36 PST 2005


Author: ofria
Date: 2005-11-10 22:43:36 -0500 (Thu, 10 Nov 2005)
New Revision: 390

Modified:
   trunk/source/main/cAnalyze.cc
   trunk/source/main/cAnalyze.h
   trunk/source/main/cAnalyzeGenotype.cc
   trunk/source/main/cAnalyzeGenotype.h
   trunk/source/main/cLandscape.cc
Log:
Upgraded "VERBOSE" command in anayze mode so that it now has four modes:
  SILENT outputs nothing
  QUIET outputs only names of commands run
  ON outputs other useful information about what's being processed
  DETAILS is a very detailed output.

For the moment, this is implemented in a piecemeal fashion, but ideally we'll
upgrade all of the commands to behave correctly with time.

ALSO: Updated analyze commands ANALYZE_KNOCKOUTS and ANALYZE_COMPLEXITY_DELTA
to output more info.


Modified: trunk/source/main/cAnalyze.cc
===================================================================
--- trunk/source/main/cAnalyze.cc	2005-11-10 21:50:26 UTC (rev 389)
+++ trunk/source/main/cAnalyze.cc	2005-11-11 03:43:36 UTC (rev 390)
@@ -63,7 +63,7 @@
 cAnalyze::cAnalyze(cString filename, cEnvironment *environment)
 : cur_batch(0)
 , d_environment(environment)
-, verbose(false)
+, verbose(nAnalyze::VERBOSE_QUIET)
 , interactive_depth(0)
 , inst_set(cHardwareUtil::DefaultInstSet(cConfig::GetInstFilename()))
 {
@@ -269,7 +269,7 @@
     << endl;
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Loading in " << num_steps
     << " detail files from update " << start_UD
     << " to update " << stop_UD
@@ -840,7 +840,7 @@
     exit(1);
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Loading file of type: " << filetype << endl;
   }
   
@@ -896,7 +896,7 @@
   // If no arguments are passed in, just find max num_cpus.
   if (cur_string.GetSize() == 0) cur_string = "num_cpus";
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Reducing batch " << cur_batch << " to genotypes: ";
   }
   
@@ -904,7 +904,7 @@
   tListPlus<cAnalyzeGenotype> found_list;
   while (cur_string.CountNumWords() > 0) {
     cString gen_desc(cur_string.PopWord());
-    if (verbose) cout << gen_desc << " ";
+    if (verbose >= nAnalyze::VERBOSE_ON) cout << gen_desc << " ";
     
     // Determine by lin_type which genotype were are tracking...
     cAnalyzeGenotype * found_gen = PopGenotype(gen_desc, cur_batch);
@@ -938,7 +938,7 @@
     return;
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Reducing batch " << cur_batch << " to organisms: " << endl;
   }
   
@@ -950,7 +950,7 @@
   
   while (cur_string.CountNumWords() > 0) {
     cString org_desc(cur_string.PopWord());
-    if (verbose) cout << org_desc << " ";
+    if (verbose >= nAnalyze::VERBOSE_ON) cout << org_desc << " ";
     
     // Determine by org_desc which genotype were are tracking...
     if (org_desc == "random") {
@@ -1007,7 +1007,7 @@
   cString lin_type = "num_cpus";
   if (cur_string.CountNumWords() > 0) lin_type = cur_string.PopWord();
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Reducing batch " << cur_batch
     << " to " << lin_type << " lineage " << endl;
   } else cout << "Performing lineage scan..." << endl;
@@ -1060,7 +1060,7 @@
     batch[cur_batch].List().PushRear(found_list.Pop());
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  Lineage has " << total_kept << " genotypes; "
     << total_removed << " were removed." << endl;
   }
@@ -1087,7 +1087,7 @@
   cString parent_method = "rec_region_size";
   if (cur_string.CountNumWords() > 0) parent_method = cur_string.PopWord();
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Reducing batch " << cur_batch
     << " to " << lin_type << " sexual lineage " 
     << " using " << parent_method << " criteria." << endl;
@@ -1215,7 +1215,7 @@
     batch[cur_batch].List().PushRear(found_list.Pop());
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  Sexual lineage has " << total_kept << " genotypes; "
     << total_removed << " were removed." << endl;
   }
@@ -1234,7 +1234,7 @@
   
   cString clade_type( cur_string.PopWord() );
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Reducing batch " << cur_batch
     << " to clade " << clade_type << "." << endl;
   } else cout << "Performing clade scan..." << endl;
@@ -1288,7 +1288,7 @@
     batch[cur_batch].List().PushRear(found_list.Pop());
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  Clade has " << total_kept << " genotypes; "
     << total_removed << " were removed." << endl;
   }
@@ -1308,7 +1308,7 @@
     test_viable = cur_string.PopWord().AsDouble();
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Sampling " << fraction << " organisms from batch "
     << cur_batch << "." << endl;
   }
@@ -1375,7 +1375,7 @@
   }
   
   int num_genotypes = batch[cur_batch].List().GetSize();
-  if (verbose) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  Removed " << org_count - new_org_count
     << " organisms (" << init_genotypes - num_genotypes
     << " genotypes); " << new_org_count
@@ -1399,7 +1399,7 @@
     test_viable = cur_string.PopWord().AsDouble();
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Sampling " << fraction << " genotypes from batch "
     << cur_batch << "." << endl;
   }
@@ -1418,7 +1418,7 @@
   }
   
   int num_genotypes = batch[cur_batch].List().GetSize();
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  Removed " << init_genotypes - num_genotypes
     << " genotypes; " << num_genotypes << " remaining."
     << endl;
@@ -1450,7 +1450,7 @@
 
 void cAnalyze::CommandPrint(cString cur_string)
 {
-  if (verbose == true) cout << "Printing batch " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Printing batch " << cur_batch << endl;
   else cout << "Printing organisms..." << endl;
   
   cString directory = PopDirectory(cur_string, "genebank/");
@@ -1469,13 +1469,15 @@
     }
     
     cTestUtil::PrintGenome(genotype->GetGenome(), filename);
-    if (verbose) cout << "Printing: " << filename << endl;
+    if (verbose >= nAnalyze::VERBOSE_ON) {
+      cout << "Printing: " << filename << endl;
+    }
   }
 }
 
 void cAnalyze::CommandTrace(cString cur_string)
 {
-  if (verbose == true) cout << "Tracing batch " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Tracing batch " << cur_batch << endl;
   else cout << "Tracing organisms..." << endl;
   
   int words = cur_string.CountNumWords();
@@ -1528,7 +1530,7 @@
     
     cTestCPU::TestGenome(test_info, genotype->GetGenome());
     
-    if (verbose) cout << "  Tracing: " << filename << endl;
+    if (verbose >= nAnalyze::VERBOSE_ON) cout << "  Tracing: " << filename << endl;
     trace_fp.close();
   }
   
@@ -1543,7 +1545,7 @@
 
 void cAnalyze::CommandPrintTasks(cString cur_string)
 {
-  if (verbose == true) cout << "Printing tasks in batch " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Printing tasks in batch " << cur_batch << endl;
   else cout << "Printing tasks..." << endl;
   
   // Load in the variables...
@@ -1564,7 +1566,7 @@
 
 void cAnalyze::CommandDetail(cString cur_string)
 {
-  if (verbose == true) cout << "Detailing batch " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Detailing batch " << cur_batch << endl;
   else cout << "Detailing..." << endl;
   
   // Load in the variables...
@@ -1599,7 +1601,7 @@
 
 void cAnalyze::CommandDetailTimeline(cString cur_string)
 {
-  if (verbose == true) cout << "Detailing batch "
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Detailing batch "
     << cur_batch << " based on time" << endl;
   else cout << "Detailing..." << endl;
   
@@ -1611,7 +1613,7 @@
   if (cur_string.GetSize() != 0) time_step = cur_string.PopWord().AsInt();
   if (cur_string.GetSize() != 0) max_time = cur_string.PopWord().AsInt();
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  Time step = " << time_step << endl
     << "  Max time = " << max_time << endl;
   }
@@ -1703,6 +1705,12 @@
   
   int cur_time = 0;
   while (cur_genotype != NULL && cur_time <= max_time) {
+    if (verbose >= nAnalyze::VERBOSE_DETAILS) {
+      cout << "Detailing genotype " << cur_genotype->GetID()
+	   << " at depth " << cur_genotype->GetDepth()
+	   << endl;
+    }
+
     output_it.Reset();
     tDataEntryCommand<cAnalyzeGenotype> * data_command = NULL;
     if (format_type == FILE_TYPE_HTML) {
@@ -1794,7 +1802,7 @@
 
 void cAnalyze::CommandDetailAverage(cString cur_string) 
 { 
-  if (verbose == true) cout << "Average detailing batch " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Average detailing batch " << cur_batch << endl;
   else cout << "Detailing..." << endl;
   
   // Load in the variables...
@@ -1829,7 +1837,7 @@
   if (cur_string.GetSize() != 0) keyword = cur_string.PopWord();
   if (cur_string.GetSize() != 0) filename = cur_string.PopWord();
   
-  if (verbose == true) cout << "Detailing batches for " << keyword << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Detailing batches for " << keyword << endl;
   else cout << "Detailing Batches..." << endl;
   
   // Scan the functions list for the keyword we need...
@@ -2100,7 +2108,7 @@
 
 void cAnalyze::CommandHistogram(cString cur_string)
 {
-  if (verbose == true) cout << "Histogram batch " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Histogram batch " << cur_batch << endl;
   else cout << "Histograming..." << endl;
   
   // Load in the variables...
@@ -2274,7 +2282,7 @@
 
 void cAnalyze::CommandPrintPhenotypes(cString cur_string)
 {
-  if (verbose == true) cout << "Printing phenotypes in batch "
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Printing phenotypes in batch "
     << cur_batch << endl;
   else cout << "Printing phenotypes..." << endl;
   
@@ -2361,7 +2369,7 @@
 // Print various diversity metrics from the current batch of genotypes...
 void cAnalyze::CommandPrintDiversity(cString cur_string)
 {
-  if (verbose == true) cout << "Printing diversity data for batch "
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Printing diversity data for batch "
     << cur_batch << endl;
   else cout << "Printing diversity data..." << endl;
   
@@ -2468,9 +2476,7 @@
   int update = cur_string.PopWord().AsInt();
 
   // Get the directory  
-  cString dir = cur_string.PopWord();
-  cString defaultDir = "community_cpx/";
-  cString directory = PopDirectory(dir, defaultDir);
+  cString directory = PopDirectory(cur_string, "community_cpx/");
 
   // Get the file name that saves the result 
   cString filename = cur_string.PopWord();
@@ -2489,8 +2495,8 @@
   cpx_fp << "# 5: Total Complexity" << endl;
   cpx_fp << endl;
 
-  /////////////////////////////////////////////////////////////////////////////////
-  // Loop through all of the genotypes in all batches and build id vs. genotype map
+  ////////////////////////////////////////////////////////////////////////////
+  // Loop through all genotypes in all batches and build id vs. genotype map
 
   map<int, cAnalyzeGenotype *> genotype_database;
   for (int i = 0; i < MAX_BATCHES; ++ i) {
@@ -2771,7 +2777,7 @@
     vector<bool> one_line_neutral(num_insts, false);
     vector< vector<bool> > neutral_mut(length_genome, one_line_neutral);
     vector< vector<bool> > alive_mut(length_genome, one_line_neutral);
-//     if (verbose == true) {
+//     if (verbose >= nAnalyze::VERBOSE_ON) {
 //       PrintTestCPUResources("");
 //     }
 
@@ -3076,7 +3082,7 @@
     // Point mutation at all lines of code to look for neutral mutation
     cout << "Test point mutation for genotype " << genotype->GetID() << endl;
     tMatrix<double> prob(length_genome, num_insts);
-//     if (verbose == true) {
+//     if (verbose >= nAnalyze::VERBOSE_ON) {
 //       PrintTestCPUResources("");
 //     }
 
@@ -3292,7 +3298,7 @@
 
 void cAnalyze::CommandLandscape(cString cur_string)
 {
-  if (verbose == true) cout << "Landscaping batch " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Landscaping batch " << cur_batch << endl;
   else cout << "Landscapping..." << endl;
   
   // Load in the variables...
@@ -3319,7 +3325,7 @@
 
 void cAnalyze::AnalyzeEpistasis(cString cur_string)
 {
-  if (verbose == true) cout << "Epistasis on " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Epistasis on " << cur_batch << endl;
   else cout << "Calculating epistasis values..." << endl;
   
   // Load in the variables...
@@ -3545,7 +3551,7 @@
   if (cur_string.GetSize() > 0) del_mut_prob = cur_string.PopWord().AsDouble();
   if (cur_string.GetSize() > 0) count_threshold = cur_string.PopWord().AsInt();
 
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "...using:"
 	 << " filename='" << filename << "'"
 	 << " num_tests=" << num_tests
@@ -3636,14 +3642,14 @@
     
     // Calculate the complexities....
     genotype->Recalculate();
-    double start_complexity = genotype->GetComplexity();
+    double start_complexity = genotype->GetKO_Complexity(); // genotype->GetComplexity();
     double start_fitness = genotype->GetFitness();
     int start_length = genotype->GetLength();
     int start_gest = genotype->GetGestTime();
 
     cAnalyzeGenotype new_genotype(mod_genome, inst_set);
     new_genotype.Recalculate();
-    double end_complexity = new_genotype.GetComplexity();
+    double end_complexity = new_genotype.GetKO_Complexity();  // GetComplexity();
     double complexity_change = end_complexity - start_complexity;
     double end_fitness = new_genotype.GetFitness();
     int end_length = new_genotype.GetLength();
@@ -3699,7 +3705,7 @@
   tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
   cAnalyzeGenotype * genotype = NULL;
   while ((genotype = batch_it.Next()) != NULL) {
-    if (verbose == true) cout << "  Knockout: " << genotype->GetName() << endl;
+    if (verbose >= nAnalyze::VERBOSE_ON) cout << "  Knockout: " << genotype->GetName() << endl;
     
     // Calculate the stats for the genotype we're working with...
     genotype->Recalculate();
@@ -3710,10 +3716,12 @@
     cGenome mod_genome(base_genome);
     
     // Loop through all the lines of code, testing the removal of each.
+    // -2=lethal, -1=detrimental, 0=neutral, 1=beneficial
     int dead_count = 0;
     int neg_count = 0;
     int neut_count = 0;
     int pos_count = 0;
+    tArray<int> ko_effect(max_line);
     for (int line_num = 0; line_num < max_line; line_num++) {
       // Save a copy of the current instruction and replace it with "NULL"
       int cur_inst = base_genome[line_num].GetOp();
@@ -3722,21 +3730,85 @@
       ko_genotype.Recalculate();
       
       double ko_fitness = ko_genotype.GetFitness();
-      if (ko_fitness == 0.0) dead_count++;
-      else if (ko_fitness < base_fitness) neg_count++;
-      else if (ko_fitness == base_fitness) neut_count++;
-      else if (ko_fitness > base_fitness) pos_count++;
-      else cerr << "ERROR: illegal state in AnalyzeKnockouts()" << endl;
+      if (ko_fitness == 0.0) {
+	dead_count++;
+	ko_effect[line_num] = -2;
+      } else if (ko_fitness < base_fitness) {
+	neg_count++;
+	ko_effect[line_num] = -1;
+      } else if (ko_fitness == base_fitness) {
+	neut_count++;
+	ko_effect[line_num] = 0;
+      } else if (ko_fitness > base_fitness) {
+	pos_count++;
+	ko_effect[line_num] = 1;
+      } else {
+	cerr << "ERROR: illegal state in AnalyzeKnockouts()" << endl;
+      }
 
       // Reset the mod_genome back to the original sequence.
       mod_genome[line_num].SetOp(cur_inst);
     }
-    
+
+    tArray<int> ko_pair_effect(ko_effect);
+    if (max_knockouts > 1) {
+      for (int line1 = 0; line1 < max_line; line1++) {
+	for (int line2 = line1+1; line2 < max_line; line2++) {
+	  int cur_inst1 = base_genome[line1].GetOp();
+	  int cur_inst2 = base_genome[line2].GetOp();
+	  mod_genome[line1] = null_inst;
+	  mod_genome[line2] = null_inst;
+	  cAnalyzeGenotype ko_genotype(mod_genome, ko_inst_set);
+	  ko_genotype.Recalculate();
+      
+	  double ko_fitness = ko_genotype.GetFitness();
+
+	  // If both individual knockouts are both harmful, but in combination
+	  // they are neutral or even beneficial, they should not count as 
+	  // information.
+	  if (ko_fitness >= base_fitness &&
+	      ko_effect[line1] < 0 && ko_effect[line2] < 0) {
+	    ko_pair_effect[line1] = 0;
+	    ko_pair_effect[line2] = 0;
+	  }
+
+	  // If the individual knockouts are both neutral (or beneficial?),
+	  // but in combination they are harmful, they are likely redundant
+	  // to each other.  For now, count them both as information.
+	  if (ko_fitness < base_fitness &&
+	      ko_effect[line1] >= 0 && ko_effect[line2] >= 0) {
+	    ko_pair_effect[line1] = -1;
+	    ko_pair_effect[line2] = -1;
+	  }	
+
+	  // Reset the mod_genome back to the original sequence.
+	  mod_genome[line1].SetOp(cur_inst1);
+	  mod_genome[line2].SetOp(cur_inst2);
+	}
+      }
+    }    
+
+    int pair_dead_count = 0;
+    int pair_neg_count = 0;
+    int pair_neut_count = 0;
+    int pair_pos_count = 0;
+    for (int i = 0; i < max_line; i++) {
+      if (ko_pair_effect[i] == -2) pair_dead_count++;
+      else if (ko_pair_effect[i] == -1) pair_neg_count++;
+      else if (ko_pair_effect[i] == 0) pair_neut_count++;
+      else if (ko_pair_effect[i] == 1) pair_pos_count++;
+    }
+
+    // Output data...
     df.Write(genotype->GetID(), "Genotype ID");
     df.Write(dead_count, "Count of lethal knockouts");
     df.Write(neg_count,  "Count of detrimental knockouts");
     df.Write(neut_count, "Count of neutral knockouts");
     df.Write(pos_count,  "Count of beneficial knockouts");
+    df.Write(pair_dead_count, "Count of lethal knockouts after paired knockout tests.");
+    df.Write(pair_neg_count,  "Count of detrimental knockouts after paired knockout tests.");
+    df.Write(pair_neut_count, "Count of neutral knockouts after paired knockout tests.");
+    df.Write(pair_pos_count,  "Count of beneficial knockouts after paired knockout tests.");
     df.Endl();
   }
 }
@@ -3744,7 +3816,7 @@
   
 void cAnalyze::CommandFitnessMatrix(cString cur_string)
 {
-  if (verbose == true) cout << "Calculating fitness matrix for batch " << cur_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Calculating fitness matrix for batch " << cur_batch << endl;
   else cout << "Calculating fitness matrix..." << endl;
   
   cout << "Warning: considering only first genotype of the batch!" << endl;
@@ -3831,7 +3903,7 @@
   const int num_cols = output_list.GetSize();
   
   // Give some information in verbose mode.
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  outputing as ";
     if (print_mode == 1) cout << "boolean ";
     if (file_type == FILE_TYPE_TEXT) {
@@ -3858,7 +3930,7 @@
   tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
   cAnalyzeGenotype * genotype = NULL;
   while ((genotype = batch_it.Next()) != NULL) {
-    if (verbose == true) cout << "  Mapping " << genotype->GetName() << endl;
+    if (verbose >= nAnalyze::VERBOSE_ON) cout << "  Mapping " << genotype->GetName() << endl;
     
     // Construct this filename...
     cString filename;
@@ -4105,7 +4177,7 @@
   const int num_cols = output_list.GetSize();
   
   // Give some information in verbose mode.
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  outputing as ";
     if (print_mode == 1) cout << "boolean ";
     cout << "text files." << endl;
@@ -4190,7 +4262,7 @@
     
     int num_cpus = genotype->GetNumCPUs();
     
-    if (verbose == true) cout << "  Mapping " << genotype->GetName() << endl;
+    if (verbose >= nAnalyze::VERBOSE_ON) cout << "  Mapping " << genotype->GetName() << endl;
     
     // Calculate the stats for the genotype we're working with...
     genotype->Recalculate();
@@ -4457,7 +4529,7 @@
   if (arg_list.PopString("html") != "") file_type = FILE_TYPE_HTML;
   
   // Give some information in verbose mode.
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "  outputing as ";
     if (file_type == FILE_TYPE_TEXT) cout << "text files." << endl;
     else cout << "HTML files." << endl;
@@ -4470,7 +4542,7 @@
   tListIterator<cAnalyzeGenotype> batch_it(batch[cur_batch].List());
   cAnalyzeGenotype * genotype = NULL;
   while ((genotype = batch_it.Next()) != NULL) {
-    if (verbose == true) {
+    if (verbose >= nAnalyze::VERBOSE_ON) {
       cout << "  Creating mutation map for " << genotype->GetName() << endl;
     }
     
@@ -4765,7 +4837,7 @@
     int tmp = batch1;  batch1 = batch2;  batch2 = tmp;
   }
   
-  if (verbose == false) {
+  if (verbose <= nAnalyze::VERBOSE_QUIET) {
     cout << "Calculating Hamming Distance... ";
     cout.flush();
   } else {
@@ -4832,7 +4904,7 @@
     int tmp = batch1;  batch1 = batch2;  batch2 = tmp;
   }
   
-  if (verbose == false) {
+  if (verbose <= nAnalyze::VERBOSE_QUIET) {
     cout << "Calculating Levenstein Distance... ";
     cout.flush();
   } else {
@@ -4899,7 +4971,7 @@
     int tmp = batch1;  batch1 = batch2;  batch2 = tmp;
   }
   
-  if (verbose == false) cout << "Calculating Species Distance... " << endl;
+  if (verbose <= nAnalyze::VERBOSE_QUIET) cout << "Calculating Species Distance... " << endl;
   else cout << "Calculating Species Distance between batch "
     << batch1 << " and " << batch2 << endl;
   
@@ -5015,7 +5087,7 @@
     int tmp = batch1;  batch1 = batch2;  batch2 = tmp;
   }
   
-  if (verbose == false) cout << "Creating recombinants...  " << endl;
+  if (verbose <= nAnalyze::VERBOSE_QUIET) cout << "Creating recombinants...  " << endl;
   else cout << "Creating recombinants between batch "
     << batch1 << " and " << batch2 << endl;
   
@@ -5109,7 +5181,7 @@
   
   cout << "Aligning sequences..." << endl;
   
-  if (batch[cur_batch].IsLineage() == false && verbose == true) {
+  if (batch[cur_batch].IsLineage() == false && verbose >= nAnalyze::VERBOSE_ON) {
     cerr << "  Warning: sequences may not be a consecutive lineage."
     << endl;
   }
@@ -5230,7 +5302,7 @@
 
   while ((child_genotype = batch_it.Next()) != NULL) {
     
-    if (verbose == true) {
+    if (verbose >= nAnalyze::VERBOSE_ON) {
       cout << "Analyze new information for " << child_genotype->GetName() << endl;
     }
     
@@ -5418,7 +5490,7 @@
     for (grid_side = 5; grid_side < 100; grid_side += 5) {
       if (grid_side * grid_side >= max_count) break;
     }
-    if (verbose == true) {
+    if (verbose >= nAnalyze::VERBOSE_ON) {
       cout << "...assuming population size "
       << grid_side << "x" << grid_side << "." << endl;
     }
@@ -5531,7 +5603,7 @@
   
   // Count the number of diffs between the two strings we're interested in.
   const int total_diffs = cStringUtil::Distance(first_seq, last_seq);
-  if (verbose) cout << "  " << total_diffs << " mutations being tested."
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "  " << total_diffs << " mutations being tested."
     << endl;
   
   // Locate each difference.
@@ -5653,7 +5725,7 @@
 
 void cAnalyze::AnalyzeInstructions(cString cur_string)
 {
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Analyzing Instructions in batch " << cur_batch << endl;
   }
   else cout << "Analyzeing Instructions..." << endl;
@@ -5793,7 +5865,7 @@
 
 void cAnalyze::AnalyzeInstPop(cString cur_string)
 {
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Analyzing Instructions in batch " << cur_batch << endl;
   }
   else cout << "Analyzeing Instructions..." << endl;
@@ -5851,7 +5923,7 @@
 
 void cAnalyze::AnalyzeBranching(cString cur_string)
 {
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Analyzing branching patterns in batch " << cur_batch << endl;
   }
   else cout << "Analyzeing Branches..." << endl;
@@ -5869,13 +5941,13 @@
 
 void cAnalyze::AnalyzeMutationTraceback(cString cur_string)
 {
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Analyzing mutation traceback in batch " << cur_batch << endl;
   }
   else cout << "Analyzing mutation traceback..." << endl;
   
   // This works best on lineages, so warn if we don't have one.
-  if (batch[cur_batch].IsLineage() == false && verbose == true) {
+  if (batch[cur_batch].IsLineage() == false && verbose >= nAnalyze::VERBOSE_ON) {
     cerr << "  Warning: trying to traceback mutations outside of lineage."
     << endl;
   }
@@ -6034,7 +6106,7 @@
   }
   
   while ((genotype = batch_it.Next()) != NULL) {
-    if (verbose == true) {
+    if (verbose >= nAnalyze::VERBOSE_ON) {
       cout << "  Analyzing complexity for " << genotype->GetName() << endl;
     }
     
@@ -6154,7 +6226,7 @@
     // where i is the batchFrequency
     for(int count=0; genotype != NULL && count < batchFrequency - 1; count++) {
       genotype = batch_it.Next();
-      if(genotype != NULL && verbose == true) {
+      if(genotype != NULL && verbose >= nAnalyze::VERBOSE_ON) {
         cout << "Skipping: " << genotype->GetName() << endl;
       }
     }
@@ -6287,7 +6359,7 @@
   cout << "Printing helpfiles in: " << cur_string << endl;
   
   cHelpManager help_control;
-  if (verbose == true) help_control.SetVerbose();
+  if (verbose >= nAnalyze::VERBOSE_ON) help_control.SetVerbose();
   while (cur_string.GetSize() > 0) {
     help_control.LoadFile(cur_string.PopWord());
   }
@@ -6300,7 +6372,7 @@
   cout << "Printing documentation files in: " << cur_string << endl;
   
   cHelpManager help_control;
-  if (verbose == true) help_control.SetVerbose();
+  if (verbose >= nAnalyze::VERBOSE_ON) help_control.SetVerbose();
   while (cur_string.GetSize() > 0) {
     help_control.LoadFile(cur_string.PopWord());
   }
@@ -6324,7 +6396,7 @@
   cString & cur_variable = GetVariable(var);
   cur_variable = cur_string.PopWord();
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Setting " << var << " to " << cur_variable << endl;
   }
 }
@@ -6335,7 +6407,7 @@
   if (cur_string.CountNumWords() > 0) {
     next_batch = cur_string.PopWord().AsInt();
   }
-  if (verbose) cout << "Setting current batch to " << next_batch << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Setting current batch to " << next_batch << endl;
   if (next_batch >= MAX_BATCHES) {
     cerr << "  Error: max batches is " << MAX_BATCHES << endl;
     exit(1);
@@ -6347,7 +6419,7 @@
 void cAnalyze::BatchName(cString cur_string)
 {
   if (cur_string.CountNumWords() == 0) {
-    if (verbose) cout << "  Warning: No name given in NAME_BATCH!" << endl;
+    if (verbose >= nAnalyze::VERBOSE_ON) cout << "  Warning: No name given in NAME_BATCH!" << endl;
     return;
   }
   
@@ -6357,11 +6429,11 @@
 void cAnalyze::BatchTag(cString cur_string)
 {
   if (cur_string.CountNumWords() == 0) {
-    if (verbose) cout << "  Warning: No tag given in TAG_BATCH!" << endl;
+    if (verbose >= nAnalyze::VERBOSE_ON) cout << "  Warning: No tag given in TAG_BATCH!" << endl;
     return;
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Tagging batch " << cur_batch
     << " with tag '" << cur_string << "'" << endl;
   }
@@ -6379,7 +6451,7 @@
   int batch_id = cur_batch;
   if (cur_string.CountNumWords() > 0) batch_id = cur_string.PopWord().AsInt();
   
-  if (verbose) cout << "Purging batch " << batch_id << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Purging batch " << batch_id << endl;
   
   while (batch[batch_id].List().GetSize() > 0) {
     delete batch[batch_id].List().Pop();
@@ -6400,7 +6472,7 @@
   int batch_to = cur_batch;
   if (cur_string.GetSize() > 0) batch_to = cur_string.PopWord().AsInt();
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Duplicating from batch " << batch_from
     << " to batch " << batch_to << "." << endl;
   }
@@ -6443,11 +6515,11 @@
     cTestCPU::UseResources() = true;
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Running batch " << cur_batch << " through test CPUs..." << endl;
   } else cout << "Running through test CPUs..." << endl;
   
-  if (verbose == true && batch[cur_batch].IsLineage() == false) {
+  if (verbose >= nAnalyze::VERBOSE_ON && batch[cur_batch].IsLineage() == false) {
     cerr << "  Warning: batch may not be a linege; "
     << "parent and ancestor distances may not be correct" << endl;
   }
@@ -6470,7 +6542,7 @@
     
     // If the previous genotype was the parent of this one, pass in a pointer
     // to it for improved recalculate (such as distance to parent, etc.)
-//     if (verbose == true) {
+//     if (verbose >= nAnalyze::VERBOSE_ON) {
 //       PrintTestCPUResources("");
 //     }
     if (last_genotype != NULL &&
@@ -6492,7 +6564,7 @@
 
 void cAnalyze::BatchRename(cString cur_string)
 {
-  if (verbose == false) cout << "Renaming organisms..." << endl;
+  if (verbose <= nAnalyze::VERBOSE_QUIET) cout << "Renaming organisms..." << endl;
   else cout << "Renaming organisms in batch " << cur_batch << endl;
   
   // If a number is given with rename, start at that number...
@@ -6532,17 +6604,33 @@
   cerr << "Debug Args: " << cur_string << endl;
 }
 
-void cAnalyze::ToggleVerbose(cString cur_string)
+void cAnalyze::CommandVerbose(cString cur_string)
 {
-  // No Args needed...
-  (void) cur_string;
+  cur_string.ToUpper();
+
+  // If no arguments are given, assume a basic toggle.
+  if (cur_string.GetSize() == 0 && verbose <= nAnalyze::VERBOSE_QUIET) {
+    verbose = nAnalyze::VERBOSE_ON;
+  }
+  else if (cur_string.GetSize() == 0 && verbose >= nAnalyze::VERBOSE_ON) {
+    verbose = nAnalyze::VERBOSE_QUIET;
+  }
+
+  // Otherwise, read in the argument to decide the new mode.
+  else if (cur_string == "SILENT") verbose = nAnalyze::VERBOSE_SILENT;
+  else if (cur_string == "QUIET") verbose = nAnalyze::VERBOSE_QUIET;
+  else if (cur_string == "OFF") verbose = nAnalyze::VERBOSE_QUIET;
+  else if (cur_string == "ON") verbose = nAnalyze::VERBOSE_ON;
+  else if (cur_string == "DETAILS") verbose = nAnalyze::VERBOSE_DETAILS;
+  else if (cur_string == "HIGH") verbose = nAnalyze::VERBOSE_DETAILS;
   
-  if (verbose == false) {
-    cout << "Using verbose log messages..." << endl;
-    verbose = true;
-  } else {
-    cout << "Using non-verbose log messages..." << endl;
-    verbose = false;
+  // Print out new verbose level (nothing for silent!)
+  if (verbose == nAnalyze::VERBOSE_QUIET) {
+    cout << "Verbose QUIET: Using minimal log messages..." << endl;
+  } else if (verbose == nAnalyze::VERBOSE_ON) {
+    cout << "Verbose ON: Using verbose log messages..." << endl;
+  } else if (verbose == nAnalyze::VERBOSE_DETAILS) {
+    cout << "Verbose DETAILS: Using detailed log messages..." << endl;
   }
 }
 
@@ -6609,7 +6697,7 @@
     exit(1);
   }
   
-  if (verbose) cout << "Creating function: " << fun_name << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Creating function: " << fun_name << endl;
   
   // Create the new function...
   cAnalyzeFunction * new_function = new cAnalyzeFunction(fun_name);
@@ -6623,7 +6711,7 @@
 
 bool cAnalyze::FunctionRun(const cString & fun_name, cString args)
 {
-  if (verbose) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Running function: " << fun_name << endl;
     // << " with args: " << args << endl;
   }
@@ -6681,7 +6769,7 @@
 void cAnalyze::CommandForeach(cString cur_string,
                               tList<cAnalyzeCommand> & clist)
 {
-  if (verbose) cout << "Initiating Foreach loop..." << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) cout << "Initiating Foreach loop..." << endl;
   
   cString var = cur_string.PopWord();
   int num_args = cur_string.CountNumWords();
@@ -6691,13 +6779,13 @@
   for (int i = 0; i < num_args; i++) {
     cur_variable = cur_string.PopWord();
     
-    if (verbose == true) {
+    if (verbose >= nAnalyze::VERBOSE_ON) {
       cout << "Foreach: setting " << var << " to " << cur_variable << endl;
     }
     ProcessCommands(clist);
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Ending Foreach on " << var << endl;
   }
 }
@@ -6706,7 +6794,9 @@
 void cAnalyze::CommandForRange(cString cur_string,
                                tList<cAnalyzeCommand> & clist)
 {
-  if (verbose) cout << "Initiating FORRANGE loop..." << endl;
+  if (verbose >= nAnalyze::VERBOSE_ON) {
+    cout << "Initiating FORRANGE loop..." << endl;
+  }
   
   int num_args = cur_string.CountNumWords();
   if (num_args < 3) {
@@ -6730,7 +6820,7 @@
     for (int i = (int) min_val; i <= (int) max_val; i += (int) step_val) {
       cur_variable.Set("%d", i);
       
-      if (verbose == true) {
+      if (verbose >= nAnalyze::VERBOSE_ON) {
         cout << "FORRANGE: setting " << var << " to " << cur_variable << endl;
       }
       ProcessCommands(clist);
@@ -6739,14 +6829,14 @@
     for (double i = min_val; i <= max_val; i += step_val) {
       cur_variable.Set("%f", i);
       
-      if (verbose == true) {
+      if (verbose >= nAnalyze::VERBOSE_ON) {
         cout << "FORRANGE: setting " << var << " to " << cur_variable << endl;
       }
       ProcessCommands(clist);
     }
   }
   
-  if (verbose == true) {
+  if (verbose >= nAnalyze::VERBOSE_ON) {
     cout << "Ending FORRANGE on " << var << endl;
   }
 }
@@ -7079,6 +7169,14 @@
                               ("complexity",   "Basic Complexity (all neutral/beneficial muts are equal)",
                                &cAnalyzeGenotype::GetComplexity,
                                (void (cAnalyzeGenotype::*)(double)) NULL));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+                              ("ko_complexity", "Complexity calculated by counting sites you can't knockout",
+                               &cAnalyzeGenotype::GetKO_Complexity,
+                               (void (cAnalyzeGenotype::*)(int)) NULL));
+  genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, int>
+                              ("ko_pair_complexity", "Count of sites you can't knockout (including epistatic effects)",
+                               &cAnalyzeGenotype::GetKOPair_Complexity,
+                               (void (cAnalyzeGenotype::*)(int)) NULL));
   genotype_data_list.PushRear(new tDataEntry<cAnalyzeGenotype, const cString &>
                               ("parent_muts", "Mutations from Parent",
                                &cAnalyzeGenotype::GetParentMuts, &cAnalyzeGenotype::SetParentMuts,
@@ -7319,7 +7417,7 @@
   AddLibraryDef("STATUS", &cAnalyze::PrintStatus);
   AddLibraryDef("DEBUG", &cAnalyze::PrintDebug);
   AddLibraryDef("ECHO", &cAnalyze::PrintDebug);
-  AddLibraryDef("VERBOSE", &cAnalyze::ToggleVerbose);
+  AddLibraryDef("VERBOSE", &cAnalyze::CommandVerbose);
   AddLibraryDef("INCLUDE", &cAnalyze::IncludeFile);
   AddLibraryDef("SYSTEM", &cAnalyze::CommandSystem);
   AddLibraryDef("INTERACTIVE", &cAnalyze::CommandInteractive);

Modified: trunk/source/main/cAnalyze.h
===================================================================
--- trunk/source/main/cAnalyze.h	2005-11-10 21:50:26 UTC (rev 389)
+++ trunk/source/main/cAnalyze.h	2005-11-11 03:43:36 UTC (rev 390)
@@ -31,6 +31,13 @@
 
 #define MAX_BATCHES 2000
 
+namespace nAnalyze {
+  const int VERBOSE_SILENT  = 0;  // No output at all
+  const int VERBOSE_QUIET   = 1;  // Notification at start of commands.
+  const int VERBOSE_ON      = 2;  // Verbose output, detailing progress
+  const int VERBOSE_DETAILS = 3;  // High level of details, as available.
+}
+
 // cAnalyze            : The master analyze object.
 
 class cGenotypeBatch; // array
@@ -67,7 +74,7 @@
   // is a pair of the update and a vector of the resource concentrations
   std::vector<std::pair<int, std::vector<double> > > resources;
 
-  bool verbose;            // Should details be output to command line?
+  int verbose;             // How much information to print?
   int interactive_depth;   // How nested are we if in interactive mode?
 
   cDataFileManager data_file_manager;
@@ -212,7 +219,7 @@
   void BatchRename(cString cur_string);
   void PrintStatus(cString cur_string);
   void PrintDebug(cString cur_string);
-  void ToggleVerbose(cString cur_string);
+  void CommandVerbose(cString cur_string);
   void IncludeFile(cString cur_string);
   void CommandSystem(cString cur_string);
   void CommandInteractive(cString cur_string);

Modified: trunk/source/main/cAnalyzeGenotype.cc
===================================================================
--- trunk/source/main/cAnalyzeGenotype.cc	2005-11-10 21:50:26 UTC (rev 389)
+++ trunk/source/main/cAnalyzeGenotype.cc	2005-11-11 03:43:36 UTC (rev 390)
@@ -51,6 +51,7 @@
   , parent_dist(0)
   , ancestor_dist(0)
   , parent_muts("")
+  , knockout_stats(NULL)
   , landscape_stats(NULL)
 {
   // Make sure that the sequences jive with the inst_set
@@ -93,6 +94,7 @@
   , parent_dist(0)
   , ancestor_dist(0)
   , parent_muts("")
+  , knockout_stats(NULL)
   , landscape_stats(NULL)
 {
 }
@@ -126,8 +128,13 @@
   , parent_dist(_gen.parent_dist)
   , ancestor_dist(_gen.ancestor_dist)
   , parent_muts(_gen.parent_muts)
+  , knockout_stats(NULL)
   , landscape_stats(NULL)
 {
+  if (_gen.knockout_stats != NULL) {
+    knockout_stats = new cAnalyzeKnockouts;
+    *knockout_stats = *(_gen.knockout_stats);
+  }
   if (_gen.landscape_stats != NULL) {
     landscape_stats = new cAnalyzeLandscape;
     *landscape_stats = *(_gen.landscape_stats);
@@ -136,6 +143,7 @@
 
 cAnalyzeGenotype::~cAnalyzeGenotype()
 {
+  if (knockout_stats != NULL) delete knockout_stats;
   if (landscape_stats != NULL) delete landscape_stats;
 }
 
@@ -145,6 +153,150 @@
   return cConfig::GetTestCPUTimeMod() * genome.GetSize();
 }
 
+void cAnalyzeGenotype::CalcKnockouts(bool check_pairs) const
+{
+  if (knockout_stats == NULL) {
+    // We've never called this before -- setup the stats.
+    knockout_stats = new cAnalyzeKnockouts;
+  }
+  else if (check_pairs == true && knockout_stats->has_pair_info == false) {
+    // We don't have the pair stats we need -- keep going.
+    knockout_stats->Reset();
+  }
+  else {
+    // We already have all the info we need -- just quit.
+    return;
+  }
+  
+  // Calculate the base fitness for the genotype we're working with...
+  // (This may not have been run already, and cost negligiably more time
+  // considering the number of knockouts we need to do.
+  cAnalyzeGenotype base_genotype(genome, inst_set);
+  base_genotype.Recalculate();      
+  double base_fitness = base_genotype.GetFitness();
+
+  // If the base fitness is 0, the organism is dead and has no complexity.
+  if (base_fitness == 0.0) {
+    knockout_stats->neut_count == length;
+    return;
+  }
+
+  cGenome mod_genome(genome);
+    
+  // Setup a NULL instruction in a special inst set.
+  cInstSet ko_inst_set(inst_set);
+  // Locate the instruction corresponding to "NULL" in the instruction library.
+  {
+    cInstruction lib_null_inst = ko_inst_set.GetInstLib()->GetInst("NULL");
+    if (lib_null_inst == ko_inst_set.GetInstLib()->GetInstError()) {
+      cout << "<cAnalyze::AnalyzeKnockouts> got error:" << endl
+	   << "  instruction 'NULL' not in current hardware type" << endl;
+      exit(1);
+    }
+    // Add mapping to located instruction. 
+    ko_inst_set.Add2(lib_null_inst.GetOp());
+  }
+  const cInstruction null_inst = ko_inst_set.GetInst("NULL");
+    
+  // Loop through all the lines of code, testing the removal of each.
+  // -2=lethal, -1=detrimental, 0=neutral, 1=beneficial
+  tArray<int> ko_effect(length);
+  for (int line_num = 0; line_num < length; line_num++) {
+    // Save a copy of the current instruction and replace it with "NULL"
+    int cur_inst = mod_genome[line_num].GetOp();
+    mod_genome[line_num] = null_inst;
+    cAnalyzeGenotype ko_genotype(mod_genome, ko_inst_set);
+    ko_genotype.Recalculate();
+      
+    double ko_fitness = ko_genotype.GetFitness();
+    if (ko_fitness == 0.0) {
+      knockout_stats->dead_count++;
+      ko_effect[line_num] = -2;
+    } else if (ko_fitness < base_fitness) {
+      knockout_stats->neg_count++;
+      ko_effect[line_num] = -1;
+    } else if (ko_fitness == base_fitness) {
+      knockout_stats->neut_count++;
+      ko_effect[line_num] = 0;
+    } else if (ko_fitness > base_fitness) {
+      knockout_stats->pos_count++;
+      ko_effect[line_num] = 1;
+    } else {
+      cerr << "INTERNAL ERROR: illegal state in CalcKnockouts()" << endl;
+    }
+
+    // Reset the mod_genome back to the original sequence.
+    mod_genome[line_num].SetOp(cur_inst);
+  }
+
+  // Only continue from here if we are looking at all pairs of knockouts
+  // as well.
+  if (check_pairs == false) return;
+
+  tArray<int> ko_pair_effect(ko_effect);
+  for (int line1 = 0; line1 < length; line1++) {
+    // If this line has already been changed, keep going...
+    if (ko_effect[line1] != ko_pair_effect[line1]) continue;
+
+    // Loop through all possibilities for the next line.
+    for (int line2 = line1+1; line2 < length; line2++) {
+      // If this line has already been changed, keep going...
+      if (ko_effect[line2] != ko_pair_effect[line2]) continue;
+
+      // If the two lines are of different types (one is information and the
+      // other is not) then we're not interested in testing this combination
+      // since any possible result is reasonable.
+      if ((ko_effect[line1] < 0 && ko_effect[line2] >= 0) ||
+	  (ko_effect[line1] >= 0 && ko_effect[line2] < 0)) {
+	continue;
+      }
+      
+      // Calculate the fitness for this pair of knockouts to determine if its
+      // something other than what we expected.
+
+      int cur_inst1 = mod_genome[line1].GetOp();
+      int cur_inst2 = mod_genome[line2].GetOp();
+      mod_genome[line1] = null_inst;
+      mod_genome[line2] = null_inst;
+      cAnalyzeGenotype ko_genotype(mod_genome, ko_inst_set);
+      ko_genotype.Recalculate();
+      
+      double ko_fitness = ko_genotype.GetFitness();
+      
+      // If the individual knockouts are both harmful, but in combination
+      // they are neutral or even beneficial, they should not count as 
+      // information.
+      if (ko_fitness >= base_fitness &&
+	  ko_effect[line1] < 0 && ko_effect[line2] < 0) {
+	ko_pair_effect[line1] = 0;
+	ko_pair_effect[line2] = 0;
+      }
+      
+      // If the individual knockouts are both neutral (or beneficial?),
+      // but in combination they are harmful, they are likely redundant
+      // to each other.  For now, count them both as information.
+      if (ko_fitness < base_fitness &&
+	  ko_effect[line1] >= 0 && ko_effect[line2] >= 0) {
+	ko_pair_effect[line1] = -1;
+	ko_pair_effect[line2] = -1;
+      }	
+      
+      // Reset the mod_genome back to the original sequence.
+      mod_genome[line1].SetOp(cur_inst1);
+      mod_genome[line2].SetOp(cur_inst2);
+    }
+  }
+
+  for (int i = 0; i < length; i++) {
+    if (ko_pair_effect[i] == -2) knockout_stats->pair_dead_count++;
+    else if (ko_pair_effect[i] == -1) knockout_stats->pair_neg_count++;
+    else if (ko_pair_effect[i] == 0) knockout_stats->pair_neut_count++;
+    else if (ko_pair_effect[i] == 1) knockout_stats->pair_pos_count++;
+  }
+  
+  knockout_stats->has_pair_info = true;
+}
+
 void cAnalyzeGenotype::CalcLandscape() const
 {
   if (landscape_stats != NULL) return;
@@ -222,6 +374,68 @@
 }
 
 
+int cAnalyzeGenotype::GetKO_DeadCount() const
+{
+  CalcKnockouts(false);  // Make sure knockouts are calculated
+  return knockout_stats->dead_count;
+}
+
+int cAnalyzeGenotype::GetKO_NegCount() const
+{
+  CalcKnockouts(false);  // Make sure knockouts are calculated
+  return knockout_stats->neg_count;
+}
+
+int cAnalyzeGenotype::GetKO_NeutCount() const
+{
+  CalcKnockouts(false);  // Make sure knockouts are calculated
+  return knockout_stats->neut_count;
+}
+
+int cAnalyzeGenotype::GetKO_PosCount() const
+{
+  CalcKnockouts(false);  // Make sure knockouts are calculated
+  return knockout_stats->pos_count;
+}
+
+int cAnalyzeGenotype::GetKO_Complexity() const
+{
+  CalcKnockouts(false);  // Make sure knockouts are calculated
+  return knockout_stats->dead_count + knockout_stats->neg_count;
+}
+
+int cAnalyzeGenotype::GetKOPair_DeadCount() const
+{
+  CalcKnockouts(true);  // Make sure knockouts are calculated
+  return knockout_stats->pair_dead_count;
+}
+
+int cAnalyzeGenotype::GetKOPair_NegCount() const
+{
+  CalcKnockouts(true);  // Make sure knockouts are calculated
+  return knockout_stats->pair_neg_count;
+}
+
+int cAnalyzeGenotype::GetKOPair_NeutCount() const
+{
+  CalcKnockouts(true);  // Make sure knockouts are calculated
+  return knockout_stats->pair_neut_count;
+}
+
+int cAnalyzeGenotype::GetKOPair_PosCount() const
+{
+  CalcKnockouts(true);  // Make sure knockouts are calculated
+  return knockout_stats->pair_pos_count;
+}
+
+int cAnalyzeGenotype::GetKOPair_Complexity() const
+{
+  CalcKnockouts(true);  // Make sure knockouts are calculated
+  return knockout_stats->pair_dead_count + knockout_stats->pair_neg_count;
+}
+
+
+
 double cAnalyzeGenotype::GetFracDead() const
 {
   CalcLandscape();  // Make sure the landscape is calculated...

Modified: trunk/source/main/cAnalyzeGenotype.h
===================================================================
--- trunk/source/main/cAnalyzeGenotype.h	2005-11-10 21:50:26 UTC (rev 389)
+++ trunk/source/main/cAnalyzeGenotype.h	2005-11-11 03:43:36 UTC (rev 390)
@@ -81,6 +81,35 @@
   cString parent_muts;
 
   // Group 4 : Landscape stats (obtained from testing all possible mutations)
+  class cAnalyzeKnockouts {
+  public:
+    int dead_count;
+    int neg_count;
+    int neut_count;
+    int pos_count;
+
+    bool has_pair_info;
+    int pair_dead_count;
+    int pair_neg_count;
+    int pair_neut_count;
+    int pair_pos_count;
+
+    void Reset() {
+      dead_count = 0;
+      neg_count = 0;
+      neut_count = 0;
+      pos_count = 0;
+
+      has_pair_info = false;
+      pair_dead_count = 0;
+      pair_neg_count = 0;
+      pair_neut_count = 0;
+      pair_pos_count = 0;
+    }
+
+    cAnalyzeKnockouts() { Reset(); }
+  };
+
   class cAnalyzeLandscape {
   public:
     double frac_dead;
@@ -92,6 +121,7 @@
 			  frac_neut(0.0), frac_pos(0.0),
 			  complexity(0.0) { ; }
   };
+  mutable cAnalyzeKnockouts * knockout_stats;
   mutable cAnalyzeLandscape * landscape_stats;
 
   // Group 5 : More complex stats (obtained indvidually, through tests)
@@ -109,6 +139,7 @@
   }
 
   int CalcMaxGestation() const;
+  void CalcKnockouts(bool check_pairs=false) const;
   void CalcLandscape() const;
 public:
   cAnalyzeGenotype(cString symbol_string, cInstSet & in_inst_set);
@@ -194,6 +225,18 @@
 
   const cString & GetParentMuts() const { return parent_muts; }
 
+  // Knockout accessors
+  int GetKO_DeadCount() const;
+  int GetKO_NegCount() const;
+  int GetKO_NeutCount() const;
+  int GetKO_PosCount() const;
+  int GetKO_Complexity() const;
+  int GetKOPair_DeadCount() const;
+  int GetKOPair_NegCount() const;
+  int GetKOPair_NeutCount() const;
+  int GetKOPair_PosCount() const;
+  int GetKOPair_Complexity() const;
+
   // Landscape accessors
   double GetFracDead() const;
   double GetFracNeg() const;

Modified: trunk/source/main/cLandscape.cc
===================================================================
--- trunk/source/main/cLandscape.cc	2005-11-10 21:50:26 UTC (rev 389)
+++ trunk/source/main/cLandscape.cc	2005-11-11 03:43:36 UTC (rev 390)
@@ -113,7 +113,7 @@
   cTestCPU::TestGenome(test_info, base_genome);
 
   cPhenotype & phenotype = test_info.GetColonyOrganism()->GetPhenotype();
-  base_fitness = phenotype.GetFitness();
+  base_fitness = test_info.GetColonyFitness(); // phenotype.GetFitness();
   base_merit = phenotype.GetMerit().GetDouble();
   base_gestation = phenotype.GetGestationTime();
    
@@ -331,6 +331,7 @@
   // Calculate the complexity...
 
   double max_ent = log((double) inst_set.GetSize());
+  total_entropy = 0;
   for (int i = 0; i < base_genome.GetSize(); i++) {
     total_entropy += (log((double) site_count[i] + 1) / max_ent);
   }
@@ -464,6 +465,7 @@
   // Calculate the complexity...
 
   double max_ent = log((double) inst_set.GetSize());
+  total_entropy = 0;
   for (int i = 0; i < base_genome.GetSize(); i++) {
     total_entropy += (log((double) site_count[i] + 1) / max_ent);
   }
@@ -863,4 +865,3 @@
 {
   cTestUtil::PrintGenome(peak_genome, filename);
 }
-




More information about the Avida-cvs mailing list