package org.jactr.core.chunk.four; /* * default logging */ import javolution.util.FastList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.chunk.IChunk; import org.jactr.core.chunk.link.IAssociativeLink; import org.jactr.core.chunk.link.IAssociativeLinkEquation; import org.jactr.core.model.IModel; import org.jactr.core.module.declarative.associative.IAssociativeLinkContainer; import org.jactr.core.module.declarative.four.learning.IDeclarativeLearningModule4; /** * uses the ACT-R 4 equations for the learning and setting of associative link * strengths and priors * * @author harrison */ public class AssociativeLinkEquation4 implements IAssociativeLinkEquation { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(AssociativeLinkEquation4.class); final private IDeclarativeLearningModule4 _declarativeLearningModule; public AssociativeLinkEquation4(IDeclarativeLearningModule4 decLM) { _declarativeLearningModule = decLM; } public double computeLearnedStrength(IAssociativeLink link) { Link4 link4 = (Link4) link; IChunk iChunk = link4.getIChunk(); IChunk jChunk = link4.getJChunk(); if (iChunk.equals(jChunk)) return 1; IModel m = iChunk.getModel(); if (!_declarativeLearningModule.isAssociativeLearningEnabled()) return link4.getStrength(); ISubsymbolicChunk4 j = jChunk.getAdapter(ISubsymbolicChunk4.class); ISubsymbolicChunk4 i = iChunk.getAdapter(ISubsymbolicChunk4.class); double numerator = _declarativeLearningModule.getAssociativeLearning() * link4.getRStrength(); double denom = _declarativeLearningModule.getAssociativeLearning() * j.getTimesInContext(); double fcEji = 1.0; if (i.getTimesNeeded() == 0) fcEji = j.getTimesInContext(); else fcEji = link4.getFNICJ() * (m.getCycle() - i.getCreationCycle()) / i.getTimesNeeded(); numerator += fcEji; if (LOGGER.isDebugEnabled()) LOGGER.debug("numerator : " + numerator + " denom : " + denom + " fcEji : " + fcEji); double rStrength = numerator / denom; link4.setRStrength(rStrength); return Math.log(numerator / denom); } public double computeDefaultStrength(IAssociativeLink link) { Link4 link4 = (Link4) link; IChunk iChunk = link4.getIChunk(); IChunk jChunk = link4.getJChunk(); /** * if a strength already exists (i.e., is not 0), and learning is off, we * assume that the strength of this link was modeler specified, so we leave * it alone. <br/> */ if (!_declarativeLearningModule.isAssociativeLearningEnabled() && Math.abs(0 - link4.getStrength()) > 0.0001) return link4.getStrength(); if (iChunk.equals(jChunk)) return 1; int totalChunksInMemory = (int) jChunk.getModel().getDeclarativeModule() .getNumberOfChunks(); int fan = 0; IAssociativeLinkContainer alc = jChunk .getAdapter(IAssociativeLinkContainer.class); ISubsymbolicChunk4 ssc4 = jChunk.getSubsymbolicChunk().getAdapter( ISubsymbolicChunk4.class); if (ssc4 != null) fan = (int) alc.getNumberOfOutboundLinks(); double dRji = 0; if (fan > 0) dRji = (double) totalChunksInMemory / (double) fan; else if (fan == 0) dRji = 1.0; /* * number of duplicate references, scales the default r accordingly */ if (link4.getCount() > 0) dRji *= link4.getCount(); if (LOGGER.isDebugEnabled()) LOGGER.debug(this + " defaultRji : " + dRji + "(" + Math.log(dRji) + ") fan : " + fan + " count : " + link4.getCount() + " totalFacts : " + totalChunksInMemory); link4.setRStrength(dRji); return Math.log(dRji); } public void resetStrengths(IModel model) { try { FastList<IAssociativeLink> links = FastList.newInstance(); for (IChunk chunk : model.getDeclarativeModule().getChunks().get()) { IAssociativeLinkContainer alc = chunk .getAdapter(IAssociativeLinkContainer.class); links.clear(); alc.getOutboundLinks(links); for (IAssociativeLink link : links) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Reseting strength of " + link); ((Link4) link).setStrength(computeDefaultStrength(link)); } } } catch (Exception e) { LOGGER.error("Could not reset links because of an exception ", e); } } }