/** * Copyright (C) 2001-3, Anthony Harrison anh23@pitt.edu This library is free * software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; * either version 2.1 of the License, or (at your option) any later version. * This library 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 Lesser General Public License for more * details. You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.jactr.core.module.declarative.four.learning; 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.model.IModel; import org.jactr.core.module.declarative.four.IDeclarativeModule4; import org.jactr.core.module.procedural.IProceduralModule; import org.jactr.core.module.random.IRandomModule; import org.jactr.core.module.random.six.DefaultRandomModule; import org.jactr.core.runtime.ACTRRuntime; import org.jactr.core.utils.references.IOptimizedReferences; import org.jactr.core.utils.references.IReferences; /** * default impl of the base level activation equation as defined in atomic * components of thought * * @author harrison * @created April 18, 2003 */ public class DefaultBaseLevelActivationEquation implements IBaseLevelActivationEquation { private static transient Log LOGGER = LogFactory .getLog(DefaultBaseLevelActivationEquation.class .getName()); IDeclarativeLearningModule4 _declarativeLearningModule; IProceduralModule _proceduralModule; IDeclarativeModule4 _declarativeModule; IRandomModule _randomModule; private IModel _model; public DefaultBaseLevelActivationEquation(IModel model) { _model = model; } private IProceduralModule getProceduralModule() { if (_proceduralModule == null) { _proceduralModule = _model.getProceduralModule(); if (_proceduralModule == null) throw new RuntimeException(this.getClass().getSimpleName() + " depends upon IProceduralModule"); } return _proceduralModule; } private IDeclarativeModule4 getDeclarativeModule() { if (_declarativeModule == null) { _declarativeModule = (IDeclarativeModule4) _model .getModule(IDeclarativeModule4.class); if (_declarativeModule == null) throw new RuntimeException(this.getClass().getSimpleName() + " depends upon IDeclarativeModule4"); } return _declarativeModule; } private IDeclarativeLearningModule4 getDeclarativeLearningModule() { if (_declarativeLearningModule == null) { _declarativeLearningModule = (IDeclarativeLearningModule4) _model .getModule(IDeclarativeLearningModule4.class); if (_declarativeLearningModule == null) throw new RuntimeException(this.getClass().getSimpleName() + " depends upon IDeclarativeLearningModule4"); } return _declarativeLearningModule; } private IRandomModule getRandomModule() { if (_randomModule == null) { _randomModule = (IRandomModule) _model.getModule(IRandomModule.class); if (_randomModule == null) _randomModule = DefaultRandomModule.getInstance(); } return _randomModule; } /** * Description of the Method * * @param model * Description of the Parameter * @param c * Description of the Parameter * @return Description of the Return Value */ public double computeBaseLevelActivation(IModel model, IChunk c) { IDeclarativeModule4 declarativeModule = getDeclarativeModule(); IDeclarativeLearningModule4 declarativeLearningModule = getDeclarativeLearningModule(); ISubsymbolicChunk ssc = c.getSubsymbolicChunk(); double baseLevelActivation = 0; double noiseActivation = 0; if (LOGGER.isDebugEnabled()) LOGGER.debug("Computing activation for " + c); if (declarativeLearningModule.isBaseLevelLearningEnabled()) { if (LOGGER.isDebugEnabled()) LOGGER.debug("base level learning is enabled, calculating"); double now = ACTRRuntime.getRuntime().getClock(model).getTime(); // compute base level activation double minusD = -1.0 * declarativeLearningModule.getBaseLevelLearning(); double defAct = getProceduralModule().getDefaultProductionFiringTime(); double base = 0.0; if (LOGGER.isDebugEnabled()) LOGGER.debug("defAct=" + defAct + " minusD=" + minusD); IReferences referenceList = ssc.getReferences(); int optimization = 0; if (referenceList instanceof IOptimizedReferences) optimization = ((IOptimizedReferences) referenceList) .getOptimizationLevel(); // exact portion double[] times = referenceList.getRelativeTimes(now); if (LOGGER.isDebugEnabled()) LOGGER .debug("Snagged " + times.length + " delta access times for " + c); if (optimization != 0) { for (double element : times) { double tMinusD = Math.pow(Math.max(defAct, element), minusD); base += tMinusD; if (LOGGER.isDebugEnabled()) LOGGER.debug("tMinusD for " + element + " = " + tMinusD + " base = " + base); } if (times.length == 0) base = Math.pow(defAct, minusD); } baseLevelActivation = base; if (LOGGER.isDebugEnabled()) LOGGER.debug("NoOpt-BaseLevelActivation " + baseLevelActivation + " with " + times.length + " accesses"); /* * optimized is : 1-d 1-d (n-m)(t0 - tn-m ) ---------------------- * (1-d)(t0 - tn-m) where m is the optimization level (# of reference * times stored) n is the number of references total t0 is the creation * time tn-m is the largest time differential in the references stored */ long nMinusM = referenceList.getNumberOfReferences() - times.length; double defActT0 = Math.max(defAct, (now - ssc.getCreationTime())); double defActTnm = Math.max(defAct, (times.length == 0 ? 0 : times[times.length - 1])); // t0 - tn-m to the 1-d double numerator = 0; double denom = 0; // it's zero.. if (optimization == 0) { numerator = Math.pow(defActT0, minusD); denom = 1; } else { numerator = Math.pow(defActT0, 1 + minusD) - Math.pow(defActTnm, 1 + minusD); denom = Math.max(defAct, defActT0 - defActTnm); } base = nMinusM * numerator / ((1 + minusD) * denom); if (LOGGER.isDebugEnabled()) { LOGGER.debug(nMinusM + "," + numerator + "," + denom + "," + times.length); LOGGER.debug("defActT0 = " + defActT0 + " defActTnm = " + defActTnm); LOGGER.debug("referenceCount = " + referenceList.getNumberOfReferences() + " Optimization = " + optimization + " times=" + times.length); LOGGER.debug("Opt-BaseLevelActivation " + base); } if (!Double.isNaN(base) && !Double.isInfinite(base)) baseLevelActivation += base; baseLevelActivation = Math.log(baseLevelActivation); baseLevelActivation += declarativeModule.getBaseLevelConstant(); if (LOGGER.isDebugEnabled()) LOGGER.debug("Adding constant " + _declarativeModule.getBaseLevelConstant() + " BaseLevelActivation " + baseLevelActivation); } else { baseLevelActivation = ssc.getBaseLevelActivation(); if (LOGGER.isDebugEnabled()) LOGGER.debug("forcing baselevel activation to " + baseLevelActivation); } IRandomModule randomModule = getRandomModule(); if (randomModule != null) noiseActivation = randomModule.logisticNoise(declarativeModule .getActivationNoise()); // System.err.println("IModel time is now "+now); if (LOGGER.isDebugEnabled()) LOGGER.debug(c + ".BaseLevelActivation = " + baseLevelActivation); return baseLevelActivation + noiseActivation; } }