17 #include "Teuchos_CommHelpers.hpp"
19 #include "Teuchos_RawParameterListHelpers.hpp"
54 #ifdef HAVE_MUELU_AVATAR
57 #include "avatar_api.h"
63 RCP<const ParameterList> AvatarInterface::GetValidParameterList()
const {
64 RCP<ParameterList> validParamList =
rcp(
new ParameterList());
86 validParamList->set<
Teuchos::ParameterList>(
"avatar: muelu parameter mapping", pl_dummy,
"Mapping of MueLu to Avatar Parameters");
89 validParamList->
set<
int>(
"avatar: good class", int_dummy,
"Numeric code for class Avatar considers to be good");
92 validParamList->
set<
int>(
"avatar: heuristic", int_dummy,
"Numeric code for which heuristic we want to use");
98 validParamList->set<
int>(
"avatar: initial dummy variables", int_dummy,
"Number of dummy variables to add at the start");
101 validParamList->set<
int>(
"avatar: pre-class dummy variables", int_dummy,
"Number of dummy variables to add at the before the class");
104 validParamList->set<
int>(
"avatar: dummy value", int_dummy,
"Value of the dummy variables to add at the before/after the class");
106 return validParamList;
115 if (comm_->getRank() == 0) {
117 for (Teuchos_Ordinal i = 0; i < tf.
size(); i++) {
119 std::stringstream ss;
122 treelist[i] = ss.str();
130 void AvatarInterface::Setup() {
132 if (comm_.is_null())
throw std::runtime_error(
"MueLu::AvatarInterface::Setup(): Communicator cannot be null");
135 if (params_.isParameter(
"avatar: decision tree strings"))
138 avatarStrings_ = ReadFromFiles(
"avatar: decision tree files");
140 if (params_.isParameter(
"avatar: names strings"))
143 namesStrings_ = ReadFromFiles(
"avatar: names files");
145 if (params_.isParameter(
"avatar: bounds file"))
146 boundsString_ = ReadFromFiles(
"avatar: bounds file");
150 if (comm_->getRank() == 0) {
153 const int namesfile_is_a_string = 1;
154 const int treesfile_is_a_string = 1;
155 avatarHandle_ = avatar_load(const_cast<char*>(filestem_[0].c_str()), const_cast<char*>(namesStrings_[0].c_str()), namesfile_is_a_string, const_cast<char*>(avatarStrings_[0].c_str()), treesfile_is_a_string);
159 avatarGoodClass_ = params_.get<
int>(
"avatar: good class");
161 heuristicToUse_ = params_.get<
int>(
"avatar: heuristic");
164 UnpackMueLuMapping();
168 void AvatarInterface::Cleanup() {
169 avatar_cleanup(avatarHandle_);
174 void AvatarInterface::GenerateFeatureString(
const Teuchos::ParameterList& problemFeatures, std::string& featureString)
const {
176 std::stringstream ss;
179 if (params_.isParameter(
"avatar: initial dummy variables")) {
180 int num_dummy = params_.get<
int>(
"avatar: initial dummy variables");
181 int dummy_value = params_.get(
"avatar: dummy value", 666);
183 for (
int i = 0; i < num_dummy; i++)
184 ss << dummy_value <<
",";
190 if (i != problemFeatures.
begin()) ss <<
",";
193 featureString = ss.str();
197 void AvatarInterface::UnpackMueLuMapping() {
205 mueluParameterName_.resize(numParams);
206 avatarParameterName_.resize(numParams);
207 mueluParameterValues_.resize(numParams);
208 avatarParameterValues_.resize(numParams);
211 std::stringstream ss;
212 ss <<
"param" << idx;
217 mueluParameterName_[idx] = sublist.
get<std::string>(
"muelu parameter");
218 avatarParameterName_[idx] = sublist.
get<std::string>(
"avatar parameter");
231 if (idx != numParams)
232 throw std::runtime_error(
"MueLu::AvatarInterface::UnpackMueLuMapping(): 'avatar: muelu parameter mapping' has unknown fields");
235 std::string AvatarInterface::ParamsToString(
const std::vector<int>& indices)
const {
236 std::stringstream ss;
237 for (Teuchos_Ordinal i = 0; i < avatarParameterValues_.size(); i++) {
238 ss <<
"," << avatarParameterValues_[i][indices[i]];
242 if (params_.isParameter(
"avatar: pre-class dummy variables")) {
243 int num_dummy = params_.get<
int>(
"avatar: pre-class dummy variables");
244 int dummy_value = params_.get(
"avatar: dummy value", 666);
245 for (
int i = 0; i < num_dummy; i++)
246 ss <<
"," << dummy_value;
253 void AvatarInterface::SetIndices(
int id, std::vector<int>& indices)
const {
255 int numParams = (int)avatarParameterValues_.size();
257 for (
int i = 0; i < numParams; i++) {
258 int div = avatarParameterValues_[i].size();
259 int mod = curr_id % div;
261 curr_id = (curr_id - mod) / div;
268 int numParams = (int)avatarParameterValues_.size();
270 for (
int i = 0; i < numParams; i++) {
271 int div = avatarParameterValues_[i].size();
272 int mod = curr_id % div;
273 pl.
set(mueluParameterName_[i], mueluParameterValues_[i][mod]);
274 curr_id = (curr_id - mod) / div;
281 std::string paramString;
283 if (comm_->getRank() == 0) {
285 if (!avatarHandle_)
throw std::runtime_error(
"MueLu::AvatarInterface::SetMueLuParameters(): Setup has not been run");
288 std::string trialString;
289 GenerateFeatureString(problemFeatures, trialString);
292 int numParams = (int)avatarParameterValues_.size();
293 std::vector<int> indices(numParams);
294 std::vector<int> sizes(numParams);
296 for (
int i = 0; i < numParams; i++) {
297 sizes[i] = avatarParameterValues_[i].size();
298 num_combos *= avatarParameterValues_[i].size();
300 GetOStream(
Runtime0) <<
"MueLu::AvatarInterface: Testing " << num_combos <<
" option combinations" << std::endl;
305 int num_classes = avatar_num_classes(avatarHandle_);
306 std::vector<int> predictions(num_combos, 0);
307 std::vector<float> probabilities(num_classes * num_combos, 0);
309 std::string testString;
310 for (
int i = 0; i < num_combos; i++) {
311 SetIndices(i, indices);
313 testString += trialString + ParamsToString(indices) +
",0\n";
316 std::cout <<
"** Avatar TestString ***\n"
317 << testString << std::endl;
319 int bound_check =
true;
320 if (params_.isParameter(
"avatar: bounds file"))
321 bound_check = checkBounds(testString, boundsString_);
325 const int test_data_is_a_string = 1;
326 avatar_test(avatarHandle_, const_cast<char*>(testString.c_str()), test_data_is_a_string, predictions.data(), probabilities.data());
329 std::vector<int> acceptableCombos;
330 acceptableCombos.reserve(100);
331 for (
int i = 0; i < num_combos; i++) {
332 if (predictions[i] == avatarGoodClass_) acceptableCombos.push_back(i);
334 GetOStream(
Runtime0) <<
"MueLu::AvatarInterface: " << acceptableCombos.size() <<
" acceptable option combinations found" << std::endl;
337 int chosen_option_id = 0;
338 if (acceptableCombos.size() == 0) {
339 GetOStream(
Runtime0) <<
"WARNING: MueLu::AvatarInterface: found *no* combinations of options which it believes will perform well on this problem" << std::endl
340 <<
" An arbitrary set of options will be chosen instead" << std::endl;
345 if (acceptableCombos.size() == 1) {
346 chosen_option_id = acceptableCombos[0];
348 switch (heuristicToUse_) {
350 chosen_option_id = hybrid(probabilities.data(), acceptableCombos);
353 chosen_option_id = highProb(probabilities.data(), acceptableCombos);
359 chosen_option_id = acceptableCombos[0];
362 chosen_option_id = lowCrash(probabilities.data(), acceptableCombos);
365 chosen_option_id = weighted(probabilities.data(), acceptableCombos);
373 if (bound_check == 0) {
374 GetOStream(
Runtime0) <<
"WARNING: Extrapolation risk detected, setting drop tolerance to 0" << std::endl;
375 GenerateMueLuParametersFromIndex(0, avatarParams);
377 GenerateMueLuParametersFromIndex(chosen_option_id, avatarParams);
381 Teuchos::updateParametersAndBroadcast(outArg(avatarParams), outArg(mueluParams), *comm_, 0, overwrite);
385 std::stringstream ss(trialString);
386 std::vector<double> vect;
391 if (ss.peek() ==
',') ss.ignore();
394 std::stringstream ssBounds(boundsString[0]);
395 std::vector<double> boundsVect;
397 while (ssBounds >> b) {
398 boundsVect.push_back(b);
399 if (ssBounds.peek() ==
',') ssBounds.ignore();
402 int min_idx = (int)std::min(vect.size(), boundsVect.size() / 2);
404 bool inbounds =
true;
405 for (
int i = 0; inbounds && i < min_idx; i++)
406 inbounds = boundsVect[2 * i] <= vect[i] && vect[i] <= boundsVect[2 * i + 1];
408 return (
int)inbounds;
411 int AvatarInterface::hybrid(
float* probabilities, std::vector<int> acceptableCombos)
const {
412 float low_crash = probabilities[0];
413 float best_prob = probabilities[2];
416 int chosen_option_id = acceptableCombos[0];
417 for (
int x = 0; x < (int)acceptableCombos.size(); x++) {
418 this_combo = acceptableCombos[x] * 3;
419 diff = probabilities[this_combo] - low_crash;
424 low_crash = probabilities[this_combo];
425 best_prob = probabilities[this_combo + 2];
426 chosen_option_id = acceptableCombos[x];
431 else if (diff <= 0 && probabilities[this_combo + 2] > best_prob) {
432 low_crash = probabilities[this_combo];
433 best_prob = probabilities[this_combo + 2];
434 chosen_option_id = acceptableCombos[x];
437 return chosen_option_id;
440 int AvatarInterface::highProb(
float* probabilities, std::vector<int> acceptableCombos)
const {
441 float high_prob = probabilities[2];
443 int chosen_option_id = acceptableCombos[0];
444 for (
int x = 0; x < (int)acceptableCombos.size(); x++) {
445 this_combo = acceptableCombos[x] * 3;
448 if (probabilities[this_combo + 2] > high_prob) {
449 high_prob = probabilities[this_combo + 2];
450 chosen_option_id = acceptableCombos[x];
453 return chosen_option_id;
456 int AvatarInterface::lowCrash(
float* probabilities, std::vector<int> acceptableCombos)
const {
457 float low_crash = probabilities[0];
459 int chosen_option_id = acceptableCombos[0];
460 for (
int x = 0; x < (int)acceptableCombos.size(); x++) {
461 this_combo = acceptableCombos[x] * 3;
464 if (probabilities[this_combo] < low_crash) {
465 low_crash = probabilities[this_combo];
466 chosen_option_id = acceptableCombos[x];
469 return chosen_option_id;
472 int AvatarInterface::weighted(
float* probabilities, std::vector<int> acceptableCombos)
const {
473 float low_crash = probabilities[0];
474 float best_prob = probabilities[2];
477 int chosen_option_id = acceptableCombos[0];
478 for (
int x = 0; x < (int)acceptableCombos.size(); x++) {
479 this_combo = acceptableCombos[x] * 3;
480 diff = probabilities[this_combo] - low_crash;
485 low_crash = probabilities[this_combo];
486 best_prob = probabilities[this_combo + 2];
487 chosen_option_id = acceptableCombos[x];
492 else if (diff <= .1 && probabilities[this_combo + 2] > best_prob) {
493 low_crash = probabilities[this_combo];
494 best_prob = probabilities[this_combo + 2];
495 chosen_option_id = acceptableCombos[x];
498 return chosen_option_id;
503 #endif // HAVE_MUELU_AVATAR
ConstIterator end() const
std::ostream & leftshift(std::ostream &os, bool printFlags=true) const
T & get(const std::string &name, T def_value)
One-liner description of what is happening.
Ordinal numParams() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
bool isSublist(const std::string &name) const
params_t::ConstIterator ConstIterator
ConstIterator begin() const
void resize(size_type new_size, const value_type &x=value_type())
const ParameterEntry & entry(ConstIterator i) const
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")