File: DLConceptTaxonomy.h

package info (click to toggle)
fact%2B%2B 1.6.5~dfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 4,496 kB
  • sloc: cpp: 28,000; java: 22,674; xml: 3,268; makefile: 102; ansic: 61; sh: 3
file content (338 lines) | stat: -rw-r--r-- 11,179 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
/* This file is part of the FaCT++ DL reasoner
Copyright (C) 2003-2015 Dmitry Tsarkov and The University of Manchester
Copyright (C) 2015-2016 Dmitry Tsarkov

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef DLCONCEPTTAXONOMY_H
#define DLCONCEPTTAXONOMY_H

#include "TaxonomyCreator.h"
#include "dlTBox.h"
#include "tProgressMonitor.h"

/// Taxonomy of named DL concepts (and mapped individuals)
class DLConceptTaxonomy: public TaxonomyCreator
{
protected:	// types
	typedef std::vector<TaxonomyVertex*> TaxVertexVec;
		/// all the derived subsumers of a class (came from the model)
	class DerivedSubsumers: public KnownSubsumers
	{
	protected:	// typedefs
			/// set of the subsumers
		typedef TaxonomyCreator::SubsumerSet SubsumerSet;
			/// SS RW iterator
		typedef SubsumerSet::iterator ss_iterator;

	protected:	// members
			/// set of sure- and possible subsumers
		SubsumerSet Sure, Possible;

	public:		// interface
			/// c'tor: copy given sets
		DerivedSubsumers ( const SubsumerSet& sure, const SubsumerSet& possible )
			: KnownSubsumers()
			, Sure(sure)
			, Possible(possible)
			{}
			/// empty d'tor
		virtual ~DerivedSubsumers ( void ) {}

		// iterators

			/// begin of the Sure subsumers interval
		virtual ss_iterator s_begin ( void ) { return Sure.begin(); }
			/// end of the Sure subsumers interval
		virtual ss_iterator s_end ( void ) { return Sure.end(); }
			/// begin of the Possible subsumers interval
		virtual ss_iterator p_begin ( void ) { return Possible.begin(); }
			/// end of the Possible subsumers interval
		virtual ss_iterator p_end ( void ) { return Possible.end(); }
	}; // DerivedSubsumers

protected:	// members
		/// host tBox
	TBox& tBox;
		/// incremental sets M+ and M-
	std::set<const TNamedEntity*> MPlus, MMinus;
		/// set of possible parents
	std::set<TaxonomyVertex*> candidates;
		/// whether look into it
	bool useCandidates;
		/// common descendants of all parents of currently classified concept
	TaxVertexVec Common;
		/// number of processed common parents
	unsigned int nCommon;

	// statistic counters
	unsigned long nConcepts;
	unsigned long nTries;
	unsigned long nPositives;
	unsigned long nNegatives;
	unsigned long nSearchCalls;
	unsigned long nSubCalls;
	unsigned long nNonTrivialSubCalls;

		/// number of positive cached subsumptions
	unsigned long nCachedPositive;
		/// number of negative cached subsumptions
	unsigned long nCachedNegative;
		/// number of non-subsumptions detected by a sorted reasoning
	unsigned long nSortedNegative;
		/// number of non-subsumptions because of module reasons
	unsigned long nModuleNegative;

		/// indicator of taxonomy creation progress
	TProgressMonitor* pTaxProgress;

	// flags

		/// flag to use Bottom-Up search
	bool flagNeedBottomUp;

private:	// no copy
		/// no copy c'tor
	DLConceptTaxonomy ( const DLConceptTaxonomy& );
		/// no assignment
	DLConceptTaxonomy& operator = ( const DLConceptTaxonomy& );

protected:	// methods
	//-----------------------------------------------------------------
	//--	General support for DL concept classification
	//-----------------------------------------------------------------

		/// get access to curEntry as a TConcept
	const TConcept* curConcept ( void ) const { return static_cast<const TConcept*>(curEntry); }
		/// tests subsumption (via tBox) and gather statistics.  Use cache and other optimisations.
	bool testSub ( const TConcept* p, const TConcept* q );
		/// test subsumption via TBox explicitly
	bool testSubTBox ( const TConcept* p, const TConcept* q )
	{
		bool res = tBox.isSubHolds ( p, q );

		// update statistic
		++nTries;

		if ( res )
			++nPositives;
		else
			++nNegatives;

		return res;
	}

	// interface from BAADER paper

		/// SEARCH procedure from Baader et al paper
	void searchBaader ( TaxonomyVertex* cur );
		/// ENHANCED_SUBS procedure from Baader et al paper
	bool enhancedSubs1 ( TaxonomyVertex* cur );
		/// short-cut from ENHANCED_SUBS
	bool enhancedSubs2 ( TaxonomyVertex* cur )
	{
		// if bottom-up search and CUR is not a successor of checking entity -- return false
		if ( unlikely(upDirection && !cur->isCommon()) )
			return false;
		if ( unlikely ( useCandidates && candidates.find(cur) == candidates.end() ) )
			return false;
		return enhancedSubs1(cur);
	}
		// wrapper for the ENHANCED_SUBS
	inline bool enhancedSubs ( TaxonomyVertex* cur )
	{
		++nSubCalls;

		if ( isValued(cur) )
			return getValue(cur);
		else
			return setValue ( cur, enhancedSubs2(cur) );
	}
		/// explicitly test appropriate subsumption relation
	bool testSubsumption ( TaxonomyVertex* cur );
		/// test whether a node could be a super-node of CUR
	bool possibleSub ( TaxonomyVertex* v ) const
	{
		const TConcept* C = static_cast<const TConcept*>(v->getPrimer());
		// non-prim concepts are candidates
		if ( !C->isPrimitive() )
			return true;
		// all others should be in the possible sups list
		return ksStack.top()->isPossibleSub(C);
	}
		/// @return true if non-subsumption is due to ENTITY is not in the \bot-module
	bool isNotInModule ( const TNamedEntity* entity ) const;
		/// reclassify node
	void reclassify ( TaxonomyVertex* node, const TSignature* s );

		/// propagate common value from NODE to all its descendants; save visited nodes
	void propagateOneCommon ( TaxonomyVertex* node );
		/// mark as COMMON all vertexes that are sub-concepts of every parent of CURRENT
	bool propagateUp ( void );
		/// clear all COMMON information
	void clearCommon ( void )
	{
		for ( TaxVertexVec::iterator p = Common.begin(), p_end = Common.end(); p < p_end; ++p )
			(*p)->clearCommon();
		Common.clear();
	}
		/// check if concept is unsat; add it as a synonym of BOTTOM if necessary
	bool isUnsatisfiable ( void );
		/// fill candidates
	void fillCandidates ( TaxonomyVertex* cur );

	//-----------------------------------------------------------------
	//--	Tunable methods (depending on taxonomy type)
	//-----------------------------------------------------------------

		/// prepare told subsumers for given entry if necessary
	virtual KnownSubsumers* buildKnownSubsumers ( ClassifiableEntry* p );
		/// prepare signature for given entry
	virtual const TSignature* buildSignature ( ClassifiableEntry* p );
		/// check if no classification needed (synonym, orphan, unsatisfiable)
	virtual bool immediatelyClassified ( void );
		/// check if no BU classification is required as C=TOP
	bool isEqualToTop ( void );

		/// check if it is possible to skip TD phase
	virtual bool needTopDown ( void ) const
		{ return !(useCompletelyDefined && curEntry->isCompletelyDefined ()); }
		/// explicitly run TD phase
	virtual void runTopDown ( void ) { searchBaader(pTax->getTopVertex()); }
		/// check if it is possible to skip BU phase
	virtual bool needBottomUp ( void ) const
	{
		// we DON'T need bottom-up phase for primitive concepts during CD-like reasoning
		// if no GCIs are in the TBox (C [= T, T [= X or Y, X [= D, Y [= D) or (T [= {o})
		// or no reflexive roles w/RnD present (Refl(R), Range(R)=D)
		return flagNeedBottomUp || !useCompletelyDefined || curConcept()->isNonPrimitive();
	}
		/// explicitly run BU phase
	virtual void runBottomUp ( void )
	{
		if ( propagateUp() )	// Common is set up here
			return;
		if ( isEqualToTop() )	// nothing to do
			return;
		if ( pTax->queryMode() )	// after classification -- bottom set up already
			searchBaader(pTax->getBottomVertex());
		else	// during classification -- have to find leaf nodes
			for ( TaxVertexVec::iterator p = Common.begin(), p_end = Common.end(); p < p_end; ++p )
				if ( (*p)->noNeighbours(/*upDirection=*/false) )
					searchBaader(*p);
	}

		/// actions that to be done BEFORE entry will be classified
	virtual void preClassificationActions ( void )
	{
		++nConcepts;
		if ( pTaxProgress != NULL )
			pTaxProgress->nextClass();
	}
		/// @return true iff curEntry is classified as a synonym
	virtual bool classifySynonym ( void );

		/// check if it is necessary to log taxonomy action
	virtual bool needLogging ( void ) const { return true; }

