// A = compressor type (e.g. s), Data = data type
persistable sclass CompressionSearch_AnyType extends Probabilistic {
replace Regime with CompressionRegime_AnyType.
// user-set
settable Regime regime;
gettable Data inputData;
settable long inputSize; // in bytes
event onNewBest;
event onDisqualified(Submission s);
// public output variables
new Best best;
new L strategies;
*() { init(); }
*(Regime *regime) { init(); }
*(Regime *regime, Data *inputData, long *inputSize) { init(); }
void init {
best.onChange = r newBest;
}
// can submit concurrently!
Submission submit(A compression, O notes default null) {
ret _submit(compression, notes);
}
// private (although Submission is returned)
class Submission {
settable O notes;
toString {
if (!correct()) ret linesLL("BAD");
ret linesLL(
(isHardChecked() ? " HARD " : "MAYBE ") + ifloor(score()*100),
"Exact compression ratio: " + scoreRatio(),
"Code:",
indentx(shorten(500, str(decompressor()))),
"Code as bytes:",
indentx(shorten(500, bytesToHex(compressed())))
);
}
void setDecompressor(A decompressor) {
this.decompressor_cache = decompressor;
}
Data inputData() { ret inputData; }
simplyCached byte[] compressed() {
ret decompressor_cache == null ?: regime.decompressorToBytes(decompressor_cache);
}
simplyCached A decompressor() {
ret compressed_cache == null ?: regime.decompressorFromBytes(compressed_cache);
}
simplyCached S decompressor_str() {
ret strOrNull(decompressor());
}
int compressedSize aka nBytes() { ret l(compressed()); }
simplyCached Ratio scoreRatio() {
ret Ratio(inputSize(), compressedSize());
}
simplyCached double score() {
ret scoreRatio()!;
}
bool decompressed;
O decompressedValue;
O decompressed() {
if (!decompressed) {
decompressedValue = regime.runDecompressor(decompressor());
set decompressed;
}
ret decompressedValue;
}
bool checkUnder(Regime regime) {
ret checkResult(regime.runDecompressor(decompressor()));
}
simplyCached bool isHardChecked() {
if (!correct()) false;
var nextRegime = regime.harderRegime();
if (nextRegime == null) true;
ret checkUnder(nextRegime);
}
bool checkResult(O decompressed) {
ret eq(toByteList(decompressed), inputData());
}
simplyCached Bool correct() {
ret eq(toByteList(decompressed()), inputData());
}
} // end of Submission
Submission _submit(A compression, O notes) {
if (compression == null) null;
print("Received submission");
print("Code: " + takeFirst(500, str(compression)));
new Submission s;
s.notes(notes);
print("Notes: " + takeFirst(500, str(notes)));
s.setDecompressor(compression);
print("Size: " + nBytes(s.nBytes()));
if (s.score() > best.score())
if (!s.correct()) {
warn("Compressor didn't verify");
disqualified(s);
} else {
print("Score: " + s.score());
best.put(s, s.score();
}
ret s;
}
Submission bestSubmission() {
methodForEach flush(strategies);
ret best!;
}
Submission bestHardSubmission() {
var s = best!;
if (s == null || !s.isHardChecked()) null;
ret s;
}
A bestCompression aka get() {
var s = bestSubmission();
ret s?.decompressor();
}
bool has() { ret bestSubmission() != null; }
void addStrategy(AbstractCompressor_AnyType compressor) {
if (compressor == null) ret;
initAction(compressor);
compressor.setSearch(this);
strategies.add(compressor);
compressor.run();
}
run {}
}