Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PackDaemon.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file protocols/pack_daemon/PackDaemon.cc
11 /// @brief Implementation for class PackDaemon
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 /// MPI Headers
15 #ifdef USEMPI
16 #include <mpi.h>
17 #endif
18 
19 // Unit headers
21 
22 // Package headers
24 
25 // Project headers
26 // AUTO-REMOVED #include <protocols/multistate_design/SingleState.hh> // REQUIRED FOR WINDOWS
28 
29 #ifdef USEMPI
30 #include <core/io/pdb/pose_io.hh>
31 #endif
33 #include <core/pose/Pose.hh>
34 #include <core/scoring/Energies.hh>
43 //#include <core/pack/interaction_graph/LazyInteractionGraph.hh>
51 #include <basic/Tracer.hh>
52 
54 
55 #include <utility/exit.hh>
56 #include <utility/integer_mapping.hh>
57 #include <utility/string_util.hh>
58 #include <utility/io/izstream.hh>
59 #include <utility/excn/Exceptions.hh>
60 
63 #include <utility/vector0.hh>
64 #include <utility/vector1.hh>
65 
66 #ifdef USEMPI
67 #include <utility/mpi_util.hh>
68 #endif
69 
70 
71 namespace protocols {
72 namespace pack_daemon {
73 
74 static basic::Tracer TR("protocols.pack_daemon.PackDaemon");
75 
77  include_background_energies_( true ),
78  background_energies_( 0.0 ),
79  setup_complete_( false ),
80  best_assignment_valid_( false )
81 {
82  best_assignment_.second = 12345;
83  last_assignment_.second = 12345;
84 }
85 
87 
88 // Initialize the PackDaemon with the appropriate data before
89 // calling setup().
90 void PackDaemon::set_pose_and_task( Pose const & pose, PackerTask const & task )
91 {
92  pose_ = new Pose( pose );
93  task_ = task.clone();
94  for ( Size ii = 1; ii <= task.total_residue(); ++ii ) {
95  task_->nonconst_residue_task( ii ).and_extrachi_cutoff( 1 );
96  }
97  task_->or_double_lazy_ig( true );
98  task_->set_bump_check( false ); /// bump check must be disabled.
99  setup_complete_ = false;
100 }
101 
103 {
104  score_function_ = new ScoreFunction( sfxn );
105  setup_complete_ = false;
106 }
107 
109 {
110  if ( ! pose_ ) {
111  utility_exit_with_message( "PackDaemon::set_entity_correspondence may only be called after the set_pose_and_task" );
112  }
113  if ( ec.num_residues() != pose_->total_residue() ) {
114  utility_exit_with_message( "Num residue disgreement between input EntityCorrespondence and existing pose_" );
115  }
116  if ( ! correspondence_ ) {
118  setup_complete_ = false;
119  }
120  correspondence_->set_pose( pose_ ); // discard the pose that's already being pointed to by the ec
121 }
122 
124 {
125  TR << "Setting dlig nmeg limit" << std::endl;
126  task_->decrease_double_lazy_ig_memlimit( 1024 * 1024 * setting );
127  setup_complete_ = false;
128 }
129 
131 {
133  setup_complete_ = false;
134 }
135 
137 {
138  if ( !pose_ || !task_ ) {
139  utility_exit_with_message( "PackDaemon::set_pose_and_task must be called before setup() can be" );
140  }
141  if ( !score_function_ ) {
142  utility_exit_with_message( "PackDaemon::set_score_function must be called before setup() can be" );
143  }
144  if ( !correspondence_ ) {
145  utility_exit_with_message( "PackDaemon::set_entity_correspondence must be called before setup() can be" );
146  }
147  TR << "PackDaemon::setup()" << std::endl;
148 
149  rot_sets_ = new RotamerSets;
152 
153  ig_ = dynamic_cast< core::pack::interaction_graph::FixedBBInteractionGraph * > ( ig.get() );
154  if ( ! ig_ ) {
155  throw utility::excn::EXCN_Msg_Exception( "Interaction graph returned by pack_rotamers_setup is not a"
156  " fixed-backbone interaction graph. Cannot continue" );
157  }
158 
159  best_assignment_.first.resize( rot_sets_->nmoltenres() );
160  last_assignment_.first.resize( rot_sets_->nmoltenres() );
161 
162  //repacker_ = new BasicSimAnnealerRepacker( pose_, task_, ig_, rot_sets_ );
163  //repacker_ = new DenseIGRepacker( pose_, task_, ig_, rot_sets_ );
164  //repacker_ = new DoubleDenseIGRepacker( pose_, task_, ig_, rot_sets_ );
165  //FASTER_IG_Repacker * temp;
166 
167 /* temp = new FASTER_IG_Repacker( pose_, task_, ig_, rot_sets_ );
168  temp->set_num_sa( 8 );
169  repacker2_ = temp;
170 
171  temp = new FASTER_IG_Repacker( pose_, task_, ig_, rot_sets_ );
172  temp->set_num_sa( 4 );
173  repacker3_ = temp;
174 
175  temp = new FASTER_IG_Repacker( pose_, task_, ig_, rot_sets_ );
176  temp->set_num_sa( 2 );
177  repacker4_ = temp;
178 
179  temp = new FASTER_IG_Repacker( pose_, task_, ig_, rot_sets_ );
180  temp->set_sa_scale( 0.025 );
181  temp->set_num_sa( 8 );
182  repacker5_ = temp;
183 
184  temp = new FASTER_IG_Repacker( pose_, task_, ig_, rot_sets_ );
185  temp->set_sa_scale( 0.025 );
186  temp->set_num_sa( 4 );
187  repacker6_ = temp;
188 
189  temp = new FASTER_IG_Repacker( pose_, task_, ig_, rot_sets_ );
190  temp->set_sa_scale( 0.025 );
191  temp->set_num_sa( 2 );
192  repacker7_ = temp;
193 
194  temp = new FASTER_IG_Repacker( pose_, task_, ig_, rot_sets_ );
195  temp->set_ciBR_only( true );
196  repacker_ = temp;*/
197 
198  DenseIGRepackerOP mca_repacker = new DenseIGRepacker( pose_, task_, ig_, rot_sets_ );
199  mca_repacker->set_MCA();
200  repacker_ = mca_repacker;
201 
203 
204  setup_complete_ = true;
205 }
206 
207 /// @brief Repack the structure with the Entity
208 /// This function proceeds in two steps: it creates a list of
209 /// rotamer indices to be used during the repacking, and then
210 /// it uses that list to repack the rotamers. The first step
211 /// is taken care of by the select_rotamer_subset method.
214 {
215  if ( ! last_entity_ ) {
216  last_entity_ = entity.clone();
217  } else {
218  (*last_entity_) = entity;
219  }
220 
221  utility::vector0< int > rot_to_pack( select_rotamer_subset( entity ) );
222 
223  //clock_t starttime, stoptime;
224 
225  //starttime = clock();
226  last_assignment_ = repacker_->repack( rot_to_pack );
227  last_assignment_.second += background_energies_; // add in the background energies to give the total energy for the pose.
228 
229  //stoptime = clock();
230 
231  /*TR << "repacker_ " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " " << last_assignment_.second << std::endl;
232 
233  starttime = clock();
234  last_assignment_ = repacker2_->repack( rot_to_pack );
235  stoptime = clock();
236 
237  TR << "repacker2_ " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " " << last_assignment_.second << std::endl;
238 
239  starttime = clock();
240  last_assignment_ = repacker3_->repack( rot_to_pack );
241  stoptime = clock();
242 
243  TR << "repacker3_ " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " " << last_assignment_.second << std::endl;
244 
245  starttime = clock();
246  last_assignment_ = repacker4_->repack( rot_to_pack );
247  stoptime = clock();
248 
249  TR << "repacker4_ " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " " << last_assignment_.second << std::endl;
250 
251  starttime = clock();
252  last_assignment_ = repacker5_->repack( rot_to_pack );
253  stoptime = clock();
254 
255  TR << "repacker5_ " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " " << last_assignment_.second << std::endl;
256 
257  starttime = clock();
258  last_assignment_ = repacker6_->repack( rot_to_pack );
259  stoptime = clock();
260 
261  TR << "repacker6_ " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " " << last_assignment_.second << std::endl;
262 
263  starttime = clock();
264  last_assignment_ = repacker7_->repack( rot_to_pack );
265  stoptime = clock();
266 
267  TR << "repacker7_ " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " " << last_assignment_.second << std::endl;
268 
269  starttime = clock();
270  last_assignment_ = repacker8_->repack( rot_to_pack );
271  stoptime = clock();
272 
273  TR << "repacker8_ " << ((double) stoptime - starttime )/CLOCKS_PER_SEC << " " << last_assignment_.second << std::endl;*/
274 
275  if ( ! best_assignment_valid_ || last_assignment_.second < best_assignment_.second ) {
277  best_assignment_valid_ = true;
278  if ( ! best_entity_ ) {
279  best_entity_ = entity.clone();
280  } else {
281  (*best_entity_) = entity;
282  }
283  }
284 
285  return last_assignment_.second;
286 }
287 
290 {
291  using namespace core::pack::rotamer_set;
292  using namespace protocols::multistate_design;
293 
294  utility::vector0< Size > rotamer_subset;
295  for ( Size ii = 1; ii <= rot_sets_->nmoltenres(); ++ii ) {
296  Size ii_resid = rot_sets_->moltenres_2_resid( ii );
297  Size ii_entity_id = correspondence_->entity_for_residue( ii_resid );
298  Size ii_offset = rot_sets_->nrotamer_offset_for_moltenres( ii );
299  RotamerSetCOP ii_rotamers = rot_sets_->rotamer_set_for_moltenresidue( ii );
300  //std::cout << "Entity id for " << ii_resid << " " << ii_entity_id << std::endl;
301  Size ii_rotamers_appended( 0 );
302  if ( ii_entity_id == 0 ) {
303  // include all the rotamers for this residue
304  for ( Size jj = 1, ii_nrots = ii_rotamers->num_rotamers(); jj <= ii_nrots; ++jj ) {
305  rotamer_subset.push_back( ii_offset + jj );
306  ++ii_rotamers_appended;
307  }
308  if ( ii_rotamers_appended == 0 ) {
309  throw utility::excn::EXCN_Msg_Exception( "Failed to find any rotamers for residue "
310  + utility::to_string( ii_resid ) + "." );
311  }
312  } else {
313  PosTypeCOP pt_ptr( dynamic_cast< PosType const * > ( entity.traits()[ ii_entity_id ].get() ));
314  if ( ! pt_ptr ) {
315  utility_exit_with_message( "Failed to downcast entity trait[" +
316  utility::to_string( ii ) + "] to PosTye; trait name: " +
317  entity.traits()[ ii ]->name() );
318  }
319  core::chemical::AA entity_aa( pt_ptr->type() );
320  // include only the rotamers from the amino acid specified in this residue's entity element
321  for ( Size jj = 1, ii_nrots = ii_rotamers->num_rotamers(); jj <= ii_nrots; ++jj ) {
322  if ( ii_rotamers->rotamer( jj )->aa() == entity_aa ) {
323  rotamer_subset.push_back( ii_offset + jj );
324  ++ii_rotamers_appended;
325  }
326  }
327 
328  if ( ii_rotamers_appended == 0 ) {
329  throw utility::excn::EXCN_Msg_Exception( "Failed to find any rotamers for residue "
330  + utility::to_string( ii_resid ) + " corresponding to entity "
331  + utility::to_string( ii_entity_id ) + " when looking for "
332  + utility::to_string( entity_aa ) + " rotamers." );
333  }
334  }
335  }
336  return rotamer_subset;
337 }
338 
340 {
341 
342  EntityElements traits_copy( last_entity_->traits().size() );
343  for ( Size ii = 1; ii <= traits_copy.size(); ++ii ) {
344  traits_copy[ ii ] = last_entity_->traits()[ ii ]->clone();
345  }
346 
347  prev_state_hash_[ traits_copy ] = last_assignment_;
348 
349 }
350 
352 {
353  prev_state_hash_.erase( ent.traits() );
354 }
355 
356 
363 
366 
369 
371 {
372  EntityToRotamerHash::const_iterator iter = prev_state_hash_.find( ent.traits() );
373 
374  if ( iter == prev_state_hash_.end() ) {
375  TR << "Failed to find entity in entity-hash: " << ent << std::endl;
377  /// Failed to find this entity -- that's a problem!
378  return 0;
379  }
380  RotamerAssignmentAndEnergy const & rotamer_assignment( iter->second );
381  PoseOP return_pose = new Pose( *pose_ );
382  for ( Size ii = 1; ii <= rot_sets_->nmoltenres(); ++ii ) {
383  Size iiresid = rot_sets_->moltenres_2_resid( ii );
384  Size iibestrot = rot_sets_->rotid_on_moltenresidue( rotamer_assignment.first[ ii ] );
385 
386  return_pose->replace_residue(
387  iiresid,
388  *rot_sets_->rotamer_set_for_moltenresidue( ii )->rotamer( iibestrot ),
389  false
390  );
391  }
392  return return_pose;
393 }
394 
396 {
397  for ( Size ii = 1; ii <= rot_sets_->nmoltenres(); ++ii ) {
398  Size iiresid = rot_sets_->moltenres_2_resid( ii );
399  Size iibestrot = rot_sets_->rotid_on_moltenresidue( last_assignment_.first[ ii ] );
400 
401  pose.replace_residue(
402  iiresid,
403  *rot_sets_->rotamer_set_for_moltenresidue( ii )->rotamer( iibestrot ),
404  false
405  );
406  }
407 
408 }
409 
410 
412 {
413  TR << "Entity History:\n";
414  for ( EntityToRotamerHash::const_iterator hashiter = prev_state_hash_.begin(),
415  hashiter_end = prev_state_hash_.end(); hashiter != hashiter_end; ++hashiter ) {
416  TR << "Stored state:";
417  for ( Size ii = 1; ii <= hashiter->first.size(); ++ii ) {
418  TR << " " << hashiter->first[ ii ]->to_string();
419  }
420  TR << " fitness: " << hashiter->second.second << " rotamers: ";
421  for ( Size ii = 1; ii <= hashiter->second.first.size(); ++ii ) {
422  TR << " " << hashiter->second.first[ ii ];
423  }
424  TR << "\n";
425  }
426  TR << std::endl;
427 }
428 
430 {
431  using namespace core;
432  using namespace core::scoring;
433  using namespace core::graph;
434 
436  Energies const & energies( pose_->energies() );
437  EnergyGraph const & energy_graph( energies.energy_graph() );
438  for ( Size ii = 1; ii <= pose_->total_residue(); ++ii ) {
439  if ( task_->being_packed( ii ) ) continue;
440  background_energies_ += energies.onebody_energies( ii ).dot( score_function_->weights() );
442  iru = energy_graph.get_node(ii)->const_upper_edge_list_begin(),
443  irue = energy_graph.get_node(ii)->const_upper_edge_list_end();
444  iru != irue; ++iru ) {
445  EnergyEdge const & edge( static_cast< EnergyEdge const & > (**iru) );
446  Size const jj = edge.get_second_node_ind();
447  if ( task_->being_packed( jj ) ) continue;
448  EnergyMap emap = edge.fill_energy_map();
449  background_energies_ += score_function_->weights().dot( emap );
450  }
451 
452  }
453 }
454 
456  num_entities_( 0 ),
457  task_factory_( new core::pack::task::TaskFactory ),
459  limit_dlig_mem_usage_( false ),
460  dlig_nmeg_limit_( 0 ),
461  ndaemons_( 0 ),
462  n_npd_properties_( 0 )
463 {}
464 
466 {}
467 
468 /// @details The entity resfile is slightly different from a regular resfile.
469 /// Its first line should consist of the number of residues that are entity; the
470 /// rest of the resfile lists those residues numbering from 1.
472  std::string const & resfile
473 )
474 {
475  utility::io::izstream infile( resfile );
476  if ( ! infile ) {
477  utility_exit_with_message( "Failed to open entity resfile: " + resfile );
478  }
479  set_entity_resfile( infile, resfile );
480 }
481 
482 
484  std::istream & resfile,
485  std::string const & resfile_name
486 )
487 {
488  using namespace core::pack::task;
489  using namespace core::pose;
490 
491  if ( ! daemons_.empty() ) {
492  utility_exit_with_message( "Entity resfile must be set before any daemons may be added and all daemons must use the same correspondece file" );
493  }
494 
495  if ( (resfile >> num_entities_ ).fail() ) {
496  utility_exit_with_message( "Error reading the number of entities from entity resfile " + resfile_name );
497  }
498 
499  Pose ala_pose;
500  std::string ala_seq( num_entities_, 'A' );
502  entity_task_ = TaskFactory::create_packer_task( ala_pose );
503 
504  entity_resfile_ = new ResfileContents( ala_pose, resfile );
505 
506  /// apply the resfile operations to the entity_task_ for later error checking
507  for ( Size ii = 1; ii <= entity_task_->total_residue(); ++ii ) {
508 
509  std::list< ResfileCommandCOP > const & ii_command_list(
510  entity_resfile_->specialized_commands_exist_for_residue( ii ) ?
511  entity_resfile_->commands_for_residue( ii )
512  : entity_resfile_->default_commands() );
513 
514  for ( std::list< ResfileCommandCOP >::const_iterator
515  iter = ii_command_list.begin(), iter_end = ii_command_list.end();
516  iter != iter_end; ++iter ) {
517  (*iter)->residue_action( *entity_task_, ii );
518  }
519  }
520 
521 }
522 
524 {
525  score_function_ = sfxn.clone();
526 }
527 
529 {
530  task_factory_ = factory;
531 }
532 
534 {
536 }
537 
539 {
540  if ( setting != 0 ) {
541  limit_dlig_mem_usage_ = true;
542  dlig_nmeg_limit_ = setting;
543  } else {
544  limit_dlig_mem_usage_ = false;
545  }
546 }
547 
550 )
551 {
552  npd_calculator_creators_[ creator->calculator_name() ] = creator;
553 }
554 
555 
556 
557 /// @brief Each daemon is associated with an index representing its position in
558 /// some master list somewhere. The DaemonSet is responsible for keeping this index.
559 void
561  Size daemon_index,
562  std::string const & pdb_name,
563  std::string const & correspondence_file_name,
564  std::string const & secondary_resfile_name
565 )
566 {
567  /// Read in the pdb
568  Pose pose;
569  core::import_pose::pose_from_pdb( pose, pdb_name );
570 
571  // Open the correspondence file
572  utility::io::izstream correspondence_file( correspondence_file_name );
573  if ( ! correspondence_file ) {
574  utility_exit_with_message( "Could not open correspondence file named: " + correspondence_file_name );
575  }
576 
577  // Open the resfile
578  utility::io::izstream secondary_resfile( secondary_resfile_name );
579  if ( ! secondary_resfile ) {
580  utility_exit_with_message( "Could not open secondary resfile named: " + secondary_resfile_name );
581  }
582  add_pack_daemon( daemon_index, pdb_name, pose, correspondence_file_name, correspondence_file, secondary_resfile_name, secondary_resfile );
583 }
584 
585 void
587  Size daemon_index,
588  std::string const & pose_file_name,
589  Pose const & pose,
590  std::string const & correspondence_file_filename,
591  std::istream & correspondence_file,
592  std::string const & secondary_refile_file_filename,
593  std::istream & secondary_resfile
594 )
595 {
596  TR << "Adding daemon: " << daemon_index << " " << pose_file_name << " " << correspondence_file_filename << " " << secondary_refile_file_filename << std::endl;
597 
598  using namespace core;
599  using namespace core::pack::task;
600 
601  if ( ! score_function_ ) {
602  utility_exit_with_message( "ScoreFunction must be set before DaemonSet::add_pack_daemon may be called" );
603  }
604  if ( num_entities_ == 0 ) {
605  utility_exit_with_message( "Entity resfile must be set before DaemonSet::add_pack_daemon may be called" );
606  }
607 
608  /// Read the correspondence file
610  ec->set_pose( new core::pose::Pose( pose ));
611  ec->set_num_entities( num_entities_ );
612  ec->initialize_from_correspondence_file( correspondence_file );
613 
614  /// Setup the task
615  PackerTaskOP task = task_factory_->create_task_and_apply_taskoperations( pose );
616  ResfileContents secondary_resfile_contents( pose, secondary_resfile );
617 
618  for ( Size ii = 1; ii <= pose.total_residue(); ++ii ) {
619  Size ii_entity = ec->entity_for_residue( ii );
620  std::list< ResfileCommandCOP > const & ii_command_list(
621  ii_entity != 0 ? (
622  entity_resfile_->specialized_commands_exist_for_residue( ii_entity ) ?
623  entity_resfile_->commands_for_residue( ii_entity ) :
624  entity_resfile_->default_commands()
625  ) :
626  (
627  secondary_resfile_contents.specialized_commands_exist_for_residue( ii ) ?
628  secondary_resfile_contents.commands_for_residue( ii ) :
629  secondary_resfile_contents.default_commands() ));
630 
631  for ( std::list< ResfileCommandCOP >::const_iterator
632  iter = ii_command_list.begin(), iter_end = ii_command_list.end();
633  iter != iter_end; ++iter ) {
634  (*iter)->residue_action( *task, ii );
635  }
636  }
637  task->initialize_from_command_line();
638 
639  /// At this point, the packer task is initialized and ready to be handed to the
640  /// PackDaemon.
641  ///
642  /// Take a moment and make sure that the task is in fact compatible with
643  /// the entity resfile: Make sure the amino-acid contents of the residues
644  /// with non-zero entity-id have the same allowable residues as the
645  /// entity packer task. If there is a discrepancy, then the program should
646  /// be halted now.
648  for ( Size ii = 1; ii <= pose.total_residue(); ++ii ) {
649  Size ii_entity_id = ec->entity_for_residue( ii );
650  if ( ii_entity_id == 0 ) {
651  continue;
652  }
653 
655  final_task_allowed = task->residue_task( ii ).allowed_residue_types_begin(),
656  entity_task_allowed = entity_task_->residue_task( ii_entity_id ).allowed_residue_types_begin(),
657  final_task_allowed_end = task->residue_task( ii ).allowed_residue_types_end(),
658  entity_task_allowed_end = entity_task_->residue_task( ii_entity_id ).allowed_residue_types_end();
659 
662 
663  /// NO SUPPORT YET FOR NONCANONICAL AMINO ACIDS
664 
665  bool bad( false );
666  while ( final_task_allowed != final_task_allowed_end ) {
667  if ( (*final_task_allowed)->aa() <= core::chemical::num_canonical_aas ) {
668  final_aas[ (*final_task_allowed)->aa() ] = true;
669  } else {
670  bad = true;
671  break;
672  }
673  ++final_task_allowed;
674  }
675  while ( entity_task_allowed != entity_task_allowed_end ) {
676  if ( (*entity_task_allowed)->aa() <= core::chemical::num_canonical_aas ) {
677  entity_aas[ (*entity_task_allowed)->aa() ] = true;
678  } else {
679  bad = true;
680  break;
681  }
682  ++entity_task_allowed;
683  }
684 
685  if ( ! bad ) {
686  for ( Size ii = 1; ii <= core::chemical::num_canonical_aas; ++ii ) {
687  if ( entity_aas[ ii ] != final_aas[ ii ] ) {
688  bad = true;
689  break;
690  }
691  }
692  }
693  if ( bad ) {
694  std::string ii_error;
695  ii_error = "Discrepancy between allowed residue types in the entity resfile and "
696  "the final resfile for residue " + utility::to_string( ii ) + " in structure " +
697  pose_file_name + " which corresponds to entity " + utility::to_string( ii_entity_id ) + "\n";
698 
699  ii_error += "Original residue type: " + pose.residue_type(ii).name() + "\n";
700 
701  ii_error += "Final packer task allows residue types\n";
702  final_task_allowed = task->residue_task( ii ).allowed_residue_types_begin();
703  final_task_allowed_end = task->residue_task( ii ).allowed_residue_types_end();
704  while ( final_task_allowed != final_task_allowed_end ) {
705  ii_error += utility::to_string( (*final_task_allowed)->aa()) + " (" + (*final_task_allowed)->name() + ")\n";
706  ++final_task_allowed;
707  }
708 
709  ii_error += "Shared packer task allows residue types\n";
710  entity_task_allowed = entity_task_->residue_task( ii_entity_id ).allowed_residue_types_begin();
711  entity_task_allowed_end = entity_task_->residue_task( ii_entity_id ).allowed_residue_types_end();
712  while ( entity_task_allowed != entity_task_allowed_end ) {
713  ii_error += utility::to_string((*entity_task_allowed)->aa()) + "\n";
714  ++entity_task_allowed;
715  }
716  error_message += ii_error;
717  }
718  }
719  if ( error_message != "" ) {
720  //std::cerr << error_message << std::endl;
721  throw utility::excn::EXCN_Msg_Exception( error_message );
722  }
723 
724  // Create the new daemon
725  PackDaemonOP daemon = new PackDaemon;
726  daemon->set_pose_and_task( pose, *task );
727  daemon->set_score_function( *score_function_ );
728  daemon->set_entity_correspondence( *ec );
729  daemon->set_include_background_energies( include_background_energies_ );
730  if ( limit_dlig_mem_usage_ ) {
731  daemon->set_dlig_nmeg_limit( dlig_nmeg_limit_ );
732  }
733 
734  daemons_.push_back( std::make_pair( daemon_index, daemon ));
735  daemon_poses_.push_back( new core::pose::Pose( pose ));
736  daemon_tasks_.push_back( task );
737  npd_calcs_for_poses_.resize( daemon_tasks_.size() );
738  ++ndaemons_;
739 }
740 
741 void
743  Size daemon_index,
744  std::string const & npd_property,
745  Size npd_index
746 )
747 {
748  if ( npd_calculator_creators_.find( npd_property ) == npd_calculator_creators_.end() ) {
749  std::string msg;
750  if ( npd_calculator_creators_.empty() ) {
751  msg = "Requested non-pairwise-decomposable (NPD) property '" + npd_property +"' but there are"
752  " no NPD Property Calculator Creators that have been registered with the DaemonSet";
753  } else {
754  msg = "Requested non-pairwise-decomposable (NPD) property '" + npd_property +"' but no such NPD"
755  " calculator creator has been registered with the DaemonSet. Available calculators include\n";
756  for ( std::map< std::string, NPDPropCalculatorCreatorOP >::const_iterator
757  npditer = npd_calculator_creators_.begin(),
758  npditer_end = npd_calculator_creators_.end();
759  npditer != npditer_end; ++npditer ) {
760  msg += " " + npditer->first + "\n";
761  }
762  }
763  throw utility::excn::EXCN_Msg_Exception( msg );
764  }
765 
766  Size which_daemon = 0;
767  for ( Size ii = 1; ii <= daemons_.size(); ++ii ) {
768  if ( daemons_[ ii ].first == daemon_index ) {
769  which_daemon = ii;
770  break;
771  }
772  }
773  if ( which_daemon == 0 ) {
774  throw utility::excn::EXCN_Msg_Exception( "Internal error: could not locate requested daemon " +
775  utility::to_string( daemon_index ) + " while trying to add NPD Property Calculator for that daemon." );
776  }
777 
778  /// if we've made it this far, create, initialize and add the creator.
779  NPDPropCalculatorOP calculator = npd_calculator_creators_[ npd_property ]->new_calculator();
780  calculator->setup( *daemon_poses_[ which_daemon ], *daemon_tasks_[ which_daemon ] );
781  npd_calcs_for_poses_[ which_daemon ].push_back( std::make_pair( npd_index, calculator ));
783 }
784 
785 
787 {
788  for ( DaemonListIter iter = daemons_.begin(), iter_end = daemons_.end(); iter != iter_end; ++iter ) {
789  iter->second->setup();
790  }
791 }
792 
793 
795 
797 
800 {
801 #ifdef APL_MEASURE_MSD_LOAD_BALANCE
802  std::clock_t starttime = clock();
803 #endif
804 
805 
806  SizeRealPairs daemon_scores;
807  for ( DaemonListIter iter = daemons_.begin(), iter_end = daemons_.end();
808  iter != iter_end; ++iter ) {
809  core::Real energy = iter->second->compute_energy_for_assignment( entity );
810  daemon_scores.push_back( std::make_pair( iter->first, energy ) );
811  //std::cout << "Computed energy " << energy << " for state " << iter->first << std::endl;
812  }
813 #ifdef APL_MEASURE_MSD_LOAD_BALANCE
814  std::clock_t midtime = clock();
815 #endif
816  SizeRealPairs npd_properties;
817  if ( n_npd_properties_ != 0 ) {
818  for ( Size ii = 1; ii <= npd_calcs_for_poses_.size(); ++ii ) {
819  if ( npd_calcs_for_poses_[ ii ].empty() ) continue;
820  daemons_[ ii ].second->assign_last_rotamers_to_pose( *daemon_poses_[ ii ] );
821  for ( std::list< NPDIndAndCalc >::const_iterator
822  npditer = npd_calcs_for_poses_[ ii ].begin(),
823  npditer_end = npd_calcs_for_poses_[ ii ].end();
824  npditer != npditer_end; ++npditer ) {
825  core::Real const npd_property = npditer->second->calculate( *daemon_poses_[ ii ] );
826  npd_properties.push_back( std::make_pair( npditer->first, npd_property ));
827  //std::cout << "Computed non-pairwise decomposable property " << npd_property << " for npdindex " << npditer->first << std::endl;
828  }
829  }
830  }
831 #ifdef APL_MEASURE_MSD_LOAD_BALANCE
832  std::clock_t stoptime = clock();
833  packing_runtime_ = ((double) midtime - starttime ) / CLOCKS_PER_SEC;
834  npd_runtime_ = ((double) stoptime - midtime ) / CLOCKS_PER_SEC;
835 #endif
836  return std::make_pair( daemon_scores, npd_properties );
837 }
838 
841 {
842  ConstDaemonList return_daemons;
843  for ( DaemonListIter iter = daemons_.begin(), iter_end = daemons_.end();
844  iter != iter_end; ++iter ) {
845  std::pair< core::Size, PackDaemonCOP > new_element;
846  new_element.first = iter->first;
847  new_element.second = iter->second;
848  return_daemons.push_back( new_element );
849  }
850  return return_daemons;
851 }
852 
854 {
855  for ( DaemonListIter iter = daemons_.begin(), iter_end = daemons_.end(); iter != iter_end; ++iter ) {
856  iter->second->mark_last_entity_as_important();
857  }
858 }
859 
861 {
862  for ( DaemonListIter iter = daemons_.begin(), iter_end = daemons_.end(); iter != iter_end; ++iter ) {
863  iter->second->mark_entity_as_unimportant( ent );
864  }
865 
866 }
867 
868 std::list< std::pair< core::Size, core::pose::PoseOP > >
870  Entity const & ent,
871  DaemonIndices const & daemon_indices
872 ) const
873 {
874  std::list< std::pair< Size, PoseOP > > return_list;
875  for ( DaemonListIter iter = daemons_.begin(), iter_end = daemons_.end(); iter != iter_end; ++iter ) {
876  bool generate_pose_for_daemon( false );
877  for ( DaemonIndices::const_iterator
878  index_iter = daemon_indices.begin(),
879  index_iter_end = daemon_indices.end();
880  index_iter != index_iter_end; ++index_iter ) {
881  if ( iter->first == *index_iter ) {
882  generate_pose_for_daemon = true;
883  }
884  }
885  if ( ! generate_pose_for_daemon ) continue;
886  return_list.push_back( std::make_pair( iter->first, iter->second->recreate_pose_for_entity( ent )) );
887  }
888  return return_list;
889 }
890 
893 
895 {
896 #ifdef USEMPI
897  while ( true ) {
898  /// Wait for a signal from node 0, and then process that request
899  int signal = utility::receive_integer_from_node( 0 );
900  DaemonSetMessage message( static_cast< DaemonSetMessage > (signal) );
901  bool leave_main_while_loop( false );
902  switch ( message ) {
903  case error_message: {
904  graceful_exit();
905  break;
906  }
907  case success_message: {
908  // noop? Why are we recieving a success signal?
909  break;
910  }
911  case add_daemon: {
913  break;
914  }
915  case evaluate_entity: {
917  break;
918  }
921  break;
922  }
923  case discard_old_entity: {
925  break;
926  }
929  break;
930  }
931  case spin_down: {
932  leave_main_while_loop = true;
933  break;
934  }
935  default: {
936  utility::send_integer_to_node( 0, error_message );
937  graceful_exit();
938  }
939  }
940  if ( leave_main_while_loop ) break;
941  }
942 #else
943  utility_exit_with_message( "MPI-related function requested of class DaemonSet in a non-MPI build" );
944 #endif
945 }
946 
947 
949 {
950 #ifdef USEMPI
951  int n_daemons = utility::receive_integer_from_node( 0 );
952  utility::vector1< int > daemon_indices( n_daemons );
953 
954  utility::vector1< std::string > pdb_names( n_daemons );
955  utility::vector1< std::string > pdbs( n_daemons );
956 
957  utility::vector1< std::string > correspondence_file_names( n_daemons );
958  utility::vector1< std::string > correspondence_files( n_daemons );
959 
960  utility::vector1< std::string > secondary_resfile_names( n_daemons );
961  utility::vector1< std::string > secondary_resfiles( n_daemons );
962 
963  utility::vector1< std::list< std::pair< Size, std::string > > > npd_properties( n_daemons );
964 
965  for ( int ii = 1; ii <= n_daemons; ++ii ) {
966  daemon_indices[ ii ] = utility::receive_integer_from_node( 0 );
967  pdb_names[ ii ] = utility::receive_string_from_node( 0 );
968  pdbs[ ii ] = utility::receive_string_from_node( 0 );
969  correspondence_file_names[ ii ] = utility::receive_string_from_node( 0 );
970  correspondence_files[ ii ] = utility::receive_string_from_node( 0 );
971  secondary_resfile_names[ ii ] = utility::receive_string_from_node( 0 );
972  secondary_resfiles[ ii ] = utility::receive_string_from_node( 0 );
973  int n_npd_properties_for_state = utility::receive_integer_from_node( 0 );
974  for ( Size jj = 1; jj <= n_npd_properties_for_state; ++jj ) {
975  Size npd_property_id = utility::receive_integer_from_node( 0 );
976  std::string property = utility::receive_string_from_node( 0 );
977  npd_properties[ ii ].push_back( std::make_pair( npd_property_id, property ) );
978  }
979  }
980 
981  try {
982  for ( int ii = 1; ii <= n_daemons; ++ii ) {
983  Pose pose;
984  core::import_pose::pose_from_pdbstring( pose, pdbs[ ii ], pdb_names[ ii ] );
985  std::istringstream correspondence_file( correspondence_files[ ii ] );
986  std::istringstream secondary_resfile( secondary_resfiles[ ii ] );
988  daemon_indices[ ii ],
989  pdb_names[ ii ], pose,
990  correspondence_file_names[ ii ], correspondence_file,
991  secondary_resfile_names[ ii ], secondary_resfile );
992  for ( std::list< std::pair< Size, std::string > >::const_iterator
993  npditer = npd_properties[ ii ].begin(),
994  npditer_end = npd_properties[ ii ].end();
995  npditer != npditer_end; ++npditer ) {
996  add_npd_property_calculator_for_state( daemon_indices[ ii ], npditer->second, npditer->first );
997  }
998 
999  }
1000  } catch ( utility::excn::EXCN_Base & excn ) {
1001  // send the error message to node 0 and exit gracefully.
1002  std::string message( excn.msg() );
1003  utility::send_integer_to_node( 0, error_message );
1004  utility::send_string_to_node( 0, message );
1005  graceful_exit();
1006  }
1007 
1008  /// If we got here, then we added all daemons successfully. Let node 0 know that.
1009  /// It's there waiting to hear from us.
1010  utility::send_integer_to_node( 0, success_message );
1011 
1012  /// Now, ask, did all the other nodes successfully get added?
1013  int others_successful = utility::receive_integer_from_node( 0 );
1014  if ( others_successful == success_message ) {
1015  // Green light: go and precompute all rotamer pair energies
1016  setup_daemons();
1017  } else {
1018  graceful_exit();
1019  }
1020 #endif
1021 }
1022 
1023 
1025 {
1026 #ifdef USEMPI
1027 
1028 #ifdef APL_MEASURE_MSD_LOAD_BALANCE
1029  std::clock_t starttime = clock();
1030 #endif
1031 
1032  EntityOP entity = recieve_entity();
1033  StateEsAndNPDs entity_energies =
1034  compute_energy_for_assignment( *entity );
1035 
1036 #ifdef APL_MEASURE_MSD_LOAD_BALANCE
1037  std::clock_t stoptime = clock();
1038 #endif
1039 
1040  assert( ndaemons() == entity_energies.first.size() );
1041  assert( n_npd_properties_ == entity_energies.second.size() );
1042 
1043  int n_daemons( ndaemons() );
1044  utility::send_integer_to_node( 0, n_daemons );
1045  for ( std::list< std::pair< core::Size, core::Real > >::const_iterator
1046  iter = entity_energies.first.begin(),
1047  iter_end = entity_energies.first.end();
1048  iter != iter_end; ++iter ) {
1049  utility::send_integer_to_node( 0, iter->first );
1050  utility::send_double_to_node( 0, iter->second );
1051  }
1052  utility::send_integer_to_node( 0, n_npd_properties_ );
1053  for ( std::list< std::pair< core::Size, core::Real > >::const_iterator
1054  iter = entity_energies.second.begin(),
1055  iter_end = entity_energies.second.end();
1056  iter != iter_end; ++iter ) {
1057  utility::send_integer_to_node( 0, iter->first );
1058  utility::send_double_to_node( 0, iter->second );
1059  }
1060 
1061 #ifdef APL_MEASURE_MSD_LOAD_BALANCE
1062  core::Real evaltime = ((double) stoptime - starttime) / CLOCKS_PER_SEC;
1063  //TR << "Node " << utility::mpi_rank() << " " << evaltime << " seconds to evaluate" << std::endl;
1064  utility::send_double_to_node( 0, evaltime );
1065  utility::send_double_to_node( 0, packing_runtime_ );
1066  utility::send_double_to_node( 0, npd_runtime_ );
1067 #endif
1068 
1069  //TR << "Finished sending state energies" << std::endl;
1070 
1071 
1072 #endif
1073 }
1074 
1075 
1077 {
1078 #ifdef USEMPI
1079  EntityOP entity = recieve_entity();
1080  mark_entity_as_unimportant( *entity );
1081 #endif
1082 }
1083 
1084 
1086 {
1087 #ifdef USEMPI
1088  EntityOP entity = recieve_entity();
1090 
1091  std::list< std::pair< Size, PoseOP > > poses = retrieve_relevant_poses_for_entity( *entity, indices );
1092  utility::send_integer_to_node( 0, poses.size() );
1093  for ( std::list< std::pair< Size, PoseOP > >::const_iterator
1094  iter = poses.begin(), iter_end = poses.end(); iter != iter_end; ++iter ) {
1095  std::ostringstream oss;
1096  core::io::pdb::dump_pdb( *( iter->second ), oss );
1097  utility::send_integer_to_node( 0, iter->first );
1098  utility::send_string_to_node( 0, oss.str() );
1099  }
1100 #endif
1101 }
1102 
1103 
1106 {
1107 #ifdef USEMPI
1108  std::string entity_string = utility::receive_string_from_node( 0 );
1109  EntityOP ent = new Entity( entity_string );
1110  return ent;
1111 #endif
1112  return 0;
1113 }
1114 
1115 
1118 {
1119  DaemonIndices indices;
1120 #ifdef USEMPI
1121  utility::vector1< int > int_indices = utility::receive_integers_from_node( 0 );
1122  indices = int_indices; // cast from unsigned to signed integers
1123 #endif
1124  return indices;
1125 }
1126 
1127 void
1129 {
1130 #ifdef USEMPI
1131  MPI_Finalize();
1132 #endif
1133  utility_exit();
1134 }
1135 
1138 
1139 void
1141  core::pose::Pose const &,
1143 )
1144 {}
1145 
1146 
1149 
1151  PoseOP pose,
1152  PackerTaskOP task,
1154  RotamerSetsOP rot_sets
1155 ) :
1156  pose_( pose ),
1157  task_( task ),
1158  ig_( ig ),
1159  rot_sets_( rot_sets )
1160 {}
1161 
1163 
1168 void QuickRepacker::task( PackerTaskOP setting ) { task_ = setting; }
1169 
1170 
1172  PoseOP pose,
1173  PackerTaskOP task,
1175  RotamerSetsOP rotsets
1176 ) :
1177  parent( pose, task, ig, rotsets )
1178 {
1179  ig()->prepare_for_simulated_annealing();
1180 }
1181 
1183 
1186 {
1187  ObjexxFCL::FArray1D< int > rotamer_assignment( pose()->total_residue() );
1188  core::PackerEnergy rotamer_energy;
1189 
1191  *pose(), task(), rot_sets(), ig(), rot_to_pack,
1192  rotamer_assignment, rotamer_energy );
1193 
1195  result.first.resize( rot_sets()->nmoltenres() );
1196 
1197  for ( Size ii = 1; ii <= rot_sets()->nmoltenres(); ++ii ) {
1198  result.first[ ii ] = rotamer_assignment( rot_sets()->moltenres_2_resid( ii ) );
1199  }
1200  result.second = rotamer_energy;
1201  return result;
1202 }
1203 
1204 
1206  PoseOP pose,
1207  PackerTaskOP task,
1209  RotamerSetsOP rotsets
1210 ) :
1211  parent( pose, task, ig, rotsets )
1212 {}
1213 
1215 
1218  utility::vector0< int > const & rot_to_pack
1219 )
1220 {
1221  return new core::pack::rotamer_set::RotamerSubsets( *rot_sets(), rot_to_pack );
1222 }
1223 
1224 
1225 /// DENSE IG REPACKER
1226 
1228  PoseOP pose,
1229  PackerTaskOP task,
1231  RotamerSetsOP rotsets
1232 ) :
1233  parent( pose, task, ig, rotsets )
1234 {
1235  ig()->prepare_for_simulated_annealing();
1236 }
1237 
1239 
1241  PackerTaskOP copy_task = task()->clone();
1242  copy_task->or_multi_cool_annealer( true ); // cannot be undone
1243  task( copy_task );
1244 }
1245 
1248 {
1249  using namespace core::pack::rotamer_set;
1250  using namespace core::pack::interaction_graph;
1251  utility::vector0< int > local_rot_to_pack( rot_to_pack );
1252  /// SHOULD be in sorted order already, but make sure!
1253  std::sort( local_rot_to_pack.begin(), local_rot_to_pack.end() );
1254 
1255  utility::subset_mapping rotamer_subset_map( rot_sets()->nrotamers() );
1256  rotamer_subset_map.reserve_destination_size( local_rot_to_pack.size() );
1257  for ( Size ii = 0; ii < local_rot_to_pack.size(); ++ii ) {
1258  rotamer_subset_map.set_next_correspondence( local_rot_to_pack[ ii ] );
1259  }
1260 
1261  RotamerSubsetsOP rsubset = create_rotamer_subsets_from_rot_to_pack( local_rot_to_pack );
1262  DensePDInteractionGraphOP dense_ig =
1263  create_dense_pdig_from_rot_to_pack( local_rot_to_pack, rsubset );
1264 
1265  //core::Size nmoltenres = rot_sets()->nmoltenres();
1266  ObjexxFCL::FArray1D< int > rotamer_assignment( pose()->total_residue() );
1267  core::PackerEnergy rotamer_energy;
1268  utility::vector0< int > all_rots( local_rot_to_pack.size() );
1269  for ( Size ii = 0; ii < all_rots.size(); ++ii ) all_rots[ ii ] = ii+1;
1270 
1272  *pose(), task(), rsubset, dense_ig, all_rots,
1273  rotamer_assignment, rotamer_energy );
1274 
1276  result.first.resize( rot_sets()->nmoltenres() );
1277 
1278  for ( Size ii = 1; ii <= rot_sets()->nmoltenres(); ++ii ) {
1279  result.first[ ii ] = rotamer_subset_map.d2s( rotamer_assignment( rot_sets()->moltenres_2_resid( ii ) ));
1280  }
1281 
1282  /*TR << "Assignment:";
1283  for ( Size ii = 1; ii <= rot_sets()->nmoltenres(); ++ii ) {
1284  TR << " " << rotamer_assignment( rot_sets()->moltenres_2_resid( ii ));
1285  }
1286  TR << std::endl;*/
1287  result.second = rotamer_energy;
1288  return result;
1289 }
1290 
1293  utility::vector0< int > const & rot_to_pack,
1294  RotamerSubsetsOP rot_subsets
1295 )
1296 {
1297  using namespace core::pack::interaction_graph;
1298 
1299  core::Size nmoltenres = rot_sets()->nmoltenres();
1300  DensePDInteractionGraphOP dense_ig = new DensePDInteractionGraph( nmoltenres );
1301  dense_ig->initialize( *rot_subsets );
1302 
1303  /// If the rotamers are in a contiguous block and all have the same "aa" according to
1304  /// the PDInteractionGraph, then we can rapidly transfer the energies from the PDIG
1305  /// to the new dense interaction graph using the new get_aa_submatrix_energies_for_edge
1306  /// function; otherwise, we have to fall back on the old
1307  utility::vector1< int > aaind_for_moltres( nmoltenres, -1 );
1308 
1309  for ( Size ii = 1; ii <= rot_to_pack.size(); ++ii ) {
1310  Size const ii_moltenres = rot_subsets->moltenres_for_rotamer( ii );
1311  Size const ii_local_id = rot_subsets->rotid_on_moltenresidue( ii );
1312  Size const ii_old_rotid = rot_sets()->rotid_on_moltenresidue(rot_to_pack[ ii - 1 ]);
1313 
1314  if ( aaind_for_moltres[ ii_moltenres ] == -1 ) {
1315  aaind_for_moltres[ ii_moltenres ] = ig()->aatype_for_node_state( ii_moltenres, ii_old_rotid );
1316  } else if ( aaind_for_moltres[ ii_moltenres ] != 0 ) {
1317  if ( aaind_for_moltres[ ii_moltenres ] != ig()->aatype_for_node_state( ii_moltenres, ii_old_rotid ) ) {
1318  aaind_for_moltres[ ii_moltenres ] = 0;
1319  }
1320  }
1321 
1322  dense_ig->add_to_nodes_one_body_energy(
1323  ii_moltenres,
1324  ii_local_id,
1325  ig()->get_one_body_energy_for_node_state( ii_moltenres, ii_old_rotid ));
1326  //std::cout << "Setting rotamer 1-body-energy " << ii_moltenres << " rot# " << ii_local_id << " (";
1327  //std::cout << rot_to_pack[ ii - 1 ] << ") = ";
1328  //std::cout << ig()->get_one_body_energy_for_node_state( ii_moltenres, ii_old_rotid) << std::endl;
1329  }
1330 
1331  for ( Size ii = 1; ii <= nmoltenres; ++ii ) {
1332  for ( Size jj = ii+1; jj <= nmoltenres; ++jj ) {
1333  if ( ig()->get_edge_exists( ii, jj ) ) {
1334  if ( aaind_for_moltres[ ii ] > 0 && aaind_for_moltres[ jj ] > 0 ) {
1335  if ( ! ig()->get_sparse_aa_info_for_edge( ii, jj,aaind_for_moltres[ ii ], aaind_for_moltres[ jj ] )) {
1336  /// NO non-zero energies for this edge
1337  continue;
1338  }
1339  }
1340  dense_ig->add_edge( ii, jj );
1341  bool fast_edge_energy_transfer_successfull = false;
1342  if ( aaind_for_moltres[ ii ] > 0 && aaind_for_moltres[ jj ] > 0 ) {
1343  ObjexxFCL::FArray2D< core::PackerEnergy > edge_energies =
1344  ig()->get_aa_submatrix_energies_for_edge( ii, jj, aaind_for_moltres[ ii ], aaind_for_moltres[ jj ] );
1345  if ( edge_energies.size1() == rot_subsets->nrotamers_for_moltenres( jj ) &&
1346  edge_energies.size2() == rot_subsets->nrotamers_for_moltenres( ii ) ) {
1347  // Safe to transfer the edge energy table to the DenseIG
1348  fast_edge_energy_transfer_successfull = true;
1349  dense_ig->swap_edge_energies( ii, jj, edge_energies );
1350  } else {
1351  TR << "Surprisingly, edge " << ii << " " << jj << " did not have the right sized"
1352  << " edge energy table from the PDIG:" << rot_subsets->nrotamers_for_moltenres( ii )
1353  << " " << edge_energies.size2() << " " << rot_subsets->nrotamers_for_moltenres( jj )
1354  << " " << edge_energies.size1() << std::endl;
1355  }
1356  }
1357 
1358  if ( ! fast_edge_energy_transfer_successfull ) {
1359  for ( Size kk = 1, kk_end = rot_subsets->nrotamers_for_moltenres( ii ); kk <= kk_end; ++kk ) {
1360  Size const kk_old = rot_sets()->rotid_on_moltenresidue(
1361  rot_to_pack[ rot_subsets->moltenres_rotid_2_rotid( ii, kk ) - 1 ] );
1362  for ( Size ll = 1, ll_end = rot_subsets->nrotamers_for_moltenres( jj ); ll <= ll_end; ++ll ) {
1363  Size const ll_old = rot_sets()->rotid_on_moltenresidue(
1364  rot_to_pack[ rot_subsets->moltenres_rotid_2_rotid( jj, ll ) - 1 ] );
1365  dense_ig->set_two_body_energy_for_edge( ii, jj, kk, ll,
1366  ig()->get_two_body_energy_for_edge( ii, jj, kk_old, ll_old ) );
1367  //std::cout << "Setting energy for edge " << ii << " " << jj;
1368  //std::cout << " rotamer pair " << kk << " (" << kk_old << ") and " << ll << " (" << ll_old;
1369  //std::cout << " ) to " << ig()->get_two_body_energy_for_edge( ii, jj, kk_old, ll_old ) << std::endl;
1370  }
1371  }
1372  }
1373  }
1374  }
1375  }
1376  return dense_ig;
1377 
1378 }
1379 
1380 //// DOUBLE DENSE IG REPACKER
1381 
1382 
1384  PoseOP pose,
1387  RotamerSetsOP rotsets
1388 ) :
1389  parent( pose, task, ig, rotsets )
1390 {
1391  ig()->prepare_for_simulated_annealing();
1392 }
1393 
1395 
1398 {
1399  using namespace core::pack::rotamer_set;
1400  using namespace core::pack::interaction_graph;
1401  utility::vector0< int > local_rot_to_pack( rot_to_pack );
1402  /// SHOULD be in sorted order already, but make sure!
1403  std::sort( local_rot_to_pack.begin(), local_rot_to_pack.end() );
1404 
1405  utility::subset_mapping rotamer_subset_map( rot_sets()->nrotamers() );
1406  rotamer_subset_map.reserve_destination_size( local_rot_to_pack.size() );
1407  for ( Size ii = 0; ii < local_rot_to_pack.size(); ++ii ) {
1408  rotamer_subset_map.set_next_correspondence( local_rot_to_pack[ ii ] );
1409  }
1410 
1411  RotamerSubsetsOP rsubset = create_rotamer_subsets_from_rot_to_pack( local_rot_to_pack );
1413  create_dense_pdig_from_rot_to_pack( local_rot_to_pack, rsubset );
1414 
1415  //core::Size nmoltenres = rot_sets()->nmoltenres();
1416  ObjexxFCL::FArray1D< int > rotamer_assignment( pose()->total_residue() );
1417  core::PackerEnergy rotamer_energy;
1418  utility::vector0< int > all_rots( local_rot_to_pack.size() );
1419  for ( Size ii = 0; ii < all_rots.size(); ++ii ) all_rots[ ii ] = ii+1;
1420 
1422  *pose(), task(), rsubset, dense_ig, all_rots,
1423  rotamer_assignment, rotamer_energy );
1424 
1426  result.first.resize( rot_sets()->nmoltenres() );
1427 
1428  for ( Size ii = 1; ii <= rot_sets()->nmoltenres(); ++ii ) {
1429  result.first[ ii ] = rotamer_subset_map.d2s( rotamer_assignment( rot_sets()->moltenres_2_resid( ii ) ));
1430  }
1431 
1432  /*TR << "Assignment:";
1433  for ( Size ii = 1; ii <= rot_sets()->nmoltenres(); ++ii ) {
1434  TR << " " << rotamer_assignment( rot_sets()->moltenres_2_resid( ii ));
1435  }
1436  TR << std::endl;*/
1437  result.second = rotamer_energy;
1438  return result;
1439 }
1440 
1441 
1444  utility::vector0< int > const & rot_to_pack,
1445  RotamerSubsetsOP rot_subsets
1446 )
1447 {
1448  using namespace core::pack::interaction_graph;
1449 
1450  core::Size nmoltenres = rot_sets()->nmoltenres();
1452  dense_ig->initialize( *rot_subsets );
1453  for ( Size ii = 1; ii <= rot_to_pack.size(); ++ii ) {
1454  Size const ii_moltenres = rot_subsets->moltenres_for_rotamer( ii );
1455  Size const ii_local_id = rot_subsets->rotid_on_moltenresidue( ii );
1456  Size const ii_old_rotid = rot_sets()->rotid_on_moltenresidue(rot_to_pack[ ii - 1 ]);
1457  dense_ig->add_to_nodes_one_body_energy(
1458  ii_moltenres,
1459  ii_local_id,
1460  ig()->get_one_body_energy_for_node_state( ii_moltenres, ii_old_rotid ));
1461  //std::cout << "Setting rotamer 1-body-energy " << ii_moltenres << " rot# " << ii_local_id << " (";
1462  //std::cout << rot_to_pack[ ii - 1 ] << ") = ";
1463  //std::cout << ig()->get_one_body_energy_for_node_state( ii_moltenres, ii_old_rotid) << std::endl;
1464  }
1465 
1466  for ( Size ii = 1; ii <= nmoltenres; ++ii ) {
1467  for ( Size jj = ii+1; jj <= nmoltenres; ++jj ) {
1468  if ( ig()->get_edge_exists( ii, jj ) ) {
1469  dense_ig->add_edge( ii, jj );
1470  for ( Size kk = 1, kk_end = rot_subsets->nrotamers_for_moltenres( ii ); kk <= kk_end; ++kk ) {
1471  Size const kk_old = rot_sets()->rotid_on_moltenresidue(
1472  rot_to_pack[ rot_subsets->moltenres_rotid_2_rotid( ii, kk ) - 1 ] );
1473  for ( Size ll = 1, ll_end = rot_subsets->nrotamers_for_moltenres( jj ); ll <= ll_end; ++ll ) {
1474  Size const ll_old = rot_sets()->rotid_on_moltenresidue(
1475  rot_to_pack[ rot_subsets->moltenres_rotid_2_rotid( jj, ll ) - 1 ] );
1476  dense_ig->set_two_body_energy_for_edge( ii, jj, kk, ll,
1477  ig()->get_two_body_energy_for_edge( ii, jj, kk_old, ll_old ) );
1478  //std::cout << "Setting energy for edge " << ii << " " << jj;
1479  //std::cout << " rotamer pair " << kk << " (" << kk_old << ") and " << ll << " (" << ll_old;
1480  //std::cout << " ) to " << ig()->get_two_body_energy_for_edge( ii, jj, kk_old, ll_old ) << std::endl;
1481  }
1482  }
1483  }
1484  }
1485  }
1486  return dense_ig;
1487 
1488 }
1489 
1491  PoseOP pose,
1494  RotamerSetsOP rotsets
1495 ) :
1496  parent( pose, task, ig, rotsets ),
1497  num_sa_( 5 ),
1498  sa_scale_( 0.05 ),
1499  ciBR_only_( false )
1500 {
1501  ig()->prepare_for_simulated_annealing();
1502 }
1503 
1505 
1508 {
1509  using namespace core::pack::rotamer_set;
1510  using namespace core::pack::interaction_graph;
1511  utility::vector0< int > local_rot_to_pack( rot_to_pack );
1512  /// SHOULD be in sorted order already, but make sure!
1513  std::sort( local_rot_to_pack.begin(), local_rot_to_pack.end() );
1514 
1515  utility::subset_mapping rotamer_subset_map( rot_sets()->nrotamers() );
1516  rotamer_subset_map.reserve_destination_size( local_rot_to_pack.size() );
1517  for ( Size ii = 0; ii < local_rot_to_pack.size(); ++ii ) {
1518  rotamer_subset_map.set_next_correspondence( local_rot_to_pack[ ii ] );
1519  }
1520 
1521  RotamerSubsetsOP rsubset = create_rotamer_subsets_from_rot_to_pack( local_rot_to_pack );
1522  FASTERInteractionGraphOP faster_ig =
1523  create_faster_ig_from_rot_to_pack( local_rot_to_pack, rsubset );
1524 
1525  //core::Size nmoltenres = rot_sets()->nmoltenres();
1526  ObjexxFCL::FArray1D< int > rotamer_assignment( pose()->total_residue() );
1527  core::PackerEnergy rotamer_energy;
1528  utility::vector0< int > all_rots( local_rot_to_pack.size() );
1529  for ( Size ii = 0; ii < all_rots.size(); ++ii ) all_rots[ ii ] = ii+1;
1530 
1531  { // scope
1532  using namespace ObjexxFCL;
1533  using namespace core::pack;
1534  using namespace core::pack::annealer;
1535 
1536  bool start_with_current = false;
1537  FArray1D_int current_rot_index( pose()->total_residue(), 0 );
1538  bool calc_rot_freq = false;
1539  FArray1D< core::PackerEnergy > rot_freq( faster_ig()->get_num_total_states(), 0.0 );
1540 
1541  FASTERAnnealer fa( rotamer_assignment, rotamer_energy, start_with_current,
1542  faster_ig, rsubset(), current_rot_index, calc_rot_freq, rot_freq );
1543 
1544  fa.set_ciBR_only( ciBR_only_ );
1547 
1548  fa.run();
1549  }
1550 
1551 
1553  result.first.resize( rot_sets()->nmoltenres() );
1554 
1555  for ( Size ii = 1; ii <= rot_sets()->nmoltenres(); ++ii ) {
1556  result.first[ ii ] = rotamer_subset_map.d2s( rotamer_assignment( rot_sets()->moltenres_2_resid( ii ) ));
1557  }
1558 
1559  /*TR << "Assignment:";
1560  for ( Size ii = 1; ii <= rot_sets()->nmoltenres(); ++ii ) {
1561  TR << " " << rotamer_assignment( rot_sets()->moltenres_2_resid( ii ));
1562  }
1563  TR << std::endl;*/
1564  result.second = rotamer_energy;
1565  return result;
1566 
1567 }
1568 
1571  utility::vector0< int > const & rot_to_pack,
1572  RotamerSubsetsOP rot_subsets
1573 )
1574 {
1575  using namespace core::pack::interaction_graph;
1576 
1577  core::Size nmoltenres = rot_sets()->nmoltenres();
1578  FASTERInteractionGraphOP faster_ig = new FASTERInteractionGraph( nmoltenres );
1579  faster_ig->initialize( *rot_subsets );
1580 
1581 
1582  /// If the rotamers are in a contiguous block and all have the same "aa" according to
1583  /// the PDInteractionGraph, then we can rapidly transfer the energies from the PDIG
1584  /// to the new dense interaction graph using the new get_aa_submatrix_energies_for_edge
1585  /// function; otherwise, we have to fall back on the old
1586  utility::vector1< int > aaind_for_moltres( nmoltenres, -1 );
1587 
1588  for ( Size ii = 1; ii <= rot_to_pack.size(); ++ii ) {
1589  Size const ii_moltenres = rot_subsets->moltenres_for_rotamer( ii );
1590  Size const ii_local_id = rot_subsets->rotid_on_moltenresidue( ii );
1591  Size const ii_old_rotid = rot_sets()->rotid_on_moltenresidue(rot_to_pack[ ii - 1 ]);
1592 
1593  if ( aaind_for_moltres[ ii_moltenres ] == -1 ) {
1594  aaind_for_moltres[ ii_moltenres ] = ig()->aatype_for_node_state( ii_moltenres, ii_old_rotid );
1595  } else if ( aaind_for_moltres[ ii_moltenres ] != 0 ) {
1596  if ( aaind_for_moltres[ ii_moltenres ] != ig()->aatype_for_node_state( ii_moltenres, ii_old_rotid ) ) {
1597  aaind_for_moltres[ ii_moltenres ] = 0;
1598  }
1599  }
1600 
1601  faster_ig->add_to_nodes_one_body_energy(
1602  ii_moltenres,
1603  ii_local_id,
1604  ig()->get_one_body_energy_for_node_state( ii_moltenres, ii_old_rotid ));
1605  //std::cout << "Setting rotamer 1-body-energy " << ii_moltenres << " rot# " << ii_local_id << " (";
1606  //std::cout << rot_to_pack[ ii - 1 ] << ") = ";
1607  //std::cout << ig()->get_one_body_energy_for_node_state( ii_moltenres, ii_old_rotid) << std::endl;
1608  }
1609 
1610  for ( Size ii = 1; ii <= nmoltenres; ++ii ) {
1611  for ( Size jj = ii+1; jj <= nmoltenres; ++jj ) {
1612  if ( ig()->get_edge_exists( ii, jj ) ) {
1613  if ( aaind_for_moltres[ ii ] > 0 && aaind_for_moltres[ jj ] > 0 ) {
1614  if ( ! ig()->get_sparse_aa_info_for_edge( ii, jj, aaind_for_moltres[ ii ], aaind_for_moltres[ jj ] )) {
1615  /// NO non-zero energies for this edge
1616  continue;
1617  }
1618  }
1619  faster_ig->add_edge( ii, jj );
1620  bool fast_edge_energy_transfer_successfull = false;
1621  if ( aaind_for_moltres[ ii ] > 0 && aaind_for_moltres[ jj ] > 0 ) {
1622  ObjexxFCL::FArray2D< core::PackerEnergy > edge_energies =
1623  ig()->get_aa_submatrix_energies_for_edge( ii, jj, aaind_for_moltres[ ii ], aaind_for_moltres[ jj ] );
1624  if ( edge_energies.size1() == rot_subsets->nrotamers_for_moltenres( jj ) &&
1625  edge_energies.size2() == rot_subsets->nrotamers_for_moltenres( ii ) ) {
1626  // Safe to transfer the edge energy table to the DenseIG
1627  fast_edge_energy_transfer_successfull = true;
1628  faster_ig->swap_edge_energies( ii, jj, edge_energies );
1629  } else {
1630  TR << "Surprisingly, edge " << ii << " " << jj << " did not have the right sized"
1631  << " edge energy table from the PDIG:" << rot_subsets->nrotamers_for_moltenres( ii )
1632  << " " << edge_energies.size2() << " " << rot_subsets->nrotamers_for_moltenres( jj )
1633  << " " << edge_energies.size1() << std::endl;
1634  }
1635  }
1636 
1637  if ( ! fast_edge_energy_transfer_successfull ) {
1638  for ( Size kk = 1, kk_end = rot_subsets->nrotamers_for_moltenres( ii ); kk <= kk_end; ++kk ) {
1639  Size const kk_old = rot_sets()->rotid_on_moltenresidue(
1640  rot_to_pack[ rot_subsets->moltenres_rotid_2_rotid( ii, kk ) - 1 ] );
1641  for ( Size ll = 1, ll_end = rot_subsets->nrotamers_for_moltenres( jj ); ll <= ll_end; ++ll ) {
1642  Size const ll_old = rot_sets()->rotid_on_moltenresidue(
1643  rot_to_pack[ rot_subsets->moltenres_rotid_2_rotid( jj, ll ) - 1 ] );
1644  faster_ig->set_two_body_energy_for_edge( ii, jj, kk, ll,
1645  ig()->get_two_body_energy_for_edge( ii, jj, kk_old, ll_old ) );
1646  //std::cout << "Setting energy for edge " << ii << " " << jj;
1647  //std::cout << " rotamer pair " << kk << " (" << kk_old << ") and " << ll << " (" << ll_old;
1648  //std::cout << " ) to " << ig()->get_two_body_energy_for_edge( ii, jj, kk_old, ll_old ) << std::endl;
1649  }
1650  }
1651  }
1652  }
1653  }
1654  }
1655  return faster_ig;
1656 
1657 }
1658 
1659 void FASTER_IG_Repacker::set_num_sa( int setting ) { num_sa_ = setting; }
1661 void FASTER_IG_Repacker::set_ciBR_only( bool setting ) { ciBR_only_ = setting; }
1662 
1663 
1664 }
1665 }