public:		// interface
		/// the only c'tor
	DLConceptTaxonomy ( Taxonomy* tax, TBox& kb )
		: TaxonomyCreator(tax)
		, tBox(kb)
		, useCandidates(false)
		, nCommon(0)
		, nConcepts (0), nTries (0), nPositives (0), nNegatives (0)
		, nSearchCalls(0)
		, nSubCalls(0)
		, nNonTrivialSubCalls(0)
		, nCachedPositive(0)
		, nCachedNegative(0)
		, nSortedNegative(0)
		, nModuleNegative(0)
		, pTaxProgress (NULL)
	{
	}
		/// d'tor
	virtual ~DLConceptTaxonomy ( void ) {}

		/// set bottom-up flag
	void setBottomUp ( const TKBFlags& GCIs ) { flagNeedBottomUp = (GCIs.isGCI() || (GCIs.isReflexive() && GCIs.isRnD())); }
		/// reclassify taxonomy wrt changed sets
	void reclassify ( const std::set<const TNamedEntity*>& MPlus, const std::set<const TNamedEntity*>& MMinus );
		/// set progress indicator
	void setProgressIndicator ( TProgressMonitor* pMon ) { pTaxProgress = pMon; }
		/// output taxonomy to a stream
	virtual void print ( std::ostream& o ) const;
}; // DLConceptTaxonomy

//
// DLConceptTaxonomy implementation
//

inline bool DLConceptTaxonomy :: isUnsatisfiable ( void )
{
	const TConcept* p = curConcept();

	if ( tBox.isSatisfiable(p) )
		return false;

	pTax->addCurrentToSynonym(pTax->getBottomVertex());
	return true;
}

inline bool DLConceptTaxonomy :: immediatelyClassified ( void )
{
	if ( classifySynonym() )
		return true;

	if ( curConcept()->getClassTag() == cttTrueCompletelyDefined )
		return false;	// true CD concepts can not be unsat

	// after SAT testing plan would be implemented
	tBox.initCache(const_cast<TConcept*>(curConcept()));

	return isUnsatisfiable();
}

//-----------------------------------------------------------------------------
//--		implementation of taxonomy-related parts of TBox
//-----------------------------------------------------------------------------

inline void
TBox :: initTaxonomy ( void )
{
	pTax = new Taxonomy ( pTop, pBottom );
	pTaxCreator = new DLConceptTaxonomy ( pTax, *this );
}

inline void
TBox :: classifyEntry ( TConcept* entry )
{
	if ( unlikely(isBlockedInd(entry)) )
		classifyEntry(getBlockingInd(entry));	// make sure that the possible synonym is already classified
	if ( !entry->isClassified() )
		pTaxCreator->classifyEntry(entry);
}

inline void
TBox :: reclassify ( const std::set<const TNamedEntity*>& MPlus, const std::set<const TNamedEntity*>& MMinus )
{
	pTaxCreator->reclassify ( MPlus, MMinus );
	Status = kbRealised;	// FIXME!! check whether it is classified/realised
}

#endif // DLCONCEPTTAXONOMY_H