package org.jactr.core.module.declarative.search.filter;
/*
* default logging
*/
import javolution.text.TextBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.chunk.ISubsymbolicChunk;
import org.jactr.core.chunk.five.ISubsymbolicChunk5;
import org.jactr.core.production.VariableBindings;
import org.jactr.core.production.request.ChunkTypeRequest;
/**
* Basic filter that removes candidates based on their activation values, and
* can log the information back to the runtime logs. This filter is not sharable
* (internal state info) nor thread safe.
*
* @author harrison
*/
public class PartialMatchActivationFilter implements ILoggedChunkFilter
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(PartialMatchActivationFilter.class);
private final double _activationThreshold;
private final ChunkTypeRequest _request;
private final boolean _log;
private double _highestActivationYet = Double.NEGATIVE_INFINITY;
private IChunk _bestChunkYet = null;
private TextBuilder _message;
private ActivationPolicy _activationPolicy;
public PartialMatchActivationFilter(ActivationPolicy policy,
ChunkTypeRequest request, double threshold, boolean logEvaluations)
{
_activationPolicy = policy;
_request = request;
_activationThreshold = threshold;
_log = logEvaluations;
if (_log) _message = new TextBuilder();
}
public PartialMatchActivationFilter(ChunkTypeRequest request, double threshold)
{
this(ActivationPolicy.SUMMATION, request, threshold, false);
}
public boolean accept(IChunk chunk)
{
int matches = _request.countMatches(chunk, new VariableBindings());
if (matches < 1)
{
if (_message != null)
_message.append(String.format(
"rejecting %s, there is no overlap with retrieval pattern %s\n",
chunk, _request));
return false;
}
ISubsymbolicChunk ssc = chunk.getSubsymbolicChunk();
double referenceActivation = _activationPolicy.getActivation(chunk);
double totalActivation = ssc.getActivation();
double discountedActivation = totalActivation;
double base = ssc.getBaseLevelActivation();
double spread = ssc.getSpreadingActivation();
ISubsymbolicChunk5 ssc5 = ssc.getAdapter(ISubsymbolicChunk5.class);
if (ssc5 != null) discountedActivation = ssc5.getActivation(_request);
double discount = totalActivation - discountedActivation;
// now with the discount, we can correctly due the referenceAc
referenceActivation -= discount;
boolean acceptChunk = referenceActivation >= _activationThreshold;
boolean newBest = false;
if (referenceActivation > _highestActivationYet)
{
_bestChunkYet = chunk;
_highestActivationYet = referenceActivation;
newBest = true;
}
if (_message != null)
{
String msg = null;
if (newBest)
msg = String.format(
"%s is best candidate yet (%.2f=%.2f+%.2f [%.2f discount])\n",
_bestChunkYet, discountedActivation, base, spread, discount);
else
msg = String
.format(
"%s doesn't have the highest activation (%.2f=%.2f+%.2f [%.2f discount])\n",
chunk, discountedActivation, base, spread, discount);
synchronized (_message)
{
_message.append(msg);
}
}
return acceptChunk;
}
public TextBuilder getMessageBuilder()
{
return _message;
}
}