Skip to content

Commit

Permalink
Add 'cowl_ontology_iterate_axioms_matching'
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanoBilenchi committed Mar 7, 2024
1 parent e25ca19 commit ec76ab1
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/cowl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "cowl_attrs.h"
#include "cowl_axiom.h"
#include "cowl_axiom_flags.h"
#include "cowl_axiom_index.h"
#include "cowl_axiom_type.h"
#include "cowl_card_type.h"
#include "cowl_char_axiom_type.h"
Expand Down
113 changes: 113 additions & 0 deletions include/cowl_axiom_index.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* Defines CowlAxiomIndex and declares its API.
*
* @author Ivano Bilenchi
*
* @copyright Copyright (c) 2024 SisInf Lab, Polytechnic University of Bari
* @copyright <http://swot.sisinflab.poliba.it>
* @copyright SPDX-License-Identifier: EPL-2.0
*
* @file
*/

#ifndef COWL_AXIOM_INDEX_H
#define COWL_AXIOM_INDEX_H

#include "cowl_axiom_flags.h"
#include "cowl_vector.h"

COWL_BEGIN_DECLS

/// @cond
uvec_decl(CowlObjectPtr);
/// @endcond

/// Axiom index parameters.
typedef struct CowlAxiomIndex {

/// Match axioms of the specified types.
CowlAxiomFlags types;

/// Match axioms referencing all the specified primitives.
UVec(CowlObjectPtr) primitives;

} CowlAxiomIndex;

/**
* @defgroup CowlAxiomIndex CowlAxiomIndex API
* @{
*/

/**
* Returns a new axiom index.
*
* @return Axiom index.
*/
COWL_CONST
COWL_INLINE
CowlAxiomIndex cowl_axiom_index(void) {
CowlAxiomIndex ret = { COWL_AF_ALL, uvec(CowlObjectPtr) };
return ret;
}

/**
* De-initializes an axiom index previously initialized via @func{#cowl_axiom_index()}.
*
* @param index Axiom index.
*/
COWL_INLINE
void cowl_axiom_index_deinit(CowlAxiomIndex *index) {
uvec_deinit(CowlObjectPtr, &index->primitives);
}

/**
* Adds the specified axiom type to the index.
*
* @param index Axiom index.
* @param type Axiom type.
*/
COWL_INLINE
void cowl_axiom_index_add_type(CowlAxiomIndex *index, CowlAxiomType type) {
index->types = ubit_set(COWL_AF, index->types, cowl_axiom_flags_from_type(type));
}

/**
* Removes the specified axiom type from the index.
*
* @param index Axiom index.
* @param type Axiom type.
*/
COWL_INLINE
void cowl_axiom_index_remove_type(CowlAxiomIndex *index, CowlAxiomType type) {
index->types = ubit_unset(COWL_AF, index->types, cowl_axiom_flags_from_type(type));
}

/**
* Adds the specified primitive to the index.
*
* @param index Axiom index.
* @param primitive Primitive.
* @return Return code.
*/
COWL_INLINE
cowl_ret cowl_axiom_index_add_primitive(CowlAxiomIndex *index, CowlAnyPrimitive *primitive) {
uvec_ret ret = uvec_push_unique(CowlObjectPtr, &index->primitives, primitive);
return ret == UVEC_ERR ? COWL_ERR_MEM : COWL_OK;
}

/**
* Removes the specified primitive from the index.
*
* @param index Axiom index.
* @param primitive Primitive.
*/
COWL_INLINE
void cowl_axiom_index_remove_primitive(CowlAxiomIndex *index, CowlAnyPrimitive *primitive) {
uvec_remove(CowlObjectPtr, &index->primitives, primitive);
}

/// @}

COWL_END_DECLS

#endif // COWL_AXIOM_INDEX_H
16 changes: 16 additions & 0 deletions include/cowl_ontology.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ COWL_BEGIN_DECLS

/// @cond
cowl_struct_decl(CowlAnnotation);
cowl_struct_decl(CowlAxiomIndex);
cowl_struct_decl(CowlClass);
cowl_struct_decl(CowlManager);
cowl_struct_decl(CowlSymTable);
Expand Down Expand Up @@ -378,6 +379,21 @@ COWL_API
bool cowl_ontology_iterate_axioms_for_primitive(CowlOntology *onto, CowlAnyPrimitive *primitive,
CowlIterator *iter, bool imports);

/**
* Iterates over the axioms matching the specified index.
*
* @param onto The ontology.
* @param index The index.
* @param iter The iterator.
* @param imports If true, the query recurses over imported ontologies.
* @return True if the iteration was completed, false if it was stopped.
*
* @note The index must not be used anymore after calling this function.
*/
COWL_API
bool cowl_ontology_iterate_axioms_matching(CowlOntology *onto, CowlAxiomIndex *index,
CowlIterator *iter, bool imports);

