Page MenuHomePhorge

No OneTemporary

Size
29 KB
Referenced Files
None
Subscribers
None
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

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)

Event Timeline