Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

638 Breadth-First Search (BFS) algorithm #194

Draft
wants to merge 22 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
498 changes: 498 additions & 0 deletions include/graphblas/algorithms/bfs.hpp

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions include/graphblas/base/internalops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,120 @@ namespace grb {
/** Core implementations of the standard operators in #grb::operators. */
namespace internal {

/**
* Standard negation operator.
*
* Assumes native availability of ! on the given data types or assumes that
* the relevant operators are properly overloaded.
*
* @tparam Op The Operator class to negate.
* Requires the following typedefs:
* - \b D1: The left-hand input domain.
* - \b D2: The right-hand input domain.
* - \b D3: The output domain.
* - \b operator_type: The internal::operator type to negate.
*/
template<
class Op,
enum Backend implementation = config::default_backend
>
class logical_not {
public:

/** Alias to the left-hand input data type. */
typedef typename Op::D1 left_type;

/** Alias to the right-hand input data type. */
typedef typename Op::D2 right_type;

/** Alias to the output data type. */
typedef typename Op::D3 result_type;

/** Whether this operator has an inplace foldl. */
static constexpr bool has_foldl = Op::operator_type::has_foldl;

/** Whether this operator has an inplace foldr. */
static constexpr bool has_foldr = Op::operator_type::has_foldr;

/**
* Whether this operator is \em mathematically associative; that is,
* associative when assuming equivalent data types for \a IN1, \a IN2,
* and \a OUT, as well as assuming exact arithmetic, no overflows, etc.
*/
static constexpr bool is_associative = Op::operator_type::is_associative;

/**
* Whether this operator is \em mathematically commutative; that is,
* commutative when assuming equivalent data types for \a IN1, \a IN2,
* and \a OUT, as well as assuming exact arithmetic, no overflows, etc.
*/
static constexpr bool is_commutative = Op::operator_type::is_commutative;

/**
* Out-of-place application of the operator.
*
* @param[in] a The left-hand side input. Must be pre-allocated and
* initialised.
* @param[in] b The right-hand side input. Must be pre-allocated and
* initialised.
* @param[out] c The output. Must be pre-allocated.
*/
static void apply(
const left_type * __restrict__ const a,
const right_type * __restrict__ const b,
result_type * __restrict__ const c,
const typename std::enable_if<
std::is_convertible< result_type, bool >::value,
void
>::type * = nullptr
) {
Op::operator_type::apply( a, b, c );
*c = !*c;
}

/**
* In-place left-to-right folding.
*
* @param[in] a Pointer to the left-hand side input data.
* @param[in,out] c Pointer to the right-hand side input data. This also
* dubs as the output memory area.
*/
static void foldr(
const left_type * __restrict__ const a,
result_type * __restrict__ const c,
const typename std::enable_if<
std::is_convertible< result_type, bool >::value,
void
>::type * = nullptr
) {
Op::operator_type::foldr( a, c );
*c = !*c;
}

/**
* In-place right-to-left folding.
*
* @param[in,out] c Pointer to the left-hand side input data. This also
* dubs as the output memory area.
* @param[in] b Pointer to the right-hand side input data.
*/
static void foldl(
result_type * __restrict__ const c,
const right_type * __restrict__ const b,
const typename std::enable_if<
std::is_convertible< result_type, bool >::value,
void
>::type * = nullptr
) {
Op::operator_type::foldl( c, b );
*c = !*c;
}
};

template< class Op >
class not_op : public logical_not< Op > {};


/**
* Standard argmin operator.
*
Expand Down Expand Up @@ -4179,6 +4293,9 @@ namespace grb {
/** The output domain of this operator. */
typedef typename OperatorBase< OP >::D3 D3;

/** The type of the operator OP. */
typedef OP operator_type;

/**
* Reduces a vector of type \a InputType into a value in \a IOType
* by repeated application of this operator. The \a IOType is cast
Expand Down
50 changes: 50 additions & 0 deletions include/graphblas/ops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,30 @@ namespace grb {
*/
namespace operators {

/**
* This operator discards all right-hand side input and simply copies the
* left-hand side input to the output variable. It exposes the complete
* interface detailed in grb::operators::internal::Operator. This operator
* can be passed to any GraphBLAS function or object constructor.
*
* Mathematical notation: \f$ \odot(x,y)\ \to\ x \f$.
*
* @tparam Op The operator to negate.
*/
template<
class Op
>
class logical_not : public internal::Operator< internal::logical_not< Op > > {

public:

template< class A >
using GenericOperator = logical_not< A >;

logical_not() {}

};

/**
* This operator discards all right-hand side input and simply copies the
* left-hand side input to the output variable. It exposes the complete
Expand Down Expand Up @@ -499,6 +523,22 @@ namespace grb {
logical_and() {}
};

template<
typename D1, typename D2 = D1, typename D3 = D2,
enum Backend implementation = config::default_backend
>
class logical_nand : public logical_not<
logical_and< D1, D2, D3, implementation >
> {

public:

template< typename A, typename B, typename C, enum Backend D >
using GenericOperator = logical_nand< A, B, C, D >;

logical_nand() {}
};

/**
* This operation is equivalent to #grb::operators::min.
*
Expand Down Expand Up @@ -981,6 +1021,11 @@ namespace grb {

} // namespace operators

template< class Op >
struct is_operator< operators::logical_not< Op > > {
static const constexpr bool value = is_operator< Op >::value;
};

template< typename D1, typename D2, typename D3, enum Backend implementation >
struct is_operator< operators::left_assign_if< D1, D2, D3, implementation > > {
static const constexpr bool value = true;
Expand Down Expand Up @@ -1063,6 +1108,11 @@ namespace grb {
static const constexpr bool value = true;
};

template< typename D1, typename D2, typename D3, enum Backend implementation >
struct is_operator< operators::logical_nand< D1, D2, D3, implementation > > {
static const constexpr bool value = true;
};

template< typename D1, typename D2, typename D3, enum Backend implementation >
struct is_operator< operators::abs_diff< D1, D2, D3, implementation > > {
static const constexpr bool value = true;
Expand Down
5 changes: 5 additions & 0 deletions tests/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ add_grb_executables( from_mpi_launch_simple_pagerank_broadcast simple_pagerank_b
ADDITIONAL_LINK_LIBRARIES MPI::MPI_CXX
)

add_grb_executables( bfs bfs.cpp
BACKENDS reference reference_omp hyperdags nonblocking
ADDITIONAL_LINK_LIBRARIES test_utils
)

add_grb_executables( knn knn.cpp ../unit/parser.cpp
BACKENDS reference reference_omp bsp1d hybrid hyperdags nonblocking
)
Expand Down
Loading