I think this is already very useful, but I want to to a step further: I want to reason over SWRL rules which evaluate data_properties which are defined by (simple) Python methods.
To demonstrate what I want I adapted the example from : I added a class "ExpensiveDrug" and a SWRL rule which should classify a Drug as expensive depending on the return value of get_per_tablet_cost.
However I cannot construct the rule that way. I get ValueError: Cannot find entity 'get_per_tablet_cost'!
Is it even possible to do what I want (i.e. software defined data properties)?
just my 2 cents, I might be wrong here tho:
a rule is specified using a string of a valid SWRL rule. i.e., it is not possible to evaluate a python function within the SWRL rule, simply because the reasoner is unable to do so.
in your example, what you intended to be a function call "get_per_tablet_cost" is interpreted as an entity, which cannot be found within the ontology
instead, you could use two separate SWRL rules. as a nice side effect, this also increases cohesion:
1. Insert costs per tablet into the ontology, see https://owlready2.readthedocs.io/en/latest/rule.html: 'Drug(?d), price(?d, ?p), number_of_tablets(?d, ?n), divide(?r, ?p, ?n) -> price_per_tablet(?d, ?r)'
2. Classification regarding the class "ExpensiveDrug" depending on the price: 'Drug(?d), price_per_tablet(?d, ?p), greaterThanOrEqual(?p, 10) -> ExpensiveDrug(?d)'
if there is a large number of rules, it may make sense to generate the SWRL strings using python functions defined within the respective classes. for this, mixing python and owl will probably come in real handy
thank you for your quick reply. I already suspected that the reasoner is not able to directly execute Python code. On the other hand it would not surprise me if there is a possibility to somehow sneak in a "callback-mechanism".
Your solution works for the presented example. However, I want to perform some more sophisticated calculations than mere arithmetic (say, calculating roots of polynomials etc.). I think that this will not be possible with pure SWRL but would be quite simple in Python code. At the end from the reasoners point of view it should not make too much difference, between calling a builtin function like "divide" or calling an external function. I might however be a technical challenge and break decidability (if one does not restrict the content of those external functions).
Anyway, your solution gave me the idea to run Python code and the reasoner alternately.