org.jactr.core.chunk.four.DefaultSubsymbolicChunk4.java Source code

Java tutorial

Introduction

Here is the source code for org.jactr.core.chunk.four.DefaultSubsymbolicChunk4.java

Source

/*
 * Created on Oct 25, 2006 Copyright (C) 2001-6, Anthony Harrison anh23@pitt.edu
 * (jactr.org) 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.chunk.four;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

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.basic.AbstractSubsymbolicChunk;
import org.jactr.core.event.ParameterEvent;
import org.jactr.core.module.declarative.IDeclarativeModule;
import org.jactr.core.module.declarative.four.IDeclarativeModule4;
import org.jactr.core.runtime.ACTRRuntime;
import org.jactr.core.utils.parameter.ACTRParameterHandler;
import org.jactr.core.utils.parameter.CollectionParameterHandler;
import org.jactr.core.utils.parameter.LinkParameterHandler;
import org.jactr.core.utils.parameter.ParameterHandler;

public class DefaultSubsymbolicChunk4 extends AbstractSubsymbolicChunk implements ISubsymbolicChunk4 {
    /**
     * logger definition
     */
    static private final Log LOGGER = LogFactory.getLog(DefaultSubsymbolicChunk4.class);

    protected long _creationCycle;

    protected Map<IChunk, Link> _jAssociations; // keyed

    // on
    // jChunk

    protected Map<IChunk, Link> _iAssociations; // keyed

    // on
    // iChunk

    public DefaultSubsymbolicChunk4(IChunk parent) {
        super(parent);
        _jAssociations = new HashMap<IChunk, Link>();
        _iAssociations = new HashMap<IChunk, Link>();
    }

    @Override
    public void encode(double when) {
        if (!_parentChunk.isEncoded())
            try {
                writeLock().lock();
                IDeclarativeModule decMod = _parentChunk.getModel().getDeclarativeModule();
                if (!(decMod instanceof IDeclarativeModule4)) {
                    if (LOGGER.isWarnEnabled())
                        LOGGER.warn("IDeclarativeModule4 required to get base level constant");
                } else
                    setBaseLevelActivation(((IDeclarativeModule4) decMod).getBaseLevelConstant());

                setCreationCycle(_parentChunk.getModel().getCycle());

                /*
                 * add a link to ourselves
                 */
                addLink(new Link(_parentChunk, _parentChunk));
            } finally {
                writeLock().unlock();
            }

        super.encode(when);
    }

    @Override
    public void dispose() {
        super.dispose();

        try {
            writeLock().lock();
            /*
             * remove our associations. Why do we bother? a chunk can be disposed
             * during the normal life cycle of a model. For example, if a visual
             * object were stashed in the visual-location.objects slot, the
             * visual-location will have a link to the visual object. When the visual
             * object is disposed of because it cannot be seen, but was never actually
             * encoded, we need to remove the associative links
             */
            for (Link l : _jAssociations.values())
                if (!l.getJChunk().hasBeenDisposed()) {
                    ((ISubsymbolicChunk4) l.getJChunk().getSubsymbolicChunk()).removeLink(l);
                }

            for (Link l : _iAssociations.values())
                if (!l.getIChunk().hasBeenDisposed()) {
                    ((ISubsymbolicChunk4) l.getIChunk().getSubsymbolicChunk()).removeLink(l);
                }

            _jAssociations.clear();
            _iAssociations.clear();
        } finally {
            writeLock().unlock();
        }
    }

    public void setCreationCycle(long cycle) {
        long old = 0;
        try {
            writeLock().lock();
            old = _creationCycle;
            _creationCycle = cycle;
        } finally {
            writeLock().unlock();
        }

        if (_parentChunk.hasParameterListeners())
            _parentChunk.dispatch(
                    new ParameterEvent(this, ACTRRuntime.getRuntime().getClock(_parentChunk.getModel()).getTime(),
                            CREATION_CYCLE, old, cycle));
    }

    public long getCreationCycle() {
        try {
            readLock().lock();
            return _creationCycle;
        } finally {
            readLock().unlock();
        }
    }

    @Override
    protected double computeSpreadingActivation() {
        double spread = 0.0;

        for (Link jLink : getJAssociations(null)) {
            ISubsymbolicChunk sc = jLink.getJChunk().getSubsymbolicChunk();
            spread += sc.getSourceActivation() * jLink.getStrength();
            if (LOGGER.isDebugEnabled())
                LOGGER.debug(_parentChunk + " Pulling " + spread + " from " + jLink);
        }

        if (LOGGER.isDebugEnabled())
            LOGGER.debug("SpreadingActivation " + spread);
        if (Double.isNaN(spread) || Double.isInfinite(spread))
            spread = 0;

        return spread;
    }

    public void addLink(Link l) {
        try {
            writeLock().lock();
            Link currentLink = null;
            IChunk iChunk = l.getIChunk();
            IChunk jChunk = l.getJChunk();
            if (jChunk.equals(_parentChunk)) {
                currentLink = getIAssociation(iChunk);
                if (currentLink == null)
                    _iAssociations.put(iChunk, l);
                else if (LOGGER.isDebugEnabled())
                    LOGGER.debug("Already have a link " + l + ", use increment instead ", new RuntimeException());
            }

            if (iChunk.equals(_parentChunk)) {
                currentLink = getJAssociation(jChunk);
                if (currentLink == null)
                    _jAssociations.put(jChunk, l);
                else if (LOGGER.isDebugEnabled())
                    LOGGER.debug("Already have a link " + l + ", use increment instead", new RuntimeException());
            }
        } finally {
            writeLock().unlock();
        }

        // if (_parentChunk.hasParameterListeners() && old != null)
        // _parentChunk.dispatch(new ParameterEvent(this, ACTRRuntime.getRuntime()
        // .getClock(_parentChunk.getModel()).getTime(), LINKS, old,
        // getIAssociations()));
    }

    public Link getIAssociation(IChunk iChunk) {
        try {
            readLock().lock();
            return _iAssociations.get(iChunk);
        } finally {
            readLock().unlock();
        }
    }

    public Collection<Link> getIAssociations(Collection<Link> container) {
        if (container == null)
            container = new ArrayList<Link>();
        try {
            readLock().lock();
            container.addAll(_iAssociations.values());
            return container;
        } finally {
            readLock().unlock();
        }
    }

    public Link getJAssociation(IChunk jChunk) {
        try {
            readLock().lock();
            return _jAssociations.get(jChunk);
        } finally {
            readLock().unlock();
        }
    }

    public Collection<Link> getJAssociations(Collection<Link> container) {
        if (container == null)
            container = new ArrayList<Link>();
        try {
            readLock().lock();
            container.addAll(_jAssociations.values());
            return container;
        } finally {
            readLock().unlock();
        }
    }

    public int getNumberOfIAssociations() {
        try {
            readLock().lock();
            return _iAssociations.size();
        } finally {
            readLock().unlock();
        }
    }

    public int getNumberOfJAssociations() {
        try {
            readLock().lock();
            return _jAssociations.size();
        } finally {
            readLock().unlock();
        }

    }

    public void removeLink(Link l) {
        // Collection<Link> old = getIAssociations();
        try {
            writeLock().lock();
            Link currentLink = null;
            if (_parentChunk.equals(l.getIChunk())) {
                currentLink = getJAssociation(l.getJChunk());
                if (currentLink != null) {
                    currentLink.decrement();
                    if (currentLink.getCount() <= 0)
                        _jAssociations.remove(l.getJChunk());
                }
            }

            if (_parentChunk.equals(l.getJChunk())) {
                currentLink = getIAssociation(l.getIChunk());
                if (currentLink != null) {
                    currentLink.decrement();
                    if (currentLink.getCount() <= 0)
                        _iAssociations.remove(l.getIChunk());
                }
            }
        } finally {
            writeLock().unlock();
        }

        // if (_parentChunk.hasParameterListeners())
        // _parentChunk.dispatch(new ParameterEvent(this, ACTRRuntime.getRuntime()
        // .getClock(_parentChunk.getModel()).getTime(), LINKS, old,
        // getIAssociations()));
    }

    @Override
    public Collection<String> getPossibleParameters() {
        Collection<String> str = super.getPossibleParameters();
        str.add(LINKS);
        str.add(CREATION_CYCLE);
        return str;
    }

    @Override
    public String getParameter(String key) {
        String rtn = null;
        if (LINKS.equalsIgnoreCase(key)) {
            Collection<Link> associations = getIAssociations(null); // everyone we
            // spread
            // to
            ACTRParameterHandler actrph = new ACTRParameterHandler(getParentChunk().getModel());
            LinkParameterHandler lph = new LinkParameterHandler(getParentChunk(), actrph);
            CollectionParameterHandler<Link> aph = new CollectionParameterHandler<Link>(lph);
            rtn = aph.toString(associations);
        } else if (CREATION_CYCLE.equalsIgnoreCase(key))
            rtn = ParameterHandler.numberInstance().toString(getCreationCycle());
        else
            rtn = super.getParameter(key);

        return rtn;
    }

    @Override
    public void setParameter(String key, String value) {
        if (CREATION_CYCLE.equalsIgnoreCase(key))
            setCreationCycle(ParameterHandler.numberInstance().coerce(value).longValue());
        else if (LINKS.equalsIgnoreCase(key)) {
            ACTRParameterHandler actrph = new ACTRParameterHandler(getParentChunk().getModel());
            LinkParameterHandler lph = new LinkParameterHandler(getParentChunk(), actrph);
            CollectionParameterHandler<Link> aph = new CollectionParameterHandler<Link>(lph);
            for (Link l : aph.coerce(value)) {
                if (LOGGER.isDebugEnabled())
                    LOGGER.debug("adding link " + l);

                Link oldLink = getIAssociation(l.getIChunk());
                if (oldLink != null) {
                    oldLink.setCount(Math.max(oldLink.getCount(), l.getCount()));
                    oldLink.setStrength(Math.max(oldLink.getStrength(), l.getStrength()));
                } else {
                    addLink(l);
                    /*
                     * we also have to add it to the iChunk
                     */
                    ((ISubsymbolicChunk4) l.getIChunk().getSubsymbolicChunk()).addLink(l);
                }
            }
        }

        super.setParameter(key, value);
    }
}