Skip to content

Commit

Permalink
Add ite expression
Browse files Browse the repository at this point in the history
This introduces Conditional expression constructs.

Issue #67
  • Loading branch information
rakhimov committed Apr 25, 2017
1 parent 36d39f0 commit 5a384ae
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 1 deletion.
14 changes: 14 additions & 0 deletions share/input.rng
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@
<choice>
<ref name="numerical-operation"/>
<ref name="Boolean-operation"/>
<ref name="conditional-operation"/>
</choice>
</define>

Expand Down Expand Up @@ -837,6 +838,19 @@
<!-- V.2.5. Conditional Expressions -->
<!-- *********************************************************** -->

<define name="conditional-operation">
<choice>
<ref name="if-then-else-operation"/>
</choice>
</define>

<define name="if-then-else-operation">
<element name="ite">
<ref name="expression"/>
<ref name="expression"/>
<ref name="expression"/>
</element>
</define>

<!-- *********************************************************** -->
<!-- V.2.6. Built-ins -->
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ set(SCRAM_CORE_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/element.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/parameter.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression/conditional.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression/constant.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression/numerical.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression/exponential.cc"
Expand Down
38 changes: 38 additions & 0 deletions src/expression/conditional.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2017 Olzhas Rakhimov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/// @file conditional.cc
/// Implementation of conditional expressions.

#include "conditional.h"

#include <algorithm>

namespace scram {
namespace mef {

Interval Ite::interval() noexcept {
assert(args().size() == 3);
Interval then_interval = args()[1]->interval();
Interval else_interval = args()[2]->interval();
return Interval::closed(
std::min(then_interval.lower(), else_interval.lower()),
std::max(then_interval.upper(), else_interval.upper()));
}

} // namespace mef
} // namespace scram
51 changes: 51 additions & 0 deletions src/expression/conditional.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2017 Olzhas Rakhimov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/// @file conditional.h
/// Conditional (if-then-else, switch-case) expressions.

#ifndef SCRAM_SRC_EXPRESSION_CONDITIONAL_H_
#define SCRAM_SRC_EXPRESSION_CONDITIONAL_H_

#include "src/expression.h"

namespace scram {
namespace mef {

/// If-Then-Else ternary expression.
class Ite : public ExpressionFormula<Ite> {
public:
/// @param[in] condition The Boolean expression to be tested.
/// @param[in] then_arm The expression if the Boolean is true.
/// @param[in] else_arm The expression if the Boolean is false.
Ite(Expression* condition, Expression* then_arm, Expression* else_arm)
: ExpressionFormula<Ite>({condition, then_arm, else_arm}) {}

Interval interval() noexcept override;

/// Computes the if-then-else expression with the given evaluator.
template <typename F>
double Compute(F&& eval) noexcept {
assert(args().size() == 3);
return eval(args()[0]) ? eval(args()[1]) : eval(args()[2]);
}
};

} // namespace mef
} // namespace scram

#endif // SCRAM_SRC_EXPRESSION_CONDITIONAL_H_
4 changes: 3 additions & 1 deletion src/initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "env.h"
#include "error.h"
#include "expression/boolean.h"
#include "expression/conditional.h"
#include "expression/exponential.h"
#include "expression/numerical.h"
#include "expression/random_deviate.h"
Expand Down Expand Up @@ -834,7 +835,8 @@ const Initializer::ExtractorMap Initializer::kExpressionExtractors_ = {
{"lt", &Extract<Lt>},
{"gt", &Extract<Gt>},
{"leq", &Extract<Leq>},
{"geq", &Extract<Geq>}};
{"geq", &Extract<Geq>},
{"ite", &Extract<Ite>}};

Expression* Initializer::GetExpression(const xmlpp::Element* expr_element,
const std::string& base_path) {
Expand Down
17 changes: 17 additions & 0 deletions tests/expression_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "expression.h"
#include "expression/boolean.h"
#include "expression/conditional.h"
#include "expression/exponential.h"
#include "expression/constant.h"
#include "expression/numerical.h"
Expand Down Expand Up @@ -1150,6 +1151,22 @@ TEST(ExpressionTest, Geq) {
EXPECT_DOUBLE_EQ(0, dev->value());
}

TEST(ExpressionTest, Ite) {
OpenExpression arg_one(1);
OpenExpression arg_two(42, 42, 32, 52);
OpenExpression arg_three(10, 10, 5, 15);
std::unique_ptr<Expression> dev;
ASSERT_NO_THROW(dev = std::make_unique<Ite>(&arg_one, &arg_two, &arg_three));
EXPECT_DOUBLE_EQ(42, dev->value());
arg_one.mean = 0;
EXPECT_DOUBLE_EQ(10, dev->value());
arg_one.mean = 0.5;
EXPECT_DOUBLE_EQ(42, dev->value());

EXPECT_TRUE(Interval::closed(5, 52) == dev->interval())
<< dev->interval();
}

} // namespace test
} // namespace mef
} // namespace scram
7 changes: 7 additions & 0 deletions tests/input/fta/correct_expressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -353,5 +353,12 @@ The input tries to utilize all the functionality including optional cases.
<bool value="false"/>
</geq>
</define-parameter>
<define-parameter name="if-then-else">
<ite>
<bool value="true"/>
<int value="42"/>
<float value="-42"/>
</ite>
</define-parameter>
</model-data>
</opsa-mef>

0 comments on commit 5a384ae

Please sign in to comment.