package solver const ( nbMaxRecent = 50 // How many recent LBD values we consider; "X" in papers about LBD. triggerRestartK = 0.8 nbMaxTrail = 5000 // How many elements in queueTrail we consider; "Y" in papers about LBD. postponeRestartT = 1.4 ) type queueData struct { totalNb int // Current total nb of values considered totalSum int // Sum of all values so far nbRecent int // NB of values used in the array ptr int // current index of oldest value in the array recentAvg float64 // Average value } // lbdStats is a structure dealing with recent LBD evolutions. type lbdStats struct { lbdData queueData trailData queueData recentVals [nbMaxRecent]int // Last LBD values recentTrails [nbMaxTrail]int // Last trail lengths } // mustRestart is true iff recent LBDs are much smaller on average than average of all LBDs. func (l *lbdStats) mustRestart() bool { if l.lbdData.nbRecent < nbMaxRecent { return false } return l.lbdData.recentAvg*triggerRestartK > float64(l.lbdData.totalSum)/float64(l.lbdData.totalNb) } // addConflict adds information about a conflict that just happened. func (l *lbdStats) addConflict(trailSz int) { td := &l.trailData td.totalNb++ td.totalSum += trailSz if td.nbRecent < nbMaxTrail { l.recentTrails[td.nbRecent] = trailSz old := float64(td.nbRecent) new := old + 1 td.recentAvg = (td.recentAvg*old)/new + float64(trailSz)/new td.nbRecent++ } else { old := l.recentTrails[td.ptr] l.recentTrails[td.ptr] = trailSz td.ptr++ if td.ptr == nbMaxTrail { td.ptr = 0 } td.recentAvg = td.recentAvg - float64(old)/nbMaxTrail + float64(trailSz)/nbMaxTrail } if td.nbRecent == nbMaxTrail && l.lbdData.nbRecent == nbMaxRecent && trailSz > int(postponeRestartT*td.recentAvg) { // Too many good assignments: postpone restart l.clear() } } // addLbd adds information about a recent learned clause's LBD. // TODO: this is very close to addConflicts's code, this should probably be rewritten/merged. func (l *lbdStats) addLbd(lbd int) { ld := &l.lbdData ld.totalNb++ ld.totalSum += lbd if ld.nbRecent < nbMaxRecent { l.recentVals[ld.nbRecent] = lbd old := float64(ld.nbRecent) new := old + 1 ld.recentAvg = (ld.recentAvg*old)/new + float64(lbd)/new ld.nbRecent++ } else { old := l.recentVals[ld.ptr] l.recentVals[ld.ptr] = lbd ld.ptr++ if ld.ptr == nbMaxRecent { ld.ptr = 0 } ld.recentAvg = ld.recentAvg - float64(old)/nbMaxRecent + float64(lbd)/nbMaxRecent } } // clear clears last values. It should be called after a restart. func (l *lbdStats) clear() { l.lbdData.ptr = 0 l.lbdData.nbRecent = 0 l.lbdData.recentAvg = 0.0 }