/**
* Iterates over the constructs that are related to the specified primitive by some axiom.
*
Expand Down
2 changes: 1 addition & 1 deletion lib/ulib
125 changes: 125 additions & 0 deletions src/cowl_ontology.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,131 @@ bool cowl_ontology_iterate_axioms_for_primitive(CowlOntology *onto, CowlAnyPrimi
return true;
}

static CowlAnyPrimitive *
cowl_ontology_best_primitive_for_index(CowlOntology *onto, CowlAxiomIndex *index, bool imports) {
if (!ubit_is_any_set(COWL_AF, index->types, COWL_AF_ALL)) {
// No types specified in the index.
return NULL;
}

CowlAnyPrimitive *best = NULL;
ulib_uint count = ULIB_UINT_MAX;

uvec_foreach (CowlObjectPtr, &index->primitives, p) {
ulib_uint c = cowl_ontology_axiom_count_for_primitive(onto, *p.item, true);
if (c < count) {
best = *p.item;
count = c;
}
}

if (!ubit_is_set(COWL_AF, index->types, COWL_AF_ALL)) {
ulib_uint c = cowl_ontology_axiom_count_for_types(onto, index->types, imports);
if (c < count) best = NULL;
}

if (!count) {
// Index matches an empty set of axioms.
index->types = COWL_AF_NONE;
return NULL;
}

if (best) {
// We will be iterating over this primitive's index,
// no need to check for it in the iterator.
cowl_axiom_index_remove_primitive(index, best);
}

return best;
}

struct MatchingCtx {
CowlAxiomFlags types;
UVec(CowlObjectPtr) *primitives;
CowlIterator *iter;
};

static bool for_each_check_type(void *ctx, CowlAnyAxiom *axiom) {
struct MatchingCtx *mctx = ctx;
if (!cowl_axiom_flags_has_type(mctx->types, cowl_axiom_get_type(axiom))) return true;
return cowl_iterate(mctx->iter, axiom);
}

static bool for_each_check_primitives(void *ctx, CowlAnyAxiom *axiom) {
struct MatchingCtx *mctx = ctx;
uvec_foreach (CowlObjectPtr, mctx->primitives, p) {
if (!cowl_has_primitive(axiom, *p.item)) return true;
}
return cowl_iterate(mctx->iter, axiom);
}

static bool for_each_check_both(void *ctx, CowlAnyAxiom *axiom) {
struct MatchingCtx *mctx = ctx;
if (!cowl_axiom_flags_has_type(mctx->types, cowl_axiom_get_type(axiom))) return true;
uvec_foreach (CowlObjectPtr, mctx->primitives, p) {
if (!cowl_has_primitive(axiom, *p.item)) return true;
}
return cowl_iterate(mctx->iter, axiom);
}

bool cowl_ontology_iterate_axioms_matching(CowlOntology *onto, CowlAxiomIndex *index,
CowlIterator *iter, bool imports) {
bool ret = true;
CowlAxiomIndex local_index;

if (index) {
local_index = *index;
*index = (CowlAxiomIndex){ 0 };
} else {
local_index = cowl_axiom_index();
}

struct MatchingCtx ctx = {
.types = local_index.types,
.primitives = &local_index.primitives,
.iter = iter,
};

CowlAnyPrimitive *best = cowl_ontology_best_primitive_for_index(onto, &local_index, imports);
if (!best && local_index.types == COWL_AF_NONE) goto end;

bool all_types = ubit_is_set(COWL_AF, local_index.types, COWL_AF_ALL);
bool all_primitives = !uvec_count(CowlObjectPtr, &local_index.primitives);

if (best) {
// Iterate over axioms referencing the primitive.
if (all_types && all_primitives) {
ret = cowl_ontology_iterate_axioms_for_primitive(onto, best, iter, imports);
} else if (all_types) {
CowlIterator l_iter = { .ctx = &ctx, .for_each = for_each_check_primitives };
ret = cowl_ontology_iterate_axioms_for_primitive(onto, best, &l_iter, imports);
} else if (all_primitives) {
CowlIterator l_iter = { .ctx = &ctx, .for_each = for_each_check_type };
ret = cowl_ontology_iterate_axioms_for_primitive(onto, best, &l_iter, imports);
} else {
CowlIterator l_iter = { .ctx = &ctx, .for_each = for_each_check_both };
ret = cowl_ontology_iterate_axioms_for_primitive(onto, best, &l_iter, imports);
}
} else {
// Iterate over axiom of the specified types.
if (all_types && all_primitives) {
ret = cowl_ontology_iterate_axioms(onto, iter, imports);
} else if (all_types) {
CowlIterator l_iter = { .ctx = &ctx, .for_each = for_each_check_primitives };
ret = cowl_ontology_iterate_axioms(onto, &l_iter, imports);
} else if (all_primitives) {
ret = cowl_ontology_iterate_axioms_of_types(onto, local_index.types, iter, imports);
} else {
CowlIterator l_iter = { .ctx = &ctx, .for_each = for_each_check_primitives };
ret = cowl_ontology_iterate_axioms_of_types(onto, local_index.types, &l_iter, imports);
}
}

end:
cowl_axiom_index_deinit(&local_index);
return ret;
}

struct CowlRelatedCtx {
CowlAxiomType type;
CowlPosition position;
Expand Down

0 comments on commit ec76ab1

Please sign in to comment.