Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F91267631
value_checker.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Nov 9, 12:35
Size
10 KB
Mime Type
text/x-c++
Expires
Mon, Nov 11, 12:35 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
22233098
Attached To
rSPECMICP SpecMiCP / ReactMiCP
value_checker.hpp
View Options
/* =============================================================================
Copyright (c) 2014 - 2016
F. Georget <fabieng@princeton.edu> Princeton University
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
============================================================================= */
#ifndef SPECMICP_UTILS_VALUECHECKER_HPP
#define SPECMICP_UTILS_VALUECHECKER_HPP
/*!
\file eigen/value_checker.hpp
\brief Framework to check and validate vectors
The user uses and/or define checker and predicates to validates the vector.
This is a header-only module using template metaprogramming.
Each checker and predicates are defined as types wich allows us to compose
them easily.
Example :
The following example check that :
- every value in the vector is finite and in the range [0.0, 1.0]
- at least one value is non-zero
\code{.cpp}
specmicp_upper_bound_predicate(LessOrEqualThanOne, 1.0);
bool check_vector(const Vector& vector) {
using predicate_all = PredicateAnd<
PredicateAnd<IsFinite,IsNonNegative>,
LessOrEqualThanOne
>;
using predicate_one = IsNonZero;
using checker = Composer<
TrueForAll<predicate_all>,
TrueForAtLeastOne<predicate_one>
>;
auto value = checker::check(vector);
if (value >= IsValidVector::error) {
ERROR << "Vector is incorrecct";
return false;
}
return true
}
\endcode
*/
#include "specmicp_common/types.hpp"
#include <functional>
namespace
specmicp
{
//! \brief namespace dedicated to functions and types used to validate vectors
namespace
value_checker
{
//! \brief Return code Of the checker
enum
class
IsValidVector
{
good
,
//!< Nothing to report
warning
,
//!< Something smells fishy
error
,
//!< Error, please correct
critical
//!< Mayde, Mayde, abort the computation
};
//! \brief Return the maximum error level between two error levels
constexpr
IsValidVector
max_error_level
(
IsValidVector
err1
,
IsValidVector
err2
)
{
return
(
err1
>
err2
)
?
err1:
err2
;
}
/*!
\brief Base class for a checker
\tparam Derived derived class
Derived class must implement the static check_impl method.
\code{.cpp}
struct DerivedValueChecker: public ValueChecker<DerivedValuedChecker>
{
static IsValidVector check_impl(const Vector& vector) {
// check vector
return IsValidVector::good;
}
};
\endcode
*/
template
<
typename
Derived
>
struct
ValueChecker
{
//! \brief Check the vector
static
IsValidVector
check
(
const
Vector
&
vector
)
{
return
Derived
::
check_impl
(
vector
);
}
};
//! \brief Compose two checkers together
//!
//! The composer will run the two checks and return the maximum error.
//! If Checker1 return a critical error, checker2 will not be run.
template
<
typename
Checker1
,
typename
Checker2
>
struct
Composer:
public
ValueChecker
<
Composer
<
Checker1
,
Checker2
>>
{
static
IsValidVector
check_impl
(
const
Vector
&
vector
)
{
auto
val1
=
Checker1
::
check
(
vector
);
if
(
val1
<
IsValidVector
::
critical
)
{
const
auto
val2
=
Checker2
::
check
(
vector
);
val1
=
max_error_level
(
val1
,
val2
);
};
return
val1
;
}
};
//! \brief Check if Predicate is true for every value in the vector
template
<
typename
Predicate
,
IsValidVector
error_level
=
IsValidVector
::
error
>
struct
TrueForAll:
public
ValueChecker
<
TrueForAll
<
Predicate
,
error_level
>>
{
static
IsValidVector
check_impl
(
const
Vector
&
vector
)
{
bool
flag
=
false
;
for
(
index_t
ind
=
0
;
ind
<
vector
.
rows
();
++
ind
)
{
if
(
not
Predicate
::
run
(
vector
(
ind
)))
{
flag
=
true
;
break
;
}
}
if
(
flag
)
return
error_level
;
return
IsValidVector
::
good
;
}
};
//! \brief Check if Predicate is true for at least one value in the vector
template
<
typename
Predicate
,
IsValidVector
error_level
=
IsValidVector
::
error
>
struct
TrueForAtLeastOne:
public
ValueChecker
<
TrueForAtLeastOne
<
Predicate
,
error_level
>>
{
static
IsValidVector
check_impl
(
const
Vector
&
vector
)
{
bool
flag
=
false
;
for
(
index_t
ind
=
0
;
ind
<
vector
.
rows
();
++
ind
)
{
if
(
Predicate
::
run
(
vector
(
ind
)))
{
flag
=
true
;
break
;
}
}
if
(
not
flag
)
return
error_level
;
return
IsValidVector
::
good
;
}
};
/*!
\brief Check the norm
\tparam Predicate a predicate (derived class of value_checker::Predicate)
\tparam error_level error level to raise if the condition is not true
\tparam p norm to use
use Eigen::Infinity for the infinit norm
\code{.cpp}
Vector vector;
// fill vector
using validator = NormChecker<IsFinite,
IsValidVector::Critical,
Eigen::Infinity>;
auto retcode = validator::check(vector);
\endcode
*/
template
<
typename
Predicate
,
IsValidVector
error_level
=
IsValidVector
::
error
,
int
p
=
2
>
struct
NormChecker:
public
ValueChecker
<
NormChecker
<
Predicate
,
error_level
>>
{
static
IsValidVector
check_impl
(
const
Vector
&
vector
)
{
const
scalar_t
norm
=
vector
.
lpNorm
<
p
>
();
if
(
not
Predicate
::
run
(
norm
))
return
error_level
;
return
IsValidVector
::
good
;
}
};
/*!
\brief Base class for a Predicate
The derived class must implement the
`bool function_impl(const scalar_t& value)' method.
Example
\code{cpp}
struct BiggerThan2: public Predicate<BiggerThan2> {
static bool functor_impl(const scalar_t& value) {
return (value > 2);
}
};
\endcode
Macros and common composer are defined to ease the process of creating predicates.
\sa PredicateNot, PredicateAnd, PredicateOr, PredicateXOr,
specmicp_create_value_predicate,
specmicp_lower_bound_predicate, specmicp_strict_lower_bound_predicate.
specmicp_upper_bound_predicate, specmicp_strict_upper_bound_predicate
*/
template
<
typename
Derived
>
struct
Predicate
{
//! \brief Evaluate the predicate
static
bool
run
(
const
scalar_t
&
value
)
{
return
Derived
::
run_impl
(
value
);
}
};
//! \brief Negate a predicate
template
<
typename
PredicateT
>
struct
PredicateNot:
public
Predicate
<
PredicateNot
<
PredicateT
>>
{
//! \brief Evaluate the predicate
static
bool
run_impl
(
const
scalar_t
&
value
)
{
return
(
not
PredicateT
::
run
(
value
));
}
};
/*!
\brief And operation on two predicates
Check that the two predicates are true
\code{.cpp}
using and_predicate = PredicateAnd<IsFinite,IsNonNegative>;
using checker = TrueForAll<and_predicate>;
auto retcode = checker::check(vector);
\endcode
*/
template
<
typename
Predicate1
,
typename
Predicate2
>
struct
PredicateAnd:
public
Predicate
<
PredicateAnd
<
Predicate1
,
Predicate2
>>
{
//! \brief Evaluate the predicate
static
bool
run_impl
(
const
scalar_t
&
value
)
{
return
(
Predicate1
::
run
(
value
)
and
Predicate2
::
run
(
value
));
}
};
//! \brief Or operation on two predicates
//!
//! Performs the or operation on two predicates
template
<
typename
Predicate1
,
typename
Predicate2
>
struct
PredicateOr:
public
Predicate
<
PredicateOr
<
Predicate1
,
Predicate2
>>
{
//! \brief Evaluate the predicate
static
bool
run_impl
(
const
scalar_t
&
value
)
{
return
(
Predicate1
::
run
(
value
)
or
Predicate2
::
run
(
value
));
}
};
//! \brief XOr operation on two predicates
//!
//! Performs the exclusive or operation on two predicates
template
<
typename
Predicate1
,
typename
Predicate2
>
struct
PredicateXOr:
public
Predicate
<
PredicateXOr
<
Predicate1
,
Predicate2
>>
{
//! \brief Evaluate the predicate
static
bool
run_impl
(
const
scalar_t
&
value
)
{
return
(
Predicate1
::
run
(
value
)
!=
Predicate2
::
run
(
value
));
}
};
}
//end namespace value_checker
}
//end namespace specmicp
/*!
\def specmicp_create_value_predicate
\brief Create a predicate with name 'name'
The expression must test 'value'
Example :
\code{.cpp}
specmicp_create_value_predicate(LowerThan5, (value < 5));
//
{
using checker = TrueForAll<LowerThan5>;
auto return_code = checker::check(vector);
}
\endcode
*/
#define specmicp_create_value_predicate(name, expression) \
struct name: public specmicp::value_checker::Predicate<name> { \
static bool run_impl(const scalar_t& value) { \
return (expression); \
} \
}
//! \def specmicp_lower_bound_predicate
//! \brief Create a predicate that check the lower bound
#define specmicp_lower_bound_predicate(name, bound) \
specmicp_create_value_predicate(name, (value >= bound))
//! \def specmicp_strict_lower_bound_predicate
//! \brief Create a predicate that check the lower bound
#define specmicp_strict_lower_bound_predicate(name, bound) \
specmicp_create_value_predicate(name, (value > bound))
//! \def specmicp_upper_bound_predicate
//! \brief Create a predicate that check the upper bound
#define specmicp_upper_bound_predicate(name, bound) \
specmicp_create_value_predicate(name, (value <= bound))
//! \def specmicp_strict_upper_bound_predicate
//! \brief Create a predicate that check the upper bound
#define specmicp_strict_upper_bound_predicate(name, bound) \
specmicp_create_value_predicate(name, (value < bound))
namespace
specmicp
{
namespace
value_checker
{
//! \class IsNonNegative
//! \brief Test if a value is non negative
specmicp_lower_bound_predicate
(
IsNonNegative
,
(
0.0
));
//! \class IsNonZero
//! \brief Test if a value is non zero
specmicp_create_value_predicate
(
IsNonZero
,
(
value
!=
0
));
//! \class IsFinite
//! \brief Test if a value is finite
specmicp_create_value_predicate
(
IsFinite
,
(
std
::
isfinite
(
value
)));
}
//end namespace value_checker
}
//end namespace specmicp
#endif
// SPECMICP_UTILS_VALUECHECKER_HPP
Event Timeline
Log In to Comment