MonteCarloGenerate: Provide more metadata on dispersions (#1608)

* Add type, dispersion, min_value, max_value and other relevant internal
  members of MonteCarloVariable* classes to the output of
  MonteCarlo_Meta_data_output. Motivation is for users wanting to post-process
  dispersion parameters used during generation of runs
* Protect against invalid memory access when length of values is zero in
  MonteCarloVariableRandomStringSet::generate_assignment(). Add a new
  verif sim warning case to cover these new lines
* Update new verif data for SIM_mc_generation to support these changes

Closes #1574

Co-authored-by: Dan Jordan <daniel.d.jordan@nasa.gov>
This commit is contained in:
ddj116 2023-12-01 10:09:17 -06:00 committed by GitHub
parent 9ead0a28be
commit 483cacfafd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 226 additions and 61 deletions

View File

@ -65,8 +65,10 @@ class MonteCarloVariable
const std::string & get_command() const {return command;}
const std::string & get_variable_name() const {return variable_name;}
const std::string & get_assignment() const {return assignment;}
MonteCarloVariableType get_type() const {return type;}
virtual MonteCarloVariableType get_type() const {return type;}
virtual std::string get_type_str() const;
virtual unsigned int get_seed() const {return 0;}
virtual std::string summarize_variable() const;
protected:
void insert_units();

View File

@ -68,6 +68,8 @@ class MonteCarloVariableFile : public MonteCarloVariable
virtual ~MonteCarloVariableFile(){};
void initialize_file();
void generate_assignment();
virtual std::string summarize_variable() const;
void register_dependent( MonteCarloVariableFile *);
virtual void shutdown() {file.close();}

View File

@ -40,7 +40,6 @@ class MonteCarloVariableRandom : public MonteCarloVariable
virtual ~MonteCarloVariableRandom(){};
unsigned int get_seed() const {return seed_m;} // override but SWIG cannot process the
// override keyword
private: // and undefined:
MonteCarloVariableRandom( const MonteCarloVariableRandom & );
MonteCarloVariableRandom& operator = (const MonteCarloVariableRandom&);

View File

@ -44,6 +44,7 @@ class MonteCarloVariableRandomNormal : public MonteCarloVariableRandom
virtual ~MonteCarloVariableRandomNormal(){};
virtual void generate_assignment();
virtual std::string summarize_variable() const;
void truncate(double limit, TruncationType type = StandardDeviation);
void truncate(double min, double max, TruncationType type = StandardDeviation);
void truncate_low(double limit, TruncationType type = StandardDeviation);

View File

@ -43,6 +43,7 @@ class MonteCarloVariableRandomStringSet : public MonteCarloVariableRandomUniform
virtual ~MonteCarloVariableRandomStringSet(){};
virtual void generate_assignment();
virtual std::string summarize_variable() const;
void add_string(std::string);
private: // and undefined:
MonteCarloVariableRandomStringSet(const MonteCarloVariableRandomStringSet&);

View File

@ -35,6 +35,7 @@ class MonteCarloVariableRandomUniform : public MonteCarloVariableRandom
double upper_bound = 1.0);
virtual ~MonteCarloVariableRandomUniform(){};
virtual void generate_assignment();
virtual std::string summarize_variable() const;
private: // and undefined:
MonteCarloVariableRandomUniform( const MonteCarloVariableRandomUniform & );
MonteCarloVariableRandomUniform& operator = (
@ -59,6 +60,7 @@ class MonteCarloVariableRandomUniformInt : public MonteCarloVariableRandom
double upper_bound = 1);
virtual ~MonteCarloVariableRandomUniformInt(){};
virtual void generate_assignment();
virtual std::string summarize_variable() const;
private: // and undefined:
MonteCarloVariableRandomUniformInt(const MonteCarloVariableRandomUniformInt&);
MonteCarloVariableRandomUniformInt& operator = (

View File

@ -0,0 +1,19 @@
monte_carlo.mc_master.activate("RUN_WARN_no_string_values")
monte_carlo.mc_master.set_num_runs(1)
print('*********************************************************************************')
print('this message is expected:')
print('No values for MonteCarloVariableRandomStringSet')
print('Length of values vector is zero for variable: test.x_string, Did you forget to call add_string()?')
print('*********************************************************************************')
# add a string variable but forget to give it options to randomize
mc_var = trick.MonteCarloVariableRandomStringSet( "test.x_string", 3)
#mc_var.add_string("\"ABC\"")
#mc_var.add_string("\"DEF\"")
#mc_var.add_string("'GHIJKL'")
mc_var.thisown = False
monte_carlo.mc_master.add_variable(mc_var)
monte_carlo.mc_master.generate_meta_data = True

View File

@ -10,32 +10,32 @@
- 0 variables of undefined type
********************* LIST OF VARIABLES, TYPES****************
test.x_boolean, Random
test.x_file_lookup[0], Prescribed
test.x_file_lookup[1], Prescribed
test.x_file_lookup[2], Prescribed
test.x_fixed_value_double, Constant
test.x_fixed_value_int, Constant
test.x_fixed_value_string, Constant
test.x_integer, Random
test.x_line_command, Calculated
test.x_normal, Random
test.x_normal_length, Random
test.x_normal_trunc[0], Random
test.x_normal_trunc[1], Random
test.x_normal_trunc[2], Random
test.x_normal_trunc[3], Random
test.x_normal_trunc[4], Random
test.x_semi_fixed_value, Constant
test.x_string, Random
test.x_uniform, Random
test.x_boolean: type=Random, dispersion=Uniform, min_value=0, max_value=1, seed=4, values=[False,True,]
test.x_file_lookup[0]: type=Prescribed, max_skip=0, is_dependent=0, filename=Modified_data/datafile.txt, column_number=3, first_column_number=1
test.x_file_lookup[1]: type=Prescribed, max_skip=0, is_dependent=1, filename=Modified_data/datafile.txt, column_number=2, first_column_number=1
test.x_file_lookup[2]: type=Prescribed, max_skip=0, is_dependent=1, filename=Modified_data/datafile.txt, column_number=1, first_column_number=1
test.x_fixed_value_double: type=Constant
test.x_fixed_value_int: type=Constant
test.x_fixed_value_string: type=Constant
test.x_integer: type=Random dispersion=Uniform, min_value=0, max_value=2, seed=1
test.x_line_command: type=Calculated
test.x_normal: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=0, max_value=0, seed=2
test.x_normal_length: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=0, max_value=0, seed=2
test.x_normal_trunc[0]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=9, max_value=11, seed=2
test.x_normal_trunc[1]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=9.5, max_value=10.7, seed=2
test.x_normal_trunc[2]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=9.9, max_value=11, seed=2
test.x_normal_trunc[3]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=9.9, max_value=0, seed=2
test.x_normal_trunc[4]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=0, max_value=4, seed=2
test.x_semi_fixed_value: type=Constant
test.x_string: type=Random, dispersion=Uniform, min_value=0, max_value=1, seed=3, values=["ABC","DEF",'GHIJKL',]
test.x_uniform: type=Random, dispersion=Uniform, min_value=10, max_value=20, seed=0
**************************************************************
*********** LIST OF EXECUTABLE FILES AND FUNCTIONS ***********
test.standalone_function( test.x_normal)
test.standalone_function( test.x_normal): type=Execute
***
Modified_data/sample.py
Modified_data/sample.py: type=Execute
***
**************************************************************

View File

@ -14,32 +14,32 @@ Sending meta-data to top-level directory.
- 0 variables of undefined type
********************* LIST OF VARIABLES, TYPES****************
test.x_boolean, Random
test.x_file_lookup[0], Prescribed
test.x_file_lookup[1], Prescribed
test.x_file_lookup[2], Prescribed
test.x_fixed_value_double, Constant
test.x_fixed_value_int, Constant
test.x_fixed_value_string, Constant
test.x_integer, Random
test.x_line_command, Calculated
test.x_normal, Random
test.x_normal_length, Random
test.x_normal_trunc[0], Random
test.x_normal_trunc[1], Random
test.x_normal_trunc[2], Random
test.x_normal_trunc[3], Random
test.x_normal_trunc[4], Random
test.x_semi_fixed_value, Constant
test.x_string, Random
test.x_uniform, Random
test.x_boolean: type=Random, dispersion=Uniform, min_value=0, max_value=1, seed=4, values=[False,True,]
test.x_file_lookup[0]: type=Prescribed, max_skip=0, is_dependent=0, filename=Modified_data/datafile.txt, column_number=3, first_column_number=1
test.x_file_lookup[1]: type=Prescribed, max_skip=0, is_dependent=1, filename=Modified_data/datafile.txt, column_number=2, first_column_number=1
test.x_file_lookup[2]: type=Prescribed, max_skip=0, is_dependent=1, filename=Modified_data/datafile.txt, column_number=1, first_column_number=1
test.x_fixed_value_double: type=Constant
test.x_fixed_value_int: type=Constant
test.x_fixed_value_string: type=Constant
test.x_integer: type=Random dispersion=Uniform, min_value=0, max_value=2, seed=1
test.x_line_command: type=Calculated
test.x_normal: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=0, max_value=0, seed=2
test.x_normal_length: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=0, max_value=0, seed=2
test.x_normal_trunc[0]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=9, max_value=11, seed=2
test.x_normal_trunc[1]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=9.5, max_value=10.7, seed=2
test.x_normal_trunc[2]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=9.9, max_value=11, seed=2
test.x_normal_trunc[3]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=9.9, max_value=0, seed=2
test.x_normal_trunc[4]: type=Random, dispersion=Normal, mean=10, stddev=2, min_value=0, max_value=4, seed=2
test.x_semi_fixed_value: type=Constant
test.x_string: type=Random, dispersion=Uniform, min_value=0, max_value=1, seed=3, values=["ABC","DEF",'GHIJKL',]
test.x_uniform: type=Random, dispersion=Uniform, min_value=10, max_value=20, seed=0
**************************************************************
*********** LIST OF EXECUTABLE FILES AND FUNCTIONS ***********
test.standalone_function( test.x_normal)
test.standalone_function( test.x_normal): type=Execute
***
Modified_data/sample.py
Modified_data/sample.py: type=Execute
***
**************************************************************

View File

@ -447,6 +447,9 @@ SIM_mc_generation:
RUN_WARN_overconstrained_config/input.py:
compare:
phase: -1
RUN_WARN_no_string_values/input.py:
compare:
phase: -1
MONTE_RUN_WARN_overconstrained_config/RUN_0/monte_input.py:
FAIL_config_error/input.py:
returns: 1

View File

@ -441,7 +441,7 @@ MonteCarloMaster::collate_meta_data()
// Capture and alphabetize all variable names with their respective variable
// type; count the number of each type.
std::list< std::string > variable_names;
std::list< std::string > variable_details;
std::list< std::string > exec_file_names;
std::list< std::pair < unsigned int, std::string> > random_variables;
unsigned int count_calc = 0;
@ -456,27 +456,27 @@ MonteCarloMaster::collate_meta_data()
// Unreachable case in current implementation.
// All current variable classes have been given a "type"
default:
variable_names.push_back (var_it->get_variable_name() + ", Undefined_type");
variable_details.push_back(var_it->summarize_variable());
count_undef++;
break;
case MonteCarloVariable::Calculated:
variable_names.push_back (var_it->get_variable_name() + ", Calculated");
variable_details.push_back (var_it->summarize_variable());
count_calc++;
break;
case MonteCarloVariable::Constant:
variable_names.push_back (var_it->get_variable_name() + ", Constant");
variable_details.push_back (var_it->summarize_variable());
count_const++;
break;
case MonteCarloVariable::Execute:
exec_file_names.push_back (var_it->get_variable_name());
exec_file_names.push_back (var_it->summarize_variable());
count_exec++;
break;
case MonteCarloVariable::Prescribed:
variable_names.push_back (var_it->get_variable_name() + ", Prescribed");
variable_details.push_back (var_it->summarize_variable());
count_presc++;
break;
case MonteCarloVariable::Random:
variable_names.push_back (var_it->get_variable_name() + ", Random");
variable_details.push_back (var_it->summarize_variable());
count_rand++;
std::pair< unsigned int, std::string> var(var_it->get_seed(),
var_it->get_variable_name());
@ -484,7 +484,7 @@ MonteCarloMaster::collate_meta_data()
break;
}
}
variable_names.sort();
variable_details.sort();
meta_data <<
"\n\n*************************** SUMMARY **************************\n" <<
@ -497,8 +497,8 @@ MonteCarloMaster::collate_meta_data()
count_undef << " variables of undefined type" <<
"\n\n********************* LIST OF VARIABLES, TYPES****************\n";
std::list< std::string >::iterator var_name_it = variable_names.begin();
for (; var_name_it != variable_names.end(); ++var_name_it) {
std::list< std::string >::iterator var_name_it = variable_details.begin();
for (; var_name_it != variable_details.end(); ++var_name_it) {
meta_data << (*var_name_it) << "\n";
}
meta_data <<

View File

@ -116,3 +116,48 @@ MonteCarloVariable::generate_command()
{
command = "\n" + variable_name + " = " + assignment;
}
/*****************************************************************************
get_type_str
Purpose:(Return the type of this variable as string. Meant to be overridden
by derived classes)
*****************************************************************************/
std::string MonteCarloVariable::get_type_str() const
{
switch (get_type()) {
// Unreachable case in current implementation.
// All current variable classes have been given a "type"
default:
return(std::string("Undefined_type"));
break;
case MonteCarloVariable::Calculated:
return(std::string("Calculated"));
break;
case MonteCarloVariable::Constant:
return(std::string("Constant"));
break;
case MonteCarloVariable::Execute:
return(std::string("Execute"));
break;
case MonteCarloVariable::Prescribed:
return(std::string("Prescribed"));
break;
case MonteCarloVariable::Random:
return(std::string("Random"));
break;
}
}
/*****************************************************************************
summarize_variable
Purpose:(Provide a string summarizing the attributes of this MonteCarloVariable)
*****************************************************************************/
std::string MonteCarloVariable::summarize_variable() const
{
std::ostringstream ss;
ss << variable_name << std::string(": type=") << get_type_str();
return (ss.str());
}

View File

@ -271,3 +271,17 @@ bool MonteCarloVariableFile::sort_by_col_num(
{
return left->get_column_number() < right->get_column_number();
}
/*****************************************************************************
summarize_variable
Purpose:(Provide a string summarizing the attributes of this MonteCarloVariable)
*****************************************************************************/
std::string MonteCarloVariableFile::summarize_variable() const
{
std::ostringstream ss;
ss << MonteCarloVariable::summarize_variable()
<< ", max_skip=" << max_skip << ", is_dependent=" << is_dependent
<< ", filename=" << filename << ", column_number=" << column_number
<< ", first_column_number=" << first_column_number;
return (ss.str());
}

View File

@ -16,6 +16,7 @@ PROGRAMMERS:
#include <limits>
#include <algorithm>
#include <assert.h>
#include <sstream> // ostringstream
/*****************************************************************************
Constructor
@ -105,6 +106,19 @@ MonteCarloVariableRandomNormal::generate_assignment()
assign_double(assignment_d);
}
/*****************************************************************************
summarize_variable
Purpose:(Provide a string summarizing the attributes of this MonteCarloVariable)
*****************************************************************************/
std::string MonteCarloVariableRandomNormal::summarize_variable() const
{
std::ostringstream ss;
ss << MonteCarloVariable::summarize_variable() << std::string(", dispersion=Normal")
<< ", mean=" << distribution.mean() << ", stddev=" << distribution.stddev()
<< ", min_value=" << min_value << ", max_value=" << max_value
<< ", seed=" << seed_m;
return (ss.str());
}
/*****************************************************************************
truncate
Purpose:(Truncates the normal distribution to be within +- limit.)

View File

@ -8,6 +8,10 @@ PROGRAMMERS:
(((Gary Turner) (OSR) (October 2019) (Antares) (Initial)))
(((Isaac Reaves) (NASA) (November 2022) (Integration into Trick Core)))
**********************************************************************/
#include <sstream> // ostringstream
#include "trick/message_type.h"
#include "trick/message_proto.h"
#include "trick/exec_proto.h"
#include "trick/mc_variable_random_string.hh"
/*****************************************************************************
@ -32,14 +36,47 @@ Purpose:(pick one string at random)
void
MonteCarloVariableRandomStringSet::generate_assignment()
{
// Protect against accessing 0th index of an empty list. In this case,
// generate_command() is never called
if (values.size() > 0) {
// generate a random number on the interval [0,1)
double pre_ix = distribution(random_generator);
// convert to an integer between 0 and max-index of the "values" vector.
size_t ix = static_cast<size_t> (pre_ix * values.size());
// send the string at that index to the command-generation.
// TODO: This fales if values.size() is zero!!!
assignment = values[ix];
generate_command();
} else {
std::string message =
std::string("File: ") + __FILE__ + ", Line: " +
std::to_string(__LINE__) + ", No values for MonteCarloVariableRandomStringSet\n"
"Length of values vector is zero for variable: " + variable_name + ", Did " +
"you forget to call add_string()?\n";
message_publish(MSG_WARNING, message.c_str());
}
}
/*****************************************************************************
summarize_variable
Purpose:(Provide a string summarizing the attributes of this MonteCarloVariable)
*****************************************************************************/
std::string MonteCarloVariableRandomStringSet::summarize_variable() const
{
std::ostringstream ss;
// TODO: Here we create a string in [val1, val2, ... ] form, but this is
// ambigious because if there's a comma in any value, parsing the resultant
// string from the MonteCarlo_Meta_data_output file could fail. What delimter
// or approach would be better? -Jordan 10/2023
ss << MonteCarloVariableRandomUniform::summarize_variable() << ", values=[";
if (values.size() > 0) {
for (auto val_it : values) {
ss << val_it << ",";
}
}
ss << "]";
return (ss.str());
}
/*****************************************************************************
add_string
Purpose:(Adds an option to the set of strings)
@ -64,3 +101,4 @@ MonteCarloVariableRandomStringSet::add_string( std::string new_string)
{
values.push_back(new_string);
}

View File

@ -7,6 +7,7 @@ PROGRAMMERS:
(((Gary Turner) (OSR) (October 2019) (Antares) (Initial)))
(((Isaac Reaves) (NASA) (November 2022) (Integration into Trick Core)))
**********************************************************************/
#include <sstream> // ostringstream
#include "trick/mc_variable_random_uniform.hh"
/*****************************************************************************
@ -33,6 +34,18 @@ MonteCarloVariableRandomUniform::generate_assignment()
assign_double(distribution(random_generator));
}
/*****************************************************************************
summarize_variable
Purpose:(Provide a string summarizing the attributes of this MonteCarloVariable)
*****************************************************************************/
std::string MonteCarloVariableRandomUniform::summarize_variable() const
{
std::ostringstream ss;
ss << MonteCarloVariable::summarize_variable() << std::string(", dispersion=Uniform")
<< ", min_value=" << distribution.min() << ", max_value=" << distribution.max()
<< ", seed=" << seed_m;
return (ss.str());
}
@ -59,3 +72,15 @@ MonteCarloVariableRandomUniformInt::generate_assignment()
{
assign_int(distribution(random_generator));
}
/*****************************************************************************
summarize_variable
Purpose:(Provide a string summarizing the attributes of this MonteCarloVariable)
*****************************************************************************/
std::string MonteCarloVariableRandomUniformInt::summarize_variable() const
{
std::ostringstream ss;
ss << MonteCarloVariable::summarize_variable() << std::string(" dispersion=Uniform,")
<< " min_value=" << distribution.min() << ", max_value=" << distribution.max()
<< ", seed=" << seed_m;
return (ss.str());
}