Browse Source

Merge branch 'master' of https://sselab.de/lab9/private/git/MRMC

Conflicts:
	src/parser/readLabFile.cpp

Additional refactoring, renamed tests.
tempestpy_adaptions
PBerger 12 years ago
parent
commit
59408b2ab4
  1. 40
      src/parser/Parser.cpp
  2. 14
      src/parser/Parser.h
  3. 46
      src/parser/readLabFile.cpp
  4. 8
      src/parser/readLabFile.h
  5. 3
      src/parser/readPrctlFile.cpp
  6. 2
      src/parser/readPrctlFile.h
  7. 17
      src/parser/readTraFile.cpp
  8. 8
      src/parser/readTraFile.h
  9. 8
      src/reward/RewardModel.h
  10. 71
      src/utility/Settings.cpp
  11. 11
      src/utility/Settings.h
  12. 0
      test/eigen/EigenSparseMatrixTest.cpp
  13. 2
      test/parser/ParseDtmcTest.cpp
  14. 2
      test/parser/ReadLabFileTest.cpp
  15. 2
      test/parser/ReadTraFileTest.cpp
  16. 2
      test/reward/RewardModelTest.cpp

40
src/parser/parser.cpp → src/parser/Parser.cpp

@ -1,4 +1,4 @@
#include "src/parser/parser.h"
#include "src/parser/Parser.h"
#if defined LINUX || defined MACOSX
# include <sys/mman.h>
@ -27,11 +27,9 @@ extern log4cplus::Logger logger;
* @param end New pointer will be written there
* @return Result of strtol()
*/
uint_fast64_t mrmc::parser::Parser::checked_strtol(const char* str, char** end)
{
uint_fast64_t mrmc::parser::Parser::checked_strtol(const char* str, char** end) {
uint_fast64_t res = strtol(str, end, 10);
if (str == *end)
{
if (str == *end) {
LOG4CPLUS_ERROR(logger, "Error while parsing integer. Next input token is not a number.");
LOG4CPLUS_ERROR(logger, "\tUpcoming input is: \"" << std::string(str, 0, 16) << "\"");
throw mrmc::exceptions::WrongFileFormatException("Error while parsing integer. Next input token is not a number.");
@ -45,8 +43,7 @@ uint_fast64_t mrmc::parser::Parser::checked_strtol(const char* str, char** end)
* @param buf String buffer
* @return pointer to first non-whitespace character
*/
char* mrmc::parser::Parser::skipWS(char* buf)
{
char* mrmc::parser::Parser::skipWS(char* buf) {
while ((*buf == ' ') || (*buf == '\t') || (*buf == '\n') || (*buf == '\r')) buf++;
return buf;
}
@ -57,33 +54,29 @@ char* mrmc::parser::Parser::skipWS(char* buf)
* and a log entry is written.
* @param filename file to be opened
*/
mrmc::parser::MappedFile::MappedFile(const char* filename)
{
mrmc::parser::MappedFile::MappedFile(const char* filename) {
#if defined LINUX || defined MACOSX
/*
* Do file mapping for reasonable systems.
* stat64(), open(), mmap()
*/
#ifdef MACOSX
if (stat(filename, &(this->st)) != 0)
if (stat(filename, &(this->st)) != 0) {
#else
if (stat64(filename, &(this->st)) != 0)
if (stat64(filename, &(this->st)) != 0) {
#endif
{
LOG4CPLUS_ERROR(logger, "Error in stat(" << filename << ").");
throw exceptions::FileIoException("mrmc::parser::MappedFile Error in stat()");
}
this->file = open(filename, O_RDONLY);
if (this->file < 0)
{
if (this->file < 0) {
LOG4CPLUS_ERROR(logger, "Error in open(" << filename << ").");
throw exceptions::FileIoException("mrmc::parser::MappedFile Error in open()");
}
this->data = (char*) mmap(NULL, this->st.st_size, PROT_READ, MAP_PRIVATE, this->file, 0);
if (this->data == (char*)-1)
{
if (this->data == (char*)-1) {
close(this->file);
LOG4CPLUS_ERROR(logger, "Error in mmap(" << filename << ").");
throw exceptions::FileIoException("mrmc::parser::MappedFile Error in mmap()");
@ -94,30 +87,26 @@ mrmc::parser::MappedFile::MappedFile(const char* filename)
* Do file mapping for windows.
* _stat64(), CreateFile(), CreateFileMapping(), MapViewOfFile()
*/
if (_stat64(filename, &(this->st)) != 0)
{
if (_stat64(filename, &(this->st)) != 0) {
LOG4CPLUS_ERROR(logger, "Error in _stat(" << filename << ").");
throw exceptions::FileIoException("mrmc::parser::MappedFile Error in stat()");
}
this->file = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (this->file == INVALID_HANDLE_VALUE)
{
if (this->file == INVALID_HANDLE_VALUE) {
LOG4CPLUS_ERROR(logger, "Error in CreateFileA(" << filename << ").");
throw exceptions::FileIoException("mrmc::parser::MappedFile Error in CreateFileA()");
}
this->mapping = CreateFileMappingA(this->file, NULL, PAGE_READONLY, (DWORD)(st.st_size >> 32), (DWORD)st.st_size, NULL);
if (this->mapping == NULL)
{
if (this->mapping == NULL) {
CloseHandle(this->file);
LOG4CPLUS_ERROR(logger, "Error in CreateFileMappingA(" << filename << ").");
throw exceptions::FileIoException("mrmc::parser::MappedFile Error in CreateFileMappingA()");
}
this->data = static_cast<char*>(MapViewOfFile(this->mapping, FILE_MAP_READ, 0, 0, this->st.st_size));
if (this->data == NULL)
{
if (this->data == NULL) {
CloseHandle(this->mapping);
CloseHandle(this->file);
LOG4CPLUS_ERROR(logger, "Error in MapViewOfFile(" << filename << ").");
@ -130,8 +119,7 @@ mrmc::parser::MappedFile::MappedFile(const char* filename)
/*!
* Will unmap the data and close the file.
*/
mrmc::parser::MappedFile::~MappedFile()
{
mrmc::parser::MappedFile::~MappedFile() {
#if defined LINUX || defined MACOSX
munmap(this->data, this->st.st_size);
close(this->file);

14
src/parser/parser.h → src/parser/Parser.h

@ -1,12 +1,12 @@
/*
* parser.h
* Parser.h
*
* Created on: 21.11.2012
* Author: Gereon Kremer
*/
#ifndef PARSER_H_
#define PARSER_H_
#ifndef MRMC_PARSER_PARSER_H_
#define MRMC_PARSER_PARSER_H_
#include "src/utility/OsDetection.h"
@ -52,8 +52,7 @@ namespace parser {
#error Platform not supported
#endif
class MappedFile
{
class MappedFile {
private:
#if defined LINUX || defined MACOSX
/*!
@ -104,8 +103,7 @@ namespace parser {
~MappedFile();
};
class Parser
{
class Parser {
protected:
/*!
* @brief Parses integer and checks, if something has been parsed.
@ -121,4 +119,4 @@ namespace parser {
} // namespace parser
} // namespace mrmc
#endif /* PARSER_H_ */
#endif /* MRMC_PARSER_PARSER_H_ */

46
src/parser/readLabFile.cpp

@ -5,8 +5,6 @@
* Author: Gereon Kremer
*/
#include "parser.h"
#include "readLabFile.h"
#include "src/exceptions/WrongFileFormatException.h"
@ -69,37 +67,31 @@ LabParser::LabParser(uint_fast64_t node_count, const char * filename)
/*
* iterate over tokens until we hit #END or end of file
*/
while(buf[0] != '\0')
{
while(buf[0] != '\0') {
buf += cnt;
cnt = strcspn(buf, separator); // position of next separator
if (cnt > 0)
{
if (cnt > 0) {
/*
* next token is #DECLARATION: just skip it
* next token is #END: stop search
* otherwise increase proposition_count
*/
if (strncmp(buf, "#DECLARATION", cnt) == 0)
{
if (strncmp(buf, "#DECLARATION", cnt) == 0) {
foundDecl = true;
continue;
}
else if (strncmp(buf, "#END", cnt) == 0)
{
else if (strncmp(buf, "#END", cnt) == 0) {
foundEnd = true;
break;
}
proposition_count++;
}
else buf++; // next char is separator, one step forward
} else buf++; // next char is separator, one step forward
}
/*
* If #DECLARATION or #END were not found, the file format is wrong
*/
if (! (foundDecl && foundEnd))
{
if (! (foundDecl && foundEnd)) {
LOG4CPLUS_ERROR(logger, "Wrong file format in (" << filename << "). File header is corrupted.");
if (! foundDecl) LOG4CPLUS_ERROR(logger, "\tDid not find #DECLARATION token.");
if (! foundEnd) LOG4CPLUS_ERROR(logger, "\tDid not find #END token.");
@ -125,20 +117,16 @@ LabParser::LabParser(uint_fast64_t node_count, const char * filename)
*/
char proposition[128]; // buffer for proposition names
size_t cnt = 0;
do
{
do {
buf += cnt;
cnt = strcspn(buf, separator); // position of next separator
if (cnt >= sizeof(proposition))
{
if (cnt >= sizeof(proposition)) {
/*
* if token is longer than our buffer, the following strncpy code might get risky...
*/
LOG4CPLUS_ERROR(logger, "Wrong file format in (" << filename << "). Atomic proposition with length > " << (sizeof(proposition)-1) << " was found.");
throw mrmc::exceptions::WrongFileFormatException();
}
else if (cnt > 0)
{
} else if (cnt > 0) {
/*
* next token is: #DECLARATION: just skip it
* next token is: #END: stop search
@ -149,8 +137,7 @@ LabParser::LabParser(uint_fast64_t node_count, const char * filename)
strncpy(proposition, buf, cnt);
proposition[cnt] = '\0';
this->labeling->addAtomicProposition(proposition);
}
else cnt = 1; // next char is separator, one step forward
} else cnt = 1; // next char is separator, one step forward
} while (cnt > 0);
/*
* Right here, the buf pointer is still pointing to our last token,
@ -169,17 +156,14 @@ LabParser::LabParser(uint_fast64_t node_count, const char * filename)
/*
* iterate over nodes
*/
while (buf[0] != '\0')
{
while (buf[0] != '\0') {
/*
* parse node number, then iterate over propositions
*/
node = checked_strtol(buf, &buf);
while ((buf[0] != '\n') && (buf[0] != '\0'))
{
while ((buf[0] != '\n') && (buf[0] != '\0')) {
cnt = strcspn(buf, separator);
if (cnt == 0)
{
if (cnt == 0) {
/*
* next char is a separator
* if it's a newline, we continue with next node
@ -187,9 +171,7 @@ LabParser::LabParser(uint_fast64_t node_count, const char * filename)
*/
if (buf[0] == '\n') break;
buf++;
}
else
{
} else {
/*
* copy proposition to buffer and add it to labeling
*/

8
src/parser/readLabFile.h

@ -4,7 +4,7 @@
#include "src/models/AtomicPropositionsLabeling.h"
#include "boost/integer/integer_mask.hpp"
#include "src/parser/parser.h"
#include "src/parser/Parser.h"
#include <memory>
@ -17,13 +17,11 @@ namespace parser {
* Note that this class creates a new AtomicPropositionsLabeling object that can
* be accessed via getLabeling(). However, it will not delete this object!
*/
class LabParser : Parser
{
class LabParser : Parser {
public:
LabParser(uint_fast64_t node_count, const char* filename);
std::shared_ptr<mrmc::models::AtomicPropositionsLabeling> getLabeling()
{
std::shared_ptr<mrmc::models::AtomicPropositionsLabeling> getLabeling() {
return this->labeling;
}

3
src/parser/readPrctlFile.cpp

@ -1,9 +1,6 @@
#include "src/parser/readPrctlFile.h"
#include "src/parser/parser.h"
#include <iostream>
#include <map>
//#include <pair>

2
src/parser/readPrctlFile.h

@ -2,7 +2,7 @@
#define READPRCTLFILE_H_
#include "src/formula/PCTLformula.h"
#include "src/parser/parser.h"
#include "src/parser/Parser.h"
namespace mrmc {
namespace parser {

17
src/parser/readTraFile.cpp

@ -5,8 +5,6 @@
* Author: Gereon Kremer
*/
#include "parser.h"
#include "src/parser/readTraFile.h"
#include "src/exceptions/FileIoException.h"
#include "src/exceptions/WrongFileFormatException.h"
@ -48,23 +46,20 @@ namespace parser{
* @param buf Data to scan. Is expected to be some char array.
* @param maxnode Is set to highest id of all nodes.
*/
uint_fast64_t TraParser::firstPass(char* buf, uint_fast64_t &maxnode)
{
uint_fast64_t TraParser::firstPass(char* buf, uint_fast64_t &maxnode) {
uint_fast64_t non_zero = 0;
/*
* check file header and extract number of transitions
*/
if (strncmp(buf, "STATES ", 7) != 0)
{
if (strncmp(buf, "STATES ", 7) != 0) {
LOG4CPLUS_ERROR(logger, "Expected \"STATES\" but got \"" << std::string(buf, 0, 16) << "\".");
return 0;
}
buf += 7; // skip "STATES "
if (strtol(buf, &buf, 10) == 0) return 0;
buf = skipWS(buf);
if (strncmp(buf, "TRANSITIONS ", 12) != 0)
{
if (strncmp(buf, "TRANSITIONS ", 12) != 0) {
LOG4CPLUS_ERROR(logger, "Expected \"TRANSITIONS\" but got \"" << std::string(buf, 0, 16) << "\".");
return 0;
}
@ -78,8 +73,7 @@ uint_fast64_t TraParser::firstPass(char* buf, uint_fast64_t &maxnode)
double val;
maxnode = 0;
char* tmp;
while (buf[0] != '\0')
{
while (buf[0] != '\0') {
/*
* read row and column
*/
@ -95,8 +89,7 @@ uint_fast64_t TraParser::firstPass(char* buf, uint_fast64_t &maxnode)
* if row == col, we have a diagonal element which is treated seperately and this non_zero must be decreased.
*/
val = strtod(buf, &tmp);
if (val == 0.0)
{
if (val == 0.0) {
LOG4CPLUS_ERROR(logger, "Expected a positive probability but got \"" << std::string(buf, 0, 16) << "\".");
return 0;
}

8
src/parser/readTraFile.h

@ -3,7 +3,7 @@
#include "src/storage/SquareSparseMatrix.h"
#include "src/parser/parser.h"
#include "src/parser/Parser.h"
#include <memory>
@ -17,13 +17,11 @@ namespace parser {
* Note that this class creates a new StaticSparseMatrix object that can be
* accessed via getMatrix(). However, it does not delete this object!
*/
class TraParser : Parser
{
class TraParser : Parser {
public:
TraParser(const char* filename);
std::shared_ptr<mrmc::storage::SquareSparseMatrix<double>> getMatrix()
{
std::shared_ptr<mrmc::storage::SquareSparseMatrix<double>> getMatrix() {
return this->matrix;
}

8
src/reward/reward_model.h → src/reward/RewardModel.h

@ -1,12 +1,12 @@
/*
* reward_model.h
* RewardModel.h
*
* Created on: 25.10.2012
* Author: Philipp Berger
*/
#ifndef MRMC_REWARD_REWARD_MODEL_H_
#define MRMC_REWARD_REWARD_MODEL_H_
#ifndef MRMC_REWARD_REWARDMODEL_H_
#define MRMC_REWARD_REWARDMODEL_H_
#include <stdexcept>
@ -76,4 +76,4 @@ class RewardModel {
} //namespace mrmc
#endif /* MRMC_REWARD_REWARD_MODEL_H_ */
#endif /* MRMC_REWARD_REWARDMODEL_H_ */

71
src/utility/Settings.cpp

@ -42,11 +42,9 @@ std::map< std::pair<std::string, std::string>, std::shared_ptr<bpo::options_desc
* @param argv should be argv passed to main function
* @param filename either nullptr or name of config file
*/
Settings::Settings(const int argc, const char* argv[], const char* filename)
{
Settings::Settings(const int argc, const char* argv[], const char* filename) {
Settings::binaryName = std::string(argv[0]);
try
{
try {
// Initially fill description objects
this->initDescriptions();
@ -57,17 +55,15 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
// Check module triggers, add corresponding options
std::map< std::string, std::list< std::string > > options;
for (auto it : Settings::modules)
{
for (auto it : Settings::modules) {
options[it.first.first].push_back(it.first.second);
}
for (auto it : options)
{
for (auto it : options) {
std::stringstream str;
str << "select " << it.first << " module (" << boost::algorithm::join(it.second, ", ") << ")";
Settings::desc->add_options()
(it.first.c_str(), bpo::value<std::string>(), str.str().c_str())
(it.first.c_str(), bpo::value<std::string>()->default_value(it.second.front()), str.str().c_str())
;
}
@ -77,13 +73,10 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
// Buffer for items to be deleted
std::list< std::pair< std::string, std::string > > deleteQueue;
// Check module triggers
for (auto it : Settings::modules)
{
for (auto it : Settings::modules) {
std::pair< std::string, std::string > trigger = it.first;
if (this->vm.count(trigger.first))
{
if (this->vm[trigger.first].as<std::string>().compare(trigger.second) == 0)
{
if (this->vm.count(trigger.first)) {
if (this->vm[trigger.first].as<std::string>().compare(trigger.second) == 0) {
Settings::desc->add(*it.second);
deleteQueue.push_back(trigger);
}
@ -93,8 +86,7 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
// Stop if help is set
if (this->vm.count("help") > 0)
{
if (this->vm.count("help") > 0) {
return;
}
@ -105,25 +97,20 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
bpo::notify(this->vm);
LOG4CPLUS_DEBUG(logger, "Finished loading config.");
}
catch (bpo::reading_file e)
{
catch (bpo::reading_file e) {
std::cerr << "Could not read config file " << filename << std::endl;
LOG4CPLUS_ERROR(logger, "Could not read config file");
}
catch (bpo::required_option e)
{
catch (bpo::required_option e) {
throw mrmc::exceptions::InvalidSettings() << "Required option missing";
}
catch (bpo::validation_error e)
{
catch (bpo::validation_error e) {
throw mrmc::exceptions::InvalidSettings() << "Validation failed: " << e.what();
}
catch (bpo::invalid_command_line_syntax e)
{
catch (bpo::invalid_command_line_syntax e) {
throw mrmc::exceptions::InvalidSettings() << e.what();
}
catch (bpo::error e)
{
catch (bpo::error e) {
throw mrmc::exceptions::InvalidSettings() << e.what();
}
}
@ -132,8 +119,7 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
* Initially fill options_description objects.
* First puts some generic options, then calls all register Callbacks.
*/
void Settings::initDescriptions()
{
void Settings::initDescriptions() {
LOG4CPLUS_DEBUG(logger, "Initializing descriptions.");
Settings::desc = std::unique_ptr<bpo::options_description>(new bpo::options_description("Generic Options"));
Settings::desc->add_options()
@ -143,7 +129,6 @@ void Settings::initDescriptions()
("test-prctl", bpo::value<std::string>(), "name of prctl file")
("trafile", bpo::value<std::string>()->required(), "name of the .tra file")
("labfile", bpo::value<std::string>()->required(), "name of the .lab file")
("matrixlib", bpo::value<std::string>()->default_value("gmm++"), "name of the matrix library")
;
}
@ -152,8 +137,7 @@ void Settings::initDescriptions()
* given), but allow for unregistered options, do not check requirements
* from options_description objects, do not check positional arguments.
*/
void Settings::firstRun(const int argc, const char* argv[], const char* filename)
{
void Settings::firstRun(const int argc, const char* argv[], const char* filename) {
LOG4CPLUS_DEBUG(logger, "Performing first run.");
// parse command line
bpo::store(bpo::command_line_parser(argc, argv).options(*(Settings::desc)).allow_unregistered().run(), this->vm);
@ -161,12 +145,9 @@ void Settings::firstRun(const int argc, const char* argv[], const char* filename
/*
* load config file if specified
*/
if (this->vm.count("configfile"))
{
if (this->vm.count("configfile")) {
bpo::store(bpo::parse_config_file<char>(this->vm["configfile"].as<std::string>().c_str(), *(Settings::desc)), this->vm, true);
}
else if (filename != NULL)
{
} else if (filename != NULL) {
bpo::store(bpo::parse_config_file<char>(filename, *(Settings::desc)), this->vm, true);
}
}
@ -176,20 +157,16 @@ void Settings::firstRun(const int argc, const char* argv[], const char* filename
* given) and check for unregistered options, requirements from
* options_description objects and positional arguments.
*/
void Settings::secondRun(const int argc, const char* argv[], const char* filename)
{
void Settings::secondRun(const int argc, const char* argv[], const char* filename) {
LOG4CPLUS_DEBUG(logger, "Performing second run.");
// Parse command line
bpo::store(bpo::command_line_parser(argc, argv).options(*(Settings::desc)).positional(this->positional).run(), this->vm);
/*
* load config file if specified
*/
if (this->vm.count("configfile"))
{
if (this->vm.count("configfile")) {
bpo::store(bpo::parse_config_file<char>(this->vm["configfile"].as<std::string>().c_str(), *(Settings::desc)), this->vm, true);
}
else if (filename != NULL)
{
} else if (filename != NULL) {
bpo::store(bpo::parse_config_file<char>(filename, *(Settings::desc)), this->vm, true);
}
}
@ -202,12 +179,10 @@ void Settings::secondRun(const int argc, const char* argv[], const char* filenam
* Use it like this:
* @code std::cout << mrmc::settings::help; @endcode
*/
std::ostream& help(std::ostream& os)
{
std::ostream& help(std::ostream& os) {
os << "Usage: " << mrmc::settings::Settings::binaryName << " [options] <transition file> <label file>" << std::endl;
os << *(mrmc::settings::Settings::desc) << std::endl;
for (auto it : Settings::modules)
{
for (auto it : Settings::modules) {
os << *(it.second) << std::endl;
}
return os;

11
src/utility/Settings.h

@ -106,13 +106,12 @@ namespace settings {
* @endcode
*/
template <typename T>
static void registerModule()
{
static void registerModule() {
// get trigger
std::pair< std::string, std::string > trigger = T::getOptionTrigger();
// build description name
std::stringstream str;
str << T::getModuleName() << " (" << trigger.first << " = " << trigger.second << ")";
str << "Options for " << T::getModuleName() << " (" << trigger.first << " = " << trigger.second << ")";
std::shared_ptr<bpo::options_description> desc = std::shared_ptr<bpo::options_description>(new bpo::options_description(str.str()));
// but options
T::putOptions(desc.get());
@ -187,8 +186,7 @@ namespace settings {
*
* @return The current instance of Settings created by newInstance().
*/
inline Settings* instance()
{
inline Settings* instance() {
return Settings::inst;
}
@ -202,8 +200,7 @@ namespace settings {
* @param filename either NULL or name of config file
* @return The new instance of Settings.
*/
inline Settings* newInstance(const int argc, const char* argv[], const char* filename)
{
inline Settings* newInstance(const int argc, const char* argv[], const char* filename) {
if (Settings::inst != nullptr) delete Settings::inst;
Settings::inst = new Settings(argc, argv, filename);
return Settings::inst;

0
test/eigen/sparse_matrix_test.cpp → test/eigen/EigenSparseMatrixTest.cpp

2
test/parser/parse_dtmc_test.cpp → test/parser/ParseDtmcTest.cpp

@ -1,5 +1,5 @@
/*
* parse_dtmc_test.cpp
* ParseDtmcTest.cpp
*
* Created on: 03.12.2012
* Author: Thomas Heinemann

2
test/parser/read_lab_file_test.cpp → test/parser/ReadLabFileTest.cpp

@ -1,5 +1,5 @@
/*
* read_lab_file_test.cpp
* ReadLabFileTest.cpp
*
* Created on: 12.09.2012
* Author: Thomas Heinemann

2
test/parser/read_tra_file_test.cpp → test/parser/ReadTraFileTest.cpp

@ -1,5 +1,5 @@
/*
* read_tra_file_test.cpp
* ReadTraFileTest.cpp
*
* Created on: 16.08.2012
* Author: Thomas Heinemann

2
test/reward/reward_model_test.cpp → test/reward/RewardModelTest.cpp

@ -5,7 +5,7 @@
#include "boost/integer/integer_mask.hpp"
#include <vector>
#include "reward/reward_model.h"
#include "reward/RewardModel.h"
TEST(RewardModelTest, ReadWriteTest) {
// 50 entries
Loading…
Cancel
Save