Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386716
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
29 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/apps/sa-ews1/sa-ews1.cpp b/apps/sa-ews1/sa-ews1.cpp
index 7fdf65b..ebcc645 100644
--- a/apps/sa-ews1/sa-ews1.cpp
+++ b/apps/sa-ews1/sa-ews1.cpp
@@ -1,404 +1,599 @@
//===-- apps/sa-ews1/sa-ews1.cpp --------------------------------*- C++ -*-===//
//
// The RoSA Framework -- Application SA-EWS1
//
// Distributed under the terms and conditions of the Boost Software License 1.0.
// See accompanying file LICENSE.
//
// If you did not receive a copy of the license file, see
// http://www.boost.org/LICENSE_1_0.txt.
//
//===----------------------------------------------------------------------===//
///
/// \file apps/sa-ews1/sa-ews1.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
+/// Maximilian Goetzinger (maxgot@utu.fi)
///
/// \date 2017-2020
///
/// \brief The application SA-EWS1 implements the case study from the paper:
/// M. Götzinger, A. Anzanpour, I. Azimi, N. TaheriNejad, and A. M. Rahmani:
/// Enhancing the Self-Aware Early Warning Score System through Fuzzified Data
/// Reliability Assessment. DOI: 10.1007/978-3-319-98551-0_1
//===----------------------------------------------------------------------===//
#include "rosa/agent/Abstraction.hpp"
-#include "rosa/agent/Confidence.hpp"
+#include "rosa/agent/CrossCombinator.h"
+#include "rosa/agent/ReliabilityConfidenceCombination.h"
#include "rosa/config/version.h"
#include "rosa/app/Application.hpp"
#include "rosa/support/csv/CSVReader.hpp"
#include "rosa/support/csv/CSVWriter.hpp"
#include "rosa/support/iterator/split_tuple_iterator.hpp"
#include "cxxopts/cxxopts.hpp"
#include <fstream>
using namespace rosa;
using namespace rosa::agent;
using namespace rosa::app;
using namespace rosa::terminal;
using namespace rosa::csv;
using namespace rosa::iterator;
const std::string AppName = "SA-EWS1";
+/// Representation type of warning levels.
+/// \note Make sure it suits all defined enumeration values.
+using WarningScoreType = uint8_t;
+
/// Warning levels for abstraction.
-enum WarningScore { No = 0, Low = 1, High = 2, Emergency = 3 };
+enum WarningScore : WarningScoreType {
+ No = 0,
+ Low = 1,
+ High = 2,
+ Emergency = 3
+};
+
+/// Vector with all possible warning levels.
+std::vector<WarningScore> warningScores = {No, Low, High, Emergency};
+
+/// Type used to represent reliability values.
+using ReliabilityType = double;
+
+/// The result type of low-level functions.
+using WarningValue = AppTuple<WarningScoreType, ReliabilityType>;
/// Helper function creating an application sensor and setting its execution
/// policy for decimation.
///
/// \note The sensors are created without defining a normal generator function,
/// which is suitable for simulation only.
///
/// \tparam T type of values for the sensor to generate
///
/// \param App the application to create the sensor in
/// \param Name name of the new sensor
/// \param Decimation the decimation parameter
///
/// \return handle for the new sensor
template <typename T>
AgentHandle createSensor(std::unique_ptr<Application> &App,
const std::string &Name, const size_t Decimation) {
AgentHandle Sensor = App->createSensor<T>(Name);
App->setExecutionPolicy(Sensor, AppExecutionPolicy::decimation(Decimation));
return Sensor;
}
/// Helper function creating an application agent for pre-processing sensory
/// values and setting its execution policy for decimation.
///
-/// \todo Replace Confidence with Reliability and send abstracted value together
-/// with reliability value.
-///
-/// Received values are first validated for confidence. Values which the
-/// validator does not mark confident are ignored. Confident values are
-/// abstracted into a \c WarningScore value, which is the result of the
-/// processing function.
+/// Received values are assessed for reliability and abstracted into a \c
+/// WarningScore. The result of the processing function is a pair of assessed
+/// reliability and abstracted values.
///
-/// \note The result, \c WarningScore, is returned as \c uint32_t because
-/// enumeration types are not integrated into built-in types. Hence, a master
-/// to these agents receives its input as \c uint32_t values, and may cast them
-/// to \c WarningScore explicitly.
+/// \note The result, \c WarningScore, is returned as \c WarningScoreType
+/// because enumeration types are not integrated into built-in types. Hence, a
+/// master to these agents receives its input as \c WarningScoreType values, and
+/// may cast them to \c WarningScore explicitly.
///
/// \tparam T type of values to receive from the sensor
///
/// \param App the application to create the agent in
/// \param Name name of the new agent
/// \param Decimation the decimation parameter
-/// \param CC confidence validator to use
/// \param A abstraction to use
+/// \param R reliability/confidence combination to use
///
/// \return handle for the new agent
template <typename T>
-AgentHandle createLowLevelAgent(std::unique_ptr<Application> &App,
- const std::string &Name,
- const size_t Decimation,
- const Confidence<T> &CC,
- const Abstraction<T, WarningScore> &A) {
- using handler = std::function<Optional<uint32_t>(std::pair<T, bool>)>;
- using result = Optional<uint32_t>;
+AgentHandle createLowLevelAgent(
+ std::unique_ptr<Application> &App, const std::string &Name,
+ const size_t Decimation, const Abstraction<T, WarningScore> &A,
+ ReliabilityAndConfidenceCombination<T, WarningScore, ReliabilityType> &R) {
+ using result = Optional<WarningValue>;
+ using input = AppTuple<T>;
+ using handler = std::function<result(std::pair<input, bool>)>;
AgentHandle Agent = App->createAgent(
- Name, handler([&, Name](std::pair<T, bool> I) -> result {
+ Name, handler([&, Name](std::pair<input, bool> I) -> result {
LOG_INFO_STREAM << "\n******\n"
<< Name << " " << (I.second ? "<New>" : "<Old>")
- << " value: " << I.first << "\n******\n";
- return (I.second && CC(I.first)) ? result(A(I.first)) : result();
+ << " value: " << std::get<0>(I.first) << "\n******\n";
+ const auto SensorValue = std::get<0>(I.first);
+ const WarningScoreType Score = A(SensorValue);
+ const ReliabilityType InputReliability =
+ R.getInputReliability(SensorValue);
+ return {WarningValue(Score, InputReliability)};
}));
App->setExecutionPolicy(Agent, AppExecutionPolicy::decimation(Decimation));
return Agent;
}
/// Helper function to print and error message in red color to the terminal and
/// exit from the application.
///
/// \note The function never returns as it calles `exit()`.
///
/// \param Error error message
/// \param ExitCode exit code to return from the application
void logErrorAndExit(const std::string &Error, const int ExitCode) {
LOG_ERROR_STREAM << Color::Red << Error << Color::Default << std::endl;
exit(ExitCode);
}
int main(int argc, char *argv[]) {
/// Paths for the CSV files for simulation.
///
///@{
std::string DataCSVPath;
std::string ScoreCSVPath;
///@}
/// Decimation of sensors and agents.
size_t Decimation = 1;
/// How many cycles of simulation to perform.
size_t NumberOfSimulationCycles = 16;
// Handle command-line arguments.
try {
cxxopts::Options Options(argv[0], library_string() + " -- " + AppName);
Options.add_options()("i,input",
"Path for the CSV file providing input data",
cxxopts::value(DataCSVPath), "file")
("o,output",
"Path fr the CSV file to write output scores",
cxxopts::value(ScoreCSVPath), "file")
("d,decimation", "Decimation of sensors and agents",
cxxopts::value(Decimation)->default_value("1"))
("c,cycles", "Number of simulation cycles to perform",
cxxopts::value(NumberOfSimulationCycles)->default_value("16"));
auto Args = Options.parse(argc, argv);
if (Args.count("data") == 0) {
throw std::invalid_argument("Argument --data must be defined.");
}
if (Args.count("score") == 0) {
throw std::invalid_argument("Argument --score must be defined.");
}
} catch (const cxxopts::OptionException &e) {
logErrorAndExit(e.what(), 1);
} catch (const std::invalid_argument &e) {
logErrorAndExit(e.what(), 1);
}
LOG_INFO_STREAM
<< '\n'
<< library_string() << " -- " << Color::Red << AppName << "app"
<< Color::Default << '\n'
<< Color::Yellow
<< "CSV files are read from and written to the current working directory."
<< Color::Default << '\n';
std::unique_ptr<Application> App = Application::create(AppName);
+ //
+ // Relevant types and definitions.
+ //
+
+ using HRType = int32_t;
+ using HRParFun = PartialFunction<HRType, ReliabilityType>;
+ using HRLinFun = LinearFunction<HRType, ReliabilityType>;
+
+ using BRType = int32_t;
+ using BRParFun = PartialFunction<BRType, ReliabilityType>;
+ using BRLinFun = LinearFunction<BRType, ReliabilityType>;
+
+ using SpO2Type = int32_t;
+ using SpO2ParFun = PartialFunction<SpO2Type, ReliabilityType>;
+ using SpO2LinFun = LinearFunction<SpO2Type, ReliabilityType>;
+
+ using BPSysType = int32_t;
+ using BPSysParFun = PartialFunction<BPSysType, ReliabilityType>;
+ using BPSysLinFun = LinearFunction<BPSysType, ReliabilityType>;
+
+ using BodyTempType = float;
+ using BodyTempParFun = PartialFunction<BodyTempType, ReliabilityType>;
+ using BodyTempLinFun = LinearFunction<BodyTempType, ReliabilityType>;
+
//
// Create application sensors.
//
LOG_INFO("Creating sensors.");
// All sensors are created without defining a normal generator function, but
// with the default value of the second argument. That, however, requires the
// data type to be explicitly defined. This is good for simulation only.
- AgentHandle HRSensor = createSensor<int32_t>(App, "HR Sensor", Decimation);
- AgentHandle BRSensor = createSensor<int32_t>(App, "BR Sensor", Decimation);
+ AgentHandle HRSensor = createSensor<HRType>(App, "HR Sensor", Decimation);
+ AgentHandle BRSensor = createSensor<BRType>(App, "BR Sensor", Decimation);
AgentHandle SpO2Sensor =
- createSensor<int32_t>(App, "SpO2 Sensor", Decimation);
+ createSensor<SpO2Type>(App, "SpO2 Sensor", Decimation);
AgentHandle BPSysSensor =
- createSensor<int32_t>(App, "BPSys Sensor", Decimation);
+ createSensor<BPSysType>(App, "BPSys Sensor", Decimation);
AgentHandle BodyTempSensor =
- createSensor<float>(App, "BodyTemp Sensor", Decimation);
+ createSensor<BodyTempType>(App, "BodyTemp Sensor", Decimation);
//
// Create functionalities.
//
LOG_INFO("Creating Functionalities for Agents.");
- //
- // Define confidence validators.
- //
- // Lower bounds are inclusive and upper bounds are exclusive.
-
- Confidence<int32_t> HRConfidence(0, 501);
- Confidence<int32_t> BRConfidence(0, 301);
- Confidence<int32_t> SpO2Confidence(0, 101);
- Confidence<int32_t> BPSysConfidence(0, 501);
- Confidence<float> BodyTempConfidence(-60,
- nextRepresentableFloatingPoint(50.0f));
-
//
// Define abstractions.
//
- RangeAbstraction<int32_t, WarningScore> HRAbstraction(
+ RangeAbstraction<HRType, WarningScore> HRAbstraction(
{{{0, 40}, Emergency},
{{40, 51}, High},
{{51, 60}, Low},
{{60, 100}, No},
{{100, 110}, Low},
{{110, 129}, High},
{{129, 200}, Emergency}},
Emergency);
- RangeAbstraction<int32_t, WarningScore> BRAbstraction({{{0, 9}, High},
- {{9, 14}, No},
- {{14, 20}, Low},
- {{20, 29}, High},
- {{29, 50}, Emergency}},
- Emergency);
-
- RangeAbstraction<int32_t, WarningScore> SpO2Abstraction({{{1, 85}, Emergency},
- {{85, 90}, High},
- {{90, 95}, Low},
- {{95, 100}, No}},
- Emergency);
+ RangeAbstraction<BRType, WarningScore> BRAbstraction({{{0, 9}, High},
+ {{9, 14}, No},
+ {{14, 20}, Low},
+ {{20, 29}, High},
+ {{29, 50}, Emergency}},
+ Emergency);
+
+ RangeAbstraction<SpO2Type, WarningScore> SpO2Abstraction(
+ {{{1, 85}, Emergency},
+ {{85, 90}, High},
+ {{90, 95}, Low},
+ {{95, 100}, No}},
+ Emergency);
- RangeAbstraction<int32_t, WarningScore> BPSysAbstraction(
+ RangeAbstraction<BPSysType, WarningScore> BPSysAbstraction(
{{{0, 70}, Emergency},
{{70, 81}, High},
{{81, 101}, Low},
{{101, 149}, No},
{{149, 169}, Low},
{{169, 179}, High},
{{179, 200}, Emergency}},
Emergency);
- RangeAbstraction<float, WarningScore> BodyTempAbstraction(
+ RangeAbstraction<BodyTempType, WarningScore> BodyTempAbstraction(
{{{0.f, 28.f}, Emergency},
{{28.f, 32.f}, High},
{{32.f, 35.f}, Low},
{{35.f, 38.f}, No},
{{38.f, 39.5f}, High},
{{39.5f, 100.f}, Emergency}},
Emergency);
+ //
+ // Define reliabilities.
+ //
+
+ ReliabilityAndConfidenceCombination<HRType, WarningScore, ReliabilityType>
+ HRReliability;
+ HRReliability.setTimeStep(1);
+
+ std::shared_ptr<Abstraction<HRType, ReliabilityType>> HRAbsRel(
+ new HRParFun({{{0, 200}, std::make_shared<HRLinFun>(1, 0)},
+ {{200, 300}, std::make_shared<HRLinFun>(200, 1, 300, 0)}},
+ 0));
+ HRReliability.setAbsoluteReliabilityFunction(HRAbsRel);
+
+ std::shared_ptr<Abstraction<HRType, ReliabilityType>> HRRelSlope(new HRParFun(
+ {{{-200, -100}, std::make_shared<HRLinFun>(-200, 0, -100, 1)},
+ {{-100, 100}, std::make_shared<HRLinFun>(1, 0)},
+ {{100, 200}, std::make_shared<HRLinFun>(100, 1, 200, 0)}},
+ 0));
+ HRReliability.setReliabilitySlopeFunction(HRRelSlope);
+
+ ReliabilityAndConfidenceCombination<BRType, WarningScore, ReliabilityType>
+ BRReliability;
+ BRReliability.setTimeStep(1);
+
+ std::shared_ptr<Abstraction<BRType, ReliabilityType>> BRAbsRel(
+ new BRParFun({{{0, 40}, std::make_shared<BRLinFun>(1, 0)},
+ {{40, 60}, std::make_shared<BRLinFun>(40, 1, 60, 0)}},
+ 0));
+ BRReliability.setAbsoluteReliabilityFunction(BRAbsRel);
+
+ std::shared_ptr<Abstraction<BRType, ReliabilityType>> BRRelSlope(
+ new BRParFun({{{-30, -20}, std::make_shared<BRLinFun>(-30, 0, -20, 1)},
+ {{-20, 20}, std::make_shared<BRLinFun>(1, 0)},
+ {{20, 30}, std::make_shared<BRLinFun>(20, 1, 30, 0)}},
+ 0));
+ BRReliability.setReliabilitySlopeFunction(BRRelSlope);
+
+ ReliabilityAndConfidenceCombination<SpO2Type, WarningScore, ReliabilityType>
+ SpO2Reliability;
+ SpO2Reliability.setTimeStep(1);
+
+ std::shared_ptr<Abstraction<SpO2Type, ReliabilityType>> SpO2AbsRel(
+ new SpO2ParFun(
+ {
+ {{0, 100}, std::make_shared<SpO2LinFun>(1, 0)},
+ },
+ 0));
+ SpO2Reliability.setAbsoluteReliabilityFunction(SpO2AbsRel);
+
+ std::shared_ptr<Abstraction<SpO2Type, ReliabilityType>> SpO2RelSlope(
+ new SpO2ParFun({{{-8, -5}, std::make_shared<SpO2LinFun>(-8, 0, -5, 1)},
+ {{-5, 5}, std::make_shared<SpO2LinFun>(1, 0)},
+ {{5, 8}, std::make_shared<SpO2LinFun>(5, 1, 8, 0)}},
+ 0));
+ SpO2Reliability.setReliabilitySlopeFunction(SpO2RelSlope);
+
+ ReliabilityAndConfidenceCombination<BPSysType, WarningScore, ReliabilityType>
+ BPSysReliability;
+ BPSysReliability.setTimeStep(1);
+
+ std::shared_ptr<Abstraction<BPSysType, ReliabilityType>> BPSysAbsRel(
+ new BPSysParFun(
+ {{{0, 260}, std::make_shared<BPSysLinFun>(1, 0)},
+ {{260, 400}, std::make_shared<BPSysLinFun>(260, 1, 400, 0)}},
+ 0));
+ BPSysReliability.setAbsoluteReliabilityFunction(BPSysAbsRel);
+
+ std::shared_ptr<Abstraction<BPSysType, ReliabilityType>> BPSysRelSlope(
+ new BPSysParFun(
+ {{{-100, -50}, std::make_shared<BPSysLinFun>(-100, 0, -50, 1)},
+ {{-50, 50}, std::make_shared<BPSysLinFun>(1, 0)},
+ {{50, 100}, std::make_shared<BPSysLinFun>(50, 1, 100, 0)}},
+ 0));
+ BPSysReliability.setReliabilitySlopeFunction(BPSysRelSlope);
+
+ ReliabilityAndConfidenceCombination<BodyTempType, WarningScore,
+ ReliabilityType>
+ BodyTempReliability;
+ BodyTempReliability.setTimeStep(1);
+
+ std::shared_ptr<Abstraction<BodyTempType, ReliabilityType>> BodyTempAbsRel(
+ new BodyTempParFun(
+ {{{-70.f, -50.f},
+ std::make_shared<BodyTempLinFun>(-70.f, 0, -50.f, 1)},
+ {{-50.f, 40.f}, std::make_shared<BodyTempLinFun>(1, 0)},
+ {{40.f, 60.f}, std::make_shared<BodyTempLinFun>(40.f, 1, 60.f, 0)}},
+ 0));
+ BodyTempReliability.setAbsoluteReliabilityFunction(BodyTempAbsRel);
+
+ std::shared_ptr<Abstraction<BodyTempType, ReliabilityType>> BodyTempRelSlope(
+ new BodyTempParFun(
+ {{{-0.1f, -0.05f},
+ std::make_shared<BodyTempLinFun>(-0.1f, 0, -0.05f, 1)},
+ {{-0.05f, 0.05f}, std::make_shared<BodyTempLinFun>(1, 0)},
+ {{0.05f, 0.1f},
+ std::make_shared<BodyTempLinFun>(0.05f, 1, 0.1f, 0)}},
+ 0));
+ BodyTempReliability.setReliabilitySlopeFunction(BodyTempRelSlope);
+
//
// Create low-level application agents with \c createLowLevelAgent.
//
LOG_INFO("Creating low-level agents.");
AgentHandle HRAgent = createLowLevelAgent(App, "HR Agent", Decimation,
- HRConfidence, HRAbstraction);
+ HRAbstraction, HRReliability);
AgentHandle BRAgent = createLowLevelAgent(App, "BR Agent", Decimation,
- BRConfidence, BRAbstraction);
+ BRAbstraction, BRReliability);
AgentHandle SpO2Agent = createLowLevelAgent(App, "SpO2 Agent", Decimation,
- SpO2Confidence, SpO2Abstraction);
+ SpO2Abstraction, SpO2Reliability);
AgentHandle BPSysAgent = createLowLevelAgent(
- App, "BPSys Agent", Decimation, BPSysConfidence, BPSysAbstraction);
+ App, "BPSys Agent", Decimation, BPSysAbstraction, BPSysReliability);
AgentHandle BodyTempAgent =
- createLowLevelAgent(App, "BodyTemp Agent", Decimation, BodyTempConfidence,
- BodyTempAbstraction);
+ createLowLevelAgent(App, "BodyTemp Agent", Decimation,
+ BodyTempAbstraction, BodyTempReliability);
//
// Connect sensors to low-level agents.
//
LOG_INFO("Connect sensors to their corresponding low-level agents.");
App->connectSensor(HRAgent, 0, HRSensor, "HR Sensor Channel");
App->connectSensor(BRAgent, 0, BRSensor, "BR Sensor Channel");
App->connectSensor(SpO2Agent, 0, SpO2Sensor, "SpO2 Sensor Channel");
App->connectSensor(BPSysAgent, 0, BPSysSensor, "BPSys Sensor Channel");
App->connectSensor(BodyTempAgent, 0, BodyTempSensor,
"BodyTemp Sensor Channel");
//
// Create a high-level application agent.
//
LOG_INFO("Create high-level agent.");
- // The new agent logs its input values and results in the the sum of them.
- // \todo Additionally calculate cross-reliability for the warning score and
- // result a pair of those values.
+ // Slave positions on BodyAgent.
+ enum SlaveIndex : rosa::id_t {
+ HRIdx = 0,
+ BRIdx = 1,
+ SpO2Idx = 2,
+ BPSysIdx = 3,
+ BodyTempIdx = 4
+ };
+
+ CrossCombinator<WarningScoreType, ReliabilityType> BodyCrossCombinator;
+ BodyCrossCombinator.setCrossLikelinessParameter(1.5);
+
+ using WarningLikelinessFun =
+ LikelinessFunction<WarningScoreType, ReliabilityType>;
+
+ std::shared_ptr<WarningLikelinessFun> BRCrossLikelinessFun(
+ new WarningLikelinessFun(0.6));
+ BodyCrossCombinator.addCrossLikelinessProfile(HRIdx, BRIdx,
+ BRCrossLikelinessFun);
+ BodyCrossCombinator.addCrossLikelinessProfile(BRIdx, HRIdx,
+ BRCrossLikelinessFun);
+ BodyCrossCombinator.addCrossLikelinessProfile(BRIdx, SpO2Idx,
+ BRCrossLikelinessFun);
+ BodyCrossCombinator.addCrossLikelinessProfile(BRIdx, BPSysIdx,
+ BRCrossLikelinessFun);
+ BodyCrossCombinator.addCrossLikelinessProfile(BRIdx, BodyTempIdx,
+ BRCrossLikelinessFun);
+ BodyCrossCombinator.addCrossLikelinessProfile(SpO2Idx, BRIdx,
+ BRCrossLikelinessFun);
+ BodyCrossCombinator.addCrossLikelinessProfile(BPSysIdx, BRIdx,
+ BRCrossLikelinessFun);
+ BodyCrossCombinator.addCrossLikelinessProfile(BodyTempIdx, BRIdx,
+ BRCrossLikelinessFun);
+
+ std::shared_ptr<WarningLikelinessFun> HRBPCrossLikelinessFun(
+ new WarningLikelinessFun(2.5));
+ BodyCrossCombinator.addCrossLikelinessProfile(HRIdx, BPSysIdx,
+ HRBPCrossLikelinessFun);
+ BodyCrossCombinator.addCrossLikelinessProfile(BPSysIdx, HRIdx,
+ HRBPCrossLikelinessFun);
+
+ // The new agent logs its input values and results in a pair of the sum of
+ // received warning scores and their cross-reliability.
AgentHandle BodyAgent = App->createAgent(
"Body Agent",
- std::function<Optional<uint32_t>(
- std::pair<uint32_t, bool>, std::pair<uint32_t, bool>,
- std::pair<uint32_t, bool>, std::pair<uint32_t, bool>,
- std::pair<uint32_t, bool>)>(
- [](std::pair<uint32_t, bool> HR, std::pair<uint32_t, bool> BR,
- std::pair<uint32_t, bool> SpO2, std::pair<uint32_t, bool> BPSys,
- std::pair<uint32_t, bool> BodyTemp) -> Optional<uint32_t> {
+ std::function<Optional<WarningValue>(
+ std::pair<WarningValue, bool>, std::pair<WarningValue, bool>,
+ std::pair<WarningValue, bool>, std::pair<WarningValue, bool>,
+ std::pair<WarningValue, bool>)>(
+ [&](std::pair<WarningValue, bool> HR,
+ std::pair<WarningValue, bool> BR,
+ std::pair<WarningValue, bool> SpO2,
+ std::pair<WarningValue, bool> BPSys,
+ std::pair<WarningValue, bool> BodyTemp)
+ -> Optional<WarningValue> {
LOG_INFO_STREAM << "\n*******\nBody Agent trigged with values:\n"
<< (HR.second ? "<New>" : "<Old>")
- << " HR warning score: " << HR.first << "\n"
+ << " HR result: " << HR.first << "\n"
<< (BR.second ? "<New>" : "<Old>")
- << " BR warning score: " << BR.first << "\n"
+ << " BR result: " << BR.first << "\n"
<< (SpO2.second ? "<New>" : "<Old>")
- << " SpO2 warning score: " << SpO2.first << "\n"
+ << " SpO2 result: " << SpO2.first << "\n"
<< (BPSys.second ? "<New>" : "<Old>")
- << " BPSys warning score: " << BPSys.first << "\n"
+ << " BPSys result: " << BPSys.first << "\n"
<< (BodyTemp.second ? "<New>" : "<Old>")
- << " BodyTemp warning score: " << BodyTemp.first
+ << " BodyTemp result: " << BodyTemp.first
<< "\n******\n";
- return {HR.first + BR.first + SpO2.first + BPSys.first +
- BodyTemp.first};
+
+ using ValueType =
+ std::tuple<rosa::id_t, WarningScoreType, ReliabilityType>;
+ const std::vector<ValueType> SlaveValues{
+ {HRIdx, std::get<0>(HR.first), std::get<1>(HR.first)},
+ {BRIdx, std::get<0>(BR.first), std::get<1>(BR.first)},
+ {SpO2Idx, std::get<0>(SpO2.first), std::get<1>(SpO2.first)},
+ {BPSysIdx, std::get<0>(BPSys.first), std::get<1>(BPSys.first)},
+ {BodyTempIdx, std::get<0>(BodyTemp.first),
+ std::get<1>(BodyTemp.first)}};
+
+ const ReliabilityType crossReliability =
+ BodyCrossCombinator.getOutputLikeliness(SlaveValues);
+
+ struct ScoreSum {
+ void operator()(const ValueType &V) { ews += std::get<1>(V); }
+ WarningScoreType ews{0};
+ };
+ const ScoreSum scoreSum = std::for_each(
+ SlaveValues.cbegin(), SlaveValues.cend(), ScoreSum());
+
+ return {WarningValue(scoreSum.ews, crossReliability)};
}));
App->setExecutionPolicy(BodyAgent, AppExecutionPolicy::decimation(Decimation));
//
// Connect low-level agents to the high-level agent.
//
LOG_INFO("Connect low-level agents to the high-level agent.");
- App->connectAgents(BodyAgent, 0, HRAgent, "HR Agent Channel");
- App->connectAgents(BodyAgent, 1, BRAgent, "BR Agent Channel");
- App->connectAgents(BodyAgent, 2, SpO2Agent, "SpO2 Agent Channel");
- App->connectAgents(BodyAgent, 3, BPSysAgent, "BPSys Agent Channel");
- App->connectAgents(BodyAgent, 4, BodyTempAgent, "BodyTemp Agent Channel");
+ App->connectAgents(BodyAgent, HRIdx, HRAgent, "HR Agent Channel");
+ App->connectAgents(BodyAgent, BRIdx, BRAgent, "BR Agent Channel");
+ App->connectAgents(BodyAgent, SpO2Idx, SpO2Agent, "SpO2 Agent Channel");
+ App->connectAgents(BodyAgent, BPSysIdx, BPSysAgent, "BPSys Agent Channel");
+ App->connectAgents(BodyAgent, BodyTempIdx, BodyTempAgent,
+ "BodyTemp Agent Channel");
//
// For simulation output, create a logger agent writing the output of the
// high-level agent into a CSV file.
//
LOG_INFO("Create a logger agent.");
// Create CSV writer.
std::ofstream ScoreCSV(ScoreCSVPath);
- csv::CSVWriter<uint32_t> ScoreWriter(ScoreCSV);
+ csv::CSVTupleWriter<WarningScoreType, ReliabilityType> ScoreWriter(ScoreCSV);
// The agent writes each new input value into a CSV file and produces nothing.
// \note The execution of the logger is not subject to decimation.
- // \todo Print the pairs that are sent by BodyAgent into a multi-column CSV
- // file.
+ using logger_result = AppTuple<unit_t>;
AgentHandle LoggerAgent = App->createAgent(
"Logger Agent",
- std::function<Optional<unit_t>(std::pair<uint32_t, bool>)>(
- [&ScoreWriter](std::pair<uint32_t, bool> Score) -> Optional<unit_t> {
- if (Score.second) {
- // The state of \p ScoreWriter is not checked, expecting good.
- ScoreWriter << Score.first;
- }
+ std::function<Optional<logger_result>(std::pair<WarningValue, bool>)>(
+ [&ScoreWriter](
+ std::pair<WarningValue, bool> Score) -> Optional<logger_result> {
+ // The state of \p ScoreWriter is not checked, expecting good.
+ ScoreWriter << Score.first;
return {};
}));
//
// Connect the high-level agent to the logger agent.
//
LOG_INFO("Connect the high-level agent to the logger agent.");
App->connectAgents(LoggerAgent, 0, BodyAgent, "Body Agent Channel");
//
// Do simulation.
//
LOG_INFO("Setting up and performing simulation.");
//
// Initialize application for simulation.
//
App->initializeSimulation();
//
// Open CSV files and register them for their corresponding sensors.
//
// Type aliases for iterators.
using CSVDataIterator =
- CSVIterator<int32_t, int32_t, int32_t, int32_t, float>;
+ CSVIterator<HRType, BRType, SpO2Type, BPSysType, BodyTempType>;
std::ifstream DataCSV(DataCSVPath);
auto [HRRange, BRRange, SpO2Range, BPSysRange, BodyTempRange] =
splitTupleIterator(CSVDataIterator(DataCSV), CSVDataIterator());
App->registerSensorValues(HRSensor, std::move(begin(HRRange)), end(HRRange));
App->registerSensorValues(BRSensor, std::move(begin(BRRange)), end(BRRange));
App->registerSensorValues(SpO2Sensor, std::move(begin(SpO2Range)),
end(SpO2Range));
App->registerSensorValues(BPSysSensor, std::move(begin(BPSysRange)),
end(BPSysRange));
App->registerSensorValues(BodyTempSensor, std::move(begin(BodyTempRange)),
end(BodyTempRange));
//
// Simulate.
//
App->simulate(NumberOfSimulationCycles);
return 0;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Jul 4, 5:51 AM (5 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157480
Default Alt Text
(29 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment