// 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"
#include "CombinadicIterator.H"
using namespace std;
void CoveringArray::SubRow::updateTracking(const Arrayvalues) {
assert(values.getSize() == columns.getSize());
const Options&options = owner.coverage.getOptions();
unsigned strength = owner.coverage.getStrength();
unsigned limit = options.getSize();
unsigned changes = 0;
ArrayoldRow(limit);
ArraynewRow(limit);
ArraychangedColumns(columns.getSize());
for (unsigned i = limit; i--;) {
oldRow[i] = owner(row, i);
}
for (unsigned i = limit, j = values.getSize(); i--;) {
if (j && (columns[j - 1] == i)) {
newRow[i] = values[--j];
} else {
newRow[i] = oldRow[i];
}
}
for (unsigned i = 0; i < limit; ++i) {
if (newRow[i] != oldRow[i]) {
changedColumns[changes++] = i;
}
}
changedColumns = Array(changedColumns, changes);
Arrayfirsts = options.getFirstSymbols();
Arraycounts = options.getSymbolCounts();
for (CombinadicIterator combo(limit, strength, changedColumns);
combo;
++combo) {
const ArrayupdateColumns = *combo;
ArrayoldSymbols(strength);
ArraynewSymbols(strength);
for (unsigned j = strength; j--;) {
unsigned column = updateColumns[j];
oldSymbols[j] = oldRow[column];
newSymbols[j] = newRow[column];
}
Coverage::Entry lost =
owner.coverage.hintGet(updateColumns, firsts, counts, oldSymbols);
assert(lost); // Assert that what we lost is something we had to lose.
if (--lost == 0) {
--owner.coverageCount;
if (owner.trackingNoncoverage) {
ArrayseparateCopyOfSymbols(oldSymbols.getSize());
for (unsigned j = oldSymbols.getSize(); j--;) {
separateCopyOfSymbols[j] = oldSymbols[j];
}
bool successfulInsertion =
owner.noncoverage->insert(separateCopyOfSymbols).second;
assert(successfulInsertion);
(void)successfulInsertion; // This is unused without assertions.
}
} else {
--owner.multipleCoverageCount;
}
Coverage::Entry gained =
owner.coverage.hintGet(updateColumns, firsts, counts, newSymbols);
if (++gained == 1) {
++owner.coverageCount;
if (owner.trackingNoncoverage) {
ArrayseparateCopyOfSymbols(newSymbols.getSize());
for (unsigned j = newSymbols.getSize(); j--;) {
separateCopyOfSymbols[j] = newSymbols[j];
}
bool successfulErasure =
(bool)owner.noncoverage->erase(separateCopyOfSymbols);
assert(successfulErasure);
(void)successfulErasure; // This is unused without assertions.
}
} else {
++owner.multipleCoverageCount;
}
}
owner.autoFinalizeSubstitutions();
}
CoveringArray::SubRow::operator Array() const {
typedef map, unsigned>::const_iterator Substitution;
Substitution end = owner.substitutions->end();
unsigned size = columns.getSize();
Arrayresult(size);
pairkey(row,0);
for (unsigned i = size; i--;) {
key.second = columns[i];
Substitution substitution = owner.substitutions->find(key);
result[i] =
(substitution == end) ?
owner.array[row][key.second] :
substitution->second;
}
return result;
}
CoveringArray::SubRow&CoveringArray::SubRow::operator =
(const Arrayvalues) {
assert(values.getSize() == columns.getSize());
if (owner.trackingCoverage) {
updateTracking(values);
}
pairkey(row, 0);
for (unsigned i = columns.getSize(); i--;) {
key.second = columns[i];
(*owner.substitutions)[key] = values[i];
}
return *this;
}