PageRenderTime 54ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/core/Core/ParadigmComponents/States.cpp

https://github.com/mworks/mworks
C++ | 399 lines | 259 code | 121 blank | 19 comment | 54 complexity | 68c92c3ebd307306d9cac682065c487d MD5 | raw file
  1. /**
  2. * States.cpp
  3. *
  4. * History:
  5. * ??/??/?? ??? - Created
  6. * Paul Janknas on 05/16/05 - fixed spacing, added functionality to state
  7. * class to add a name so users can see states by name.
  8. *
  9. * Copyright 2005 MIT. All rights reserved.
  10. */
  11. #include "States.h"
  12. #include "Experiment.h"
  13. #include <string>
  14. #include "ComponentRegistry.h"
  15. #include "ComponentInfo.h"
  16. #include "ParameterValue.h"
  17. #include "SequentialSelection.h"
  18. #include "RandomWORSelection.h"
  19. #include "RandomWithReplacementSelection.h"
  20. #include <boost/foreach.hpp>
  21. BEGIN_NAMESPACE_MW
  22. void State::describeComponent(ComponentInfo &info) {
  23. Component::describeComponent(info);
  24. // "description" is no longer used but is still present in many old experiments
  25. info.addIgnoredParameter("description");
  26. }
  27. State::State() :
  28. experiment(GlobalCurrentExperiment)
  29. { }
  30. State::State(const ParameterValueMap &parameters) :
  31. Component(parameters),
  32. experiment(GlobalCurrentExperiment)
  33. { }
  34. void State::action() {
  35. currentState->setValue(getCompactID());
  36. shared_ptr<Experiment> experiment_shared(getExperiment());
  37. if (experiment_shared) {
  38. experiment_shared->announceLocalVariables();
  39. }
  40. updateCurrentScopedVariableContext();
  41. }
  42. weak_ptr<State> State::next() {
  43. shared_ptr<State> sharedParent = getParent();
  44. if (!sharedParent) {
  45. throw SimpleException("Internal error: state has no parent");
  46. }
  47. sharedParent->updateCurrentScopedVariableContext();
  48. reset();
  49. return sharedParent;
  50. }
  51. void State::updateHierarchy() {
  52. if (auto sharedParent = getParent()) {
  53. setExperiment(sharedParent->getExperiment());
  54. }
  55. }
  56. shared_ptr<ScopedVariableContext> State::getLocalScopedVariableContext() const {
  57. if (auto sharedParent = getParent()) {
  58. return sharedParent->getLocalScopedVariableContext();
  59. }
  60. return nullptr;
  61. }
  62. void State::updateCurrentScopedVariableContext() {
  63. if (auto sharedParent = getParent()) {
  64. sharedParent->updateCurrentScopedVariableContext();
  65. }
  66. }
  67. bool State::isInterruptible() const {
  68. if (!interruptible) {
  69. return false;
  70. }
  71. shared_ptr<State> sharedParent(getParent());
  72. if (sharedParent) {
  73. return sharedParent->isInterruptible();
  74. }
  75. return true;
  76. }
  77. const std::string ContainerState::INTERRUPTIBLE("interruptible");
  78. void ContainerState::describeComponent(ComponentInfo &info) {
  79. State::describeComponent(info);
  80. info.addParameter(INTERRUPTIBLE, "YES");
  81. }
  82. ContainerState::ContainerState() {
  83. setName("ContainerState");
  84. requestVariableContext();
  85. }
  86. ContainerState::ContainerState(const ParameterValueMap &parameters) :
  87. State(parameters)
  88. {
  89. setInterruptible(bool(parameters[INTERRUPTIBLE]));
  90. requestVariableContext();
  91. }
  92. void ContainerState::requestVariableContext() {
  93. if (auto sharedExperiment = getExperiment()) {
  94. local_variable_context = sharedExperiment->createNewContext();
  95. }
  96. }
  97. void ContainerState::updateHierarchy() {
  98. State::updateHierarchy();
  99. if (!local_variable_context) {
  100. merror(M_SYSTEM_MESSAGE_DOMAIN, "Invalid variable context in state object");
  101. local_variable_context = shared_ptr<ScopedVariableContext>(new ScopedVariableContext(NULL));
  102. }
  103. if (auto sharedParent = getParent()) {
  104. if (auto parentContext = sharedParent->getLocalScopedVariableContext()) {
  105. local_variable_context->inheritFrom(parentContext);
  106. } else {
  107. merror(M_SYSTEM_MESSAGE_DOMAIN, "Invalid parent variable context");
  108. //throw("I don't know what will happen here yet...");
  109. //local_variable_context = new ScopedVariableContext();// DEAL WITH THIS EVENTUALLY
  110. }
  111. }
  112. shared_ptr<State> self_ptr = component_shared_from_this<State>();
  113. BOOST_FOREACH( shared_ptr<State> child, *list ) {
  114. // recurse down the hierarchy
  115. child->setParent(self_ptr);
  116. child->updateHierarchy();
  117. }
  118. }
  119. void ContainerState::reset() {
  120. accessed = false;
  121. BOOST_FOREACH( shared_ptr<State> child, *list ) {
  122. // call recursively down the experiment hierarchy
  123. child->reset();
  124. }
  125. }
  126. shared_ptr<ScopedVariableContext> ContainerState::getLocalScopedVariableContext() const {
  127. return local_variable_context;
  128. }
  129. void ContainerState::updateCurrentScopedVariableContext() {
  130. shared_ptr<ScopedVariableEnvironment> environment_shared = getExperiment();
  131. if (environment_shared) {
  132. environment_shared->setCurrentContext(local_variable_context);
  133. shared_ptr<State> parent_shared(getParent());
  134. if (parent_shared) {
  135. shared_ptr<ScopedVariableContext> parentContext = parent_shared->getLocalScopedVariableContext();
  136. if (parentContext) {
  137. int numScopedVars = local_variable_context->getNFields();
  138. for (int i=0; i<numScopedVars; ++i) {
  139. if (local_variable_context->getTransparency(i) == M_TRANSPARENT) {
  140. local_variable_context->setWithTransparency(i, parentContext->get(i));
  141. }
  142. }
  143. }
  144. }
  145. } else {
  146. // TODO: better throw
  147. throw SimpleException("Cannot update scoped variable context without a valid environment");
  148. }
  149. }
  150. void ContainerState::addChild(std::map<std::string, std::string> parameters,
  151. ComponentRegistry *reg,
  152. shared_ptr<mw::Component> child)
  153. {
  154. auto state = boost::dynamic_pointer_cast<State>(child);
  155. if (!state) {
  156. throw SimpleException("Attempt to add non-paradigm component object as child of a paradigm component");
  157. }
  158. list->push_back(state);
  159. state->setParent(component_shared_from_this<State>());
  160. state->updateHierarchy();
  161. }
  162. const std::string ListState::SELECTION("selection");
  163. const std::string ListState::NSAMPLES("nsamples");
  164. const std::string ListState::SAMPLING_METHOD("sampling_method");
  165. void ListState::describeComponent(ComponentInfo &info) {
  166. ContainerState::describeComponent(info);
  167. info.addParameter(SELECTION, "sequential");
  168. info.addParameter(NSAMPLES, "1");
  169. info.addParameter(SAMPLING_METHOD, "cycles");
  170. }
  171. ListState::ListState() :
  172. selection_type(M_SEQUENTIAL),
  173. nsamples(1),
  174. sampling_method(M_CYCLES)
  175. { }
  176. template<>
  177. SelectionType ParameterValue::convert(const std::string &s, ComponentRegistryPtr reg) {
  178. std::string selection_string(boost::algorithm::to_lower_copy(s));
  179. if (selection_string == "sequential") {
  180. return M_SEQUENTIAL;
  181. } else if (selection_string == "sequential_ascending") {
  182. return M_SEQUENTIAL_ASCENDING;
  183. } else if (selection_string == "sequential_descending") {
  184. return M_SEQUENTIAL_DESCENDING;
  185. } else if (selection_string == "random_with_replacement") {
  186. return M_RANDOM_WITH_REPLACEMENT;
  187. } else if (selection_string == "random_without_replacement") {
  188. return M_RANDOM_WOR;
  189. } else {
  190. throw SimpleException(M_PARADIGM_MESSAGE_DOMAIN, "invalid value for parameter \"selection\"", s);
  191. }
  192. }
  193. template<>
  194. SampleType ParameterValue::convert(const std::string &s, ComponentRegistryPtr reg) {
  195. std::string sampling_method_string(boost::algorithm::to_lower_copy(s));
  196. if (sampling_method_string == "cycles") {
  197. return M_CYCLES;
  198. } else if (sampling_method_string == "samples") {
  199. return M_SAMPLES;
  200. } else {
  201. throw SimpleException(M_PARADIGM_MESSAGE_DOMAIN, "invalid value for parameter \"sampling_method\"", s);
  202. }
  203. }
  204. ListState::ListState(const ParameterValueMap &parameters) :
  205. ContainerState(parameters),
  206. selection_type(parameters[SELECTION]),
  207. nsamples(parameters[NSAMPLES]),
  208. sampling_method(parameters[SAMPLING_METHOD])
  209. {
  210. if (nsamples < 1) {
  211. throw SimpleException(M_PARADIGM_MESSAGE_DOMAIN, "\"nsamples\" must be greater than or equal to 1");
  212. }
  213. }
  214. weak_ptr<State> ListState::next() {
  215. if(!selection){
  216. throw SimpleException("Attempt to draw from an invalid selection object");
  217. }
  218. if (hasMoreChildrenToRun()) {
  219. //mprintf("I am %s, and I have more children to run!", name);
  220. int index;
  221. try{
  222. index = selection->draw();
  223. } catch(std::exception& e){
  224. index = -1; // just a bandaid for now
  225. }
  226. shared_ptr<State> thestate;
  227. if ((index < 0) || !(thestate = getList()[index])) {
  228. mwarning(M_PARADIGM_MESSAGE_DOMAIN,
  229. "List state returned invalid state at index %d",
  230. index);
  231. return State::next();
  232. }
  233. shared_ptr<State> thestate_parent(thestate->getParent());
  234. if (thestate_parent.get() != this) {
  235. // this ensures that we find our way back,
  236. // even if something is screwed up
  237. thestate->setParent(component_shared_from_this<State>());
  238. thestate->updateHierarchy(); // TODO: might want to do this differently
  239. }
  240. thestate->updateCurrentScopedVariableContext();
  241. return thestate;
  242. } else {
  243. return State::next();
  244. }
  245. }
  246. void ListState::reset() {
  247. ContainerState::reset();
  248. if(selection != NULL) {
  249. selection->reset();
  250. } else {
  251. mwarning(M_PARSER_MESSAGE_DOMAIN,"attempt to reset NULL selection object");
  252. }
  253. }
  254. void ListState::finalize(std::map<std::string, std::string> parameters, ComponentRegistry *reg) {
  255. long N = nsamples;
  256. if (sampling_method == M_CYCLES) {
  257. N *= getNItems();
  258. }
  259. Selection *selection = NULL;
  260. switch(selection_type){
  261. case M_SEQUENTIAL:
  262. case M_SEQUENTIAL_ASCENDING:
  263. selection = new SequentialSelection(N);
  264. break;
  265. case M_SEQUENTIAL_DESCENDING:
  266. selection = new SequentialSelection(N, false);
  267. break;
  268. case M_RANDOM_WITH_REPLACEMENT:
  269. selection = new RandomWithReplacementSelection(N);
  270. break;
  271. case M_RANDOM_WOR:
  272. selection = new RandomWORSelection(N);
  273. break;
  274. }
  275. shared_ptr<Selection> sel_ptr(selection);
  276. attachSelection(sel_ptr);
  277. }
  278. END_NAMESPACE_MW