// 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
#include "utility/igreater.H"
#include "covering/space/GraftSpace.H"
using namespace std;
#ifndef MAXIMUM_SUBROW_CHANGE_FAILED_ATTEMPTS
#define MAXIMUM_SUBROW_CHANGE_FAILED_ATTEMPTS 32
#endif
ArrayGraftSpace::createRandomMatchingRow(InputKnown&known) const {
Arrayresult(options.getSize());
for (unsigned i = options.getSize(); i--;) {
vectorcandidates;
for (unsigned
j = options.getSymbolCount(i),
base = options.getFirstSymbol(i);
j--;) {
candidates.push_back(base + j);
}
unsigned index = rand() % candidates.size();
unsigned symbol = candidates[index];
known.append(InputTerm(false, symbol));
while (!solver(known)) {
known.undoAppend();
candidates[index] = candidates[candidates.size() - 1];
candidates.pop_back();
index = rand() % candidates.size();
symbol = candidates[index];
known.append(InputTerm(false, symbol));
}
result[i] = symbol;
}
return result;
}
CoveringArray GraftSpace::createStartState(unsigned rows) const {
CoveringArray result(rows, strength, options, solver);
unsigned i = rows;
while (i-->resurrectionBuffer.size()) {
InputKnown known;
result.setBackingArrayRow(i, createRandomMatchingRow(known));
}
if (resurrectionBuffer.size()) {
for (++i;i--;) {
Arrayrow = resurrectionBuffer[i];
// We must deep copy to preserve the resurrection buffer.
for (unsigned j = options.getSize(); j--;) {
result.setBackingArrayEntry(i, j, row[j]);
}
}
}
result.setTrackingCoverage(true);
result.setTrackingNoncoverage(true);
return result;
}
CoverageCost GraftSpace::getTraveled(const CoveringArray&start) const {
return 0;
}
CoverageCost GraftSpace::getTraveled
(const Node&parent,const CoveringArray&state)
const {
return 0;
}
setGraftSpace::getChildren
(const CoveringArray&state, float proportion) const {
assert(false); // Unimplemented.
return getChildren(state, (unsigned)1);
}
setGraftSpace::getChildren
(const CoveringArray&state, unsigned count) const {
setresult;
unsigned rows = state.getRows();
assert(options.getSize() == state.getOptions());
assert(state.isTrackingNoncoverage());
const set, ArrayComparator >&noncoverage =
state.getNoncoverage();
if (noncoverage.empty()){
return result;
}
unsigned attempts = 0;
for (unsigned i = count; i; ++attempts) {
unsigned row = rand() % rows;
set, ArrayComparator >::const_iterator
combinationIterator = noncoverage.begin();
unsigned combinationIndex = rand() % noncoverage.size();
while (combinationIndex--) {
++combinationIterator;
}
Arraycombination = *combinationIterator;
Arraycolumns(strength);
InputKnown known;
if (attempts < MAXIMUM_SUBROW_CHANGE_FAILED_ATTEMPTS) {
for (unsigned j = strength; j--;) {
columns[j] = options.getOption(combination[j]);
}
for (unsigned j = options.getSize(), k = strength; j--;) {
if (k && columns[k-1] == j) {
unsigned symbol = combination[--k];
known.append(InputTerm(false, symbol));
} else {
assert(!k || columns[k - 1] < j);
unsigned symbol = state(row, j);
known.append(InputTerm(false, symbol));
}
}
if (solver(known)) {
CoveringArray child = state;
child(row, columns) = combination;
result.insert(child);
--i;
attempts = 0;
}
} else {
cout << "Considering a full row change" << endl;
for (unsigned k = strength; k--;) {
known.append(InputTerm(false, combination[k]));
}
CoveringArray child = state;
child(row) = createRandomMatchingRow(known);
result.insert(child);
--i;
attempts = 0;
}
}
return result;
}
void GraftSpace::signal(const SearchFinish&finish) {
const set*>&best =
finish.source.getBest();
if (best.empty()) {
return;
}
const CoveringArray&solution = (*best.begin())->getState();
unsigned rowCount = solution.getRows();
unsigned optionCount = solution.getOptions();
resurrectionBuffer.reserve(rowCount);
while (resurrectionBuffer.size() < rowCount) {
resurrectionBuffer.push_back(Array());
}
cout << "Sorting rows for distinct coverage" << endl;
ArraydistinctCoverage = solution.countDistinctCoverage();
Arraypermutation(rowCount);
for (unsigned i = rowCount; i--;) {
permutation[i] = i;
}
igreaterbetterDistinctCoverage(distinctCoverage);
sort(permutation + 0, permutation + rowCount, betterDistinctCoverage);
cout << "Saving rows in resurrection buffer" << endl;
for (unsigned i = rowCount; i--;) {
unsigned p = permutation[i];
Arrayrow = Array(optionCount);
for (unsigned j = optionCount; j--;) {
row[j] = solution(p, j);
}
resurrectionBuffer[i] = row;
}
}
void GraftSpace::clearResurrectionBuffer() {
resurrectionBuffer.clear();
}