What you want to do seems to be better handled, IMO, with a custom piece of code in your favourite programming language. Difficult to express these kinds of things in OWL, and certainly not efficient.
But FWIW, here is something you can do. Fasten your seat belt, here begins a trip to advanced OWL 2 modelling. Assume that you have the base colours "blue", "green", "red". You can define a datatype that includes the three strings (I use Turtle syntax):
:baseColor a rdfs:Datatype;
owl:equivalentClass [
a rdfs:Datatype;
owl:withRestrictions ( [ xsd:pattern "blue|green|red" ] )
] .
Then you can define modified colours:
:modColor a rdfs:Datatype;
owl:equivalentClass [
a rdfs:Datatype;
owl:withRestrictions (
[ xsd:pattern "(dark|light)?(blue|green|red)(ish)?" ]
)
] .
you could even have more datatypes such as :lightColor
, :darkColor
, mediumColor
.
Then you make a class :Color
that has a datatype property :hasColor
:
:hasColor a owl:DatatypeProperty;
rdfs:domain :Color;
rdfs:range [
a rdfs:Dataype;
owl:unionOf ( :baseColor :modColor )
]
:Color a owl:Class;
rdfs:subClassOf [
a owl:Restriction;
owl:onProperty :hasColor;
owl:someValuesFrom xsd:string
];
owl:hasKey ( :hasColor ) .
Here, I impose that instances of :Color
have at least a color string and I impose that the color string is a unique identifier for the color (it's a key). So, whenever I have a color given with its color string, I can verify that the string is in the regex patterns given above. Assuming I defined the datatypes :darkColor
, :lightColor
and :mediumColor
, I can also express the :darker
and :lighter
relations:
:DarkColor a owl:Class;
rdfs:subClassOf :Color, [
a owl:Restriction;
owl:onProperty :hasColor;
owl:allValuesFrom :darkColor
] .
:LightColor a owl:Class;
rdfs:subClassOf :Color, [
a owl:Restriction;
owl:onProperty :hasColor;
owl:allValuesFrom :lightColor
] .
:MediumColor a owl:Class;
rdfs:subClassOf :Color, [
a owl:Restriction;
owl:onProperty :hasColor;
owl:allValuesFrom :mediumColor
] .
Then you want to say that all :DarkColor
s are :darker
than all :MediumColor
and all :LightColor
. Such an axiom is not trivial to implement as it demands to introduce auxiliary terms. It is explained in the paper All Elephants are Bigger than All Mice and it's called, in DL terminology, concept product:
:p1 a owl:ObjectProperty . # auxiliary property (do not reuse elsewhere)
:p2 a owl:ObjectProperty . # idem
:x a owl:Thing . # auxiliary individual
:darker owl:propertyChainAxiom ( :p1 :p2 ) .
:DarkColor rdfs:subClassOf [
a owl:Restriction;
owl:onProperty :p1;
owl:hasValue :x
] .
[ owl:unionOf ( :LightColor :MediumColor ) ] rdfs:SubClassOf [
a owl:Restriction;
owl:onProperty [ owl:inverseOf :p2 ];
owl:hasValue :x
] .
Do the same for :lighter
.
You can't really introduce the modified colours automatically. You really have to provide a pattern that contain all the base colors + the modifiers. But this can easily be done programmatically. In any case, the OWL code that I give should not be used, IMO, as it's much better/more efficiently addressed by a customised programme.