// Copyright 2008, 2009 Brady J. Garvin // This file is part of Covering Arrays by Simulated Annealing (CASA). // CASA is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // CASA 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 General Public License for more details. // You should have received a copy of the GNU General Public License // along with CASA. If not, see . #include "covering/state/CoveringArray.H" using namespace std; #ifndef MAXIMUM_COVERING_ARRAY_SUBSTITUTION #define MAXIMUM_COVERING_ARRAY_SUBSTITUTION 0x40 #endif CoveringArray::CoveringArray (unsigned rows, unsigned strength, Options options, SATSolver&solver) : array(rows), substitutions(new map, unsigned>()), solver(&solver), trackingCoverage(false), trackingNoncoverage(false), coverageCount(0), multipleCoverageCount(0), coverage(strength, options), noncoverage(new set, ArrayComparator >()) { for (unsigned i = rows; i--;) { array[i] = Array(options.getSize()); } coverage.fill(0); } CoveringArray::CoveringArray(const CoveringArray©) : array(copy.array), substitutions(copy.substitutions), solver(copy.solver), trackingCoverage(copy.trackingCoverage), trackingNoncoverage(copy.trackingNoncoverage), coverageCount(copy.coverageCount), multipleCoverageCount(copy.multipleCoverageCount), coverage(copy.coverage), noncoverage(copy.noncoverage) { assert(array); } void CoveringArray::setBackingArrayEntry (unsigned row, unsigned option, unsigned value) { assert(!substitutions->size()); array[row][option] = value; } void CoveringArray::setBackingArrayRow(unsigned row, Arrayvalue) { assert(!substitutions->size()); array[row] = value; } unsigned CoveringArray::getCoverageCount() const { return coverageCount; } unsigned CoveringArray::getMultipleCoverageCount() const { return multipleCoverageCount; } ArrayCoveringArray::countDistinctCoverage() const { assert(trackingCoverage); Arrayresult(array.getSize()); result.fill(0); unsigned strength = coverage.getStrength(); unsigned limit = coverage.getOptions().getSize(); Arrayfirsts = coverage.getOptions().getFirstSymbols(); Arraycounts = coverage.getOptions().getSymbolCounts(); unsigned hint = 0; for (Array columns = combinadic.begin(strength), symbols(strength); columns[strength - 1](const CoveringArray&other) const { return this > &other; } bool CoveringArray::operator ==(const CoveringArray&other) const { return this == &other; } bool CoveringArray::operator !=(const CoveringArray&other) const { return this != &other; } void CoveringArray::finalizeSubstitutions() { unsigned outer = getRows(); unsigned inner = getOptions(); Array >replacement(outer); for (unsigned i = outer; i--;) { replacement[i] = Array(inner); for (unsigned j = inner; j--;) { replacement[i][j] = array[i][j]; } } for (map, unsigned>::const_iterator iterator = substitutions->begin(), end = substitutions->end(); iterator != end; ++iterator) { const pair&location = iterator->first; replacement[location.first][location.second] = iterator->second; } substitutions->clear(); array = replacement; } void CoveringArray::autoFinalizeSubstitutions() { if (substitutions->size() > MAXIMUM_COVERING_ARRAY_SUBSTITUTION) { finalizeSubstitutions(); } } bool CoveringArray::isTrackingCoverage() const { return trackingCoverage; } void CoveringArray::setTrackingCoverage(bool trackingCoverage) { if (this->trackingCoverage) { this->trackingCoverage = trackingCoverage; return; } this->trackingCoverage = trackingCoverage; if (trackingCoverage) { unsigned strength = coverage.getStrength(); unsigned limit = coverage.getOptions().getSize(); Arrayfirsts = coverage.getOptions().getFirstSymbols(); Arraycounts = coverage.getOptions().getSymbolCounts(); coverage.fill(0); coverageCount = 0; multipleCoverageCount = 0; if (substitutions->size()) { unsigned hint = 0; for (Array columns = combinadic.begin(strength), symbols(strength); columns[strength - 1] < limit; combinadic.next(columns), ++hint) { for (unsigned i = array.getSize();i--;) { for (unsigned j = strength;j--;) { symbols[j] = (*this)(i, columns[j]); } unsigned newCoverage = ++coverage.hintGet(hint, columns, firsts, counts, symbols); if (newCoverage == 1) { ++coverageCount; } if (newCoverage>1) { ++multipleCoverageCount; } } } } else { // A special common case where we can bypass the () operator: unsigned hint = 0; for (Array columns = combinadic.begin(strength), symbols(strength); columns[strength - 1] < limit; combinadic.next(columns), ++hint) { for (unsigned i = array.getSize(); i--;) { for (unsigned j = strength; j--;) { symbols[j] = array[i][columns[j]]; } unsigned newCoverage = ++coverage.hintGet(hint, columns, firsts, counts, symbols); if (newCoverage == 1) { ++coverageCount; } if (newCoverage>1) { ++multipleCoverageCount; } } } } } } bool CoveringArray::isTrackingNoncoverage() const { return trackingNoncoverage; } void CoveringArray::setTrackingNoncoverage(bool trackingNoncoverage) { if (this->trackingNoncoverage) { this->trackingNoncoverage = trackingNoncoverage; if (!trackingNoncoverage) { noncoverage->clear(); } return; } this->trackingNoncoverage = trackingNoncoverage; if (trackingNoncoverage) { assert(trackingCoverage); assert(noncoverage->empty()); #ifndef NDEBUG unsigned impossible = 0; #endif for (Coverage::iterator iterator = coverage.begin(), end = coverage.end(); iterator != end; ++iterator) { if (!*iterator) { InputKnown known; Arraycombination = iterator.getCombination(); for (unsigned i = combination.getSize(); i--;) { known.append(InputTerm(false, combination[i])); } if ((*solver)(known)) { noncoverage->insert(combination); } #ifndef NDEBUG else { ++impossible; } #endif } } assert(coverageCount + noncoverage->size() + impossible == coverage.getSize()); } } const set, ArrayComparator >& CoveringArray::getNoncoverage() const { return *noncoverage; } ostream&operator <<(ostream&out, const CoveringArray&array) { out << '{'; for (unsigned i = 0; i < array.getRows(); ++i) { out << '['; for (unsigned j = 0; j < array.getOptions(); ++j) { out << array(i,j) << ','; } out << "X],"; } out << "X} -> "; if (array.isTrackingCoverage()) { out << array.getCoverageCount(); }else{ out << '?'; } return out; }