Ensure rule tags of all dropped rule matches are propagated as algo output (MPSCR-32)

This commit is contained in:
Grigorii Kirgizov 2020-02-04 19:31:10 +03:00
parent 73ebfbe7d1
commit 438d8e6e9a
3 changed files with 29 additions and 11 deletions

View File

@ -48,8 +48,13 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
: StoreAwareJournalImpl(journal, logicalState)
{
private val journalIndex: MatchJournal.Index = journal.index()
private val execQueue: ExecutionQueue = ExecutionQueue(journalIndex, RuleOrdering(ruleIndex))
// tags of rule matches discarded at queue execution
private val rewrittenRuleMatches: MutableSet<Any> = mutableSetOf<Any>()
private data class MatchCandidate(val rule: Rule, val occChunk: MatchJournal.OccChunk)
@ -83,7 +88,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
while (it.hasNext()) {
val chunk = it.next()
if (chunk is MatchJournal.MatchChunk && ruleIds.contains(chunk.match.rule().uniqueTag())) {
if (chunk is MatchJournal.MatchChunk && ruleIds.contains(chunk.ruleUniqueTag)) {
justificationRoots.add(chunk.id)
}
@ -99,7 +104,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
if (chunk is MatchJournal.MatchChunk) {
trace.invalidate(chunk.match)
allInvalidatedIds.add(chunk.match.rule().uniqueTag())
allInvalidatedIds.add(chunk.ruleUniqueTag)
// Seems, it's not strictly necessary, because some of its head occurrences are anyway invalidated forever
// and storing this invalid consumed match can make no harm, except some memory overhead.
@ -184,17 +189,19 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
}
}
fun launchQueue(controller: Controller): FeedbackStatus =
execQueue.run(controller, this)
fun launchQueue(controller: Controller): Pair<FeedbackStatus, Set<Any>> =
execQueue.run(controller, this) to rewrittenRuleMatches
/**
* Clears state unneeded between incremental sessions
* and returns [SessionToken] with session results.
*/
fun endSession(): SessionToken {
rewrittenRuleMatches.clear()
val histView = view()
resetStore() // clear observers
val rules = ArrayList<Rule>().apply { ruleIndex.forEach { add(it) } }
// preserve only relevant and non-empty RuleMatchers
val principalState = dispatchingFront.state().filterValues { ruleMatcher ->
ispec.isPrincipal(ruleMatcher.rule()) || ruleMatcher.probe().hasOccurrences()
}
@ -241,7 +248,7 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
if (activationChunk != null && !isFront()) {
val discards = match.matchHeadReplaced().contains(active)
if (discards) {
dropDiscardingMatchesFor(activationChunk)
dropDiscardingMatchesFor(activationChunk, rewrittenRuleMatches)
}
}
@ -261,10 +268,15 @@ internal class ConstraintsProcessing(private var dispatchingFront: Dispatcher.Di
return outStatus
}
private fun dropDiscardingMatchesFor(ancestor: MatchJournal.OccChunk) =
private fun dropDiscardingMatchesFor(ancestor: MatchJournal.OccChunk, droppedRuleTags: MutableSet<Any>) =
this.dropDescendantsWhile(ancestor) { chunk ->
chunk is MatchJournal.MatchChunk
&& chunk.match.matchHeadReplaced().contains(ancestor.occ)
if (chunk is MatchJournal.MatchChunk
&& chunk.match.matchHeadReplaced().contains(ancestor.occ))
{
droppedRuleTags.add(chunk.ruleUniqueTag)
true
} else false
}
private inline fun FeedbackStatus.then(action: (FeedbackStatus) -> FeedbackStatus) : FeedbackStatus =

View File

@ -55,18 +55,22 @@ internal class ControllerImpl (
}
fun incrLaunch(constraint: Constraint, rulesDiff: RulesDiff): Pair<FeedbackStatus, Set<Any>> {
val invalidatedRuleTags =
profiler.profile<Set<Any>>("invalidation") {
processing.invalidateRuleMatches(rulesDiff.removed)
}
profiler.profile("adding_matches") {
processing.addRuleMatches(rulesDiff.added)
}
val status =
profiler.profile<FeedbackStatus>("reexecution") {
val (status, rewrittenRuleTags) =
profiler.profile<Pair<FeedbackStatus, Set<Any>>>("reexecution") {
processing.launchQueue(this)
}
return status to invalidatedRuleTags
return status to invalidatedRuleTags.union(rewrittenRuleTags)
}
fun activate(constraint: Constraint) : FeedbackStatus {

View File

@ -178,6 +178,8 @@ interface MatchJournal : MutableIterable<MatchJournal.Chunk> {
override fun entriesLog(): List<Chunk.Entry> = entries
override fun toString() = "(id=$id, $justifications, ${match.rule().tag()}, $entries)"
val ruleUniqueTag: Any get() = match.rule().uniqueTag()
}
class OccChunk(override val id: Int, val occ: Occurrence) : Chunk {