public int bind(IModel model, VariableBindings variableBindings, boolean isIterative) throws CannotMatchException { int unresolved = 0; IChunk resolvedChunk = (IChunk) variableBindings.get(getVariableName()); if (resolvedChunk == null && !isIterative) throw new CannotMatchException( new GeneralMatchFailure(this, String.format("%s is undefined", getVariableName()))); try { if (resolvedChunk == null) unresolved = getRequest().bind(model, variableBindings, isIterative) + 1; else unresolved = getRequest() .bind( model, resolvedChunk.getSymbolicChunk().getName(), resolvedChunk.getSymbolicChunk(), variableBindings, isIterative); } catch (CannotMatchException cme) { cme.getMismatch().setCondition(this); throw cme; } return unresolved; }
public double computeEncodingTime(IChunk visualChunk, IVisualModule module) { IChunk error = module.getModel().getDeclarativeModule().getErrorChunk(); if (error.equals(visualChunk)) return module.getModel().getProceduralModule().getDefaultProductionFiringTime(); return 0.085; }
@Override public void fillSlotValues( ChunkTypeRequest mutableRequest, IIdentifier identifier, IChunk encodedChunk, ChunkTypeRequest originalSearchRequest) { String[] kinds = _currentKindMap.get(identifier); if (kinds != null) for (String kind : kinds) try { // attempt to resolve it.. IChunkType chunkType = encodedChunk.getModel().getDeclarativeModule().getChunkType(kind).get(); Object kindValue = kind; if (chunkType != null) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Got chunktype " + chunkType + " for " + kind); kindValue = chunkType; } else if (LOGGER.isDebugEnabled()) LOGGER.debug("No chunktype matching " + kind + " could be found, using string value"); if (kindMatchesPattern(originalSearchRequest, kindValue)) { mutableRequest.addSlot(new BasicSlot(IAuralModule.KIND_SLOT, kindValue)); return; } } catch (Exception e) { throw new RuntimeException("Failed to get kind ", e); } }
@Override protected boolean removeSourceChunkInternal(IChunk chunkToRemove) { if (LOGGER.isDebugEnabled()) LOGGER.debug("attempting to remove " + chunkToRemove + " from " + getName()); if (_times.containsKey(chunkToRemove)) { if (LOGGER.isDebugEnabled()) LOGGER.debug("removing and setting status slots"); double time = _times.remove(chunkToRemove); _sourceChunks.remove(time); chunkRemoved(chunkToRemove); if (LOGGER.isDebugEnabled()) { // TODO remove debugging code LOGGER.debug(getName() + " Source Chunks & Times " + _sourceChunks); for (IChunk chunk : _sourceChunks.values()) if (chunk.isEncoded()) LOGGER.debug("WARNING : " + chunk + " has already been encoded"); } return true; } else /* * TODO remove debugging code safety check while I debug this issue: in * some cases, the chunk (in the buffer) is being encoded and merged with * an existing chunk - now, the buffer should not contain any encoded * chunks, but somehow this one is still in here.. the problem is that the * merging process changes the hashcode which will mean that the above * check will fail.. this finds the problem and throws the appropriate * exception so we can stop the execution */ /* * problem found: two buffers, with the same chunk, one removes and * encodes. solution: make all insertions copies */ for (IChunk source : _times.keySet()) if (source.equals(chunkToRemove)) throw new IllegalStateException( "Mayday, hashcode has changed for encoded chunk " + chunkToRemove); if (LOGGER.isDebugEnabled()) LOGGER.debug("nothing to remove"); return false; }
/** * must only be called within the write lock. will remove chunks until capacity is no longer * reached (i.e. there is room for one more chunk) - this is called by addSourceChunkInternal */ private void ensureCapacity() { IModel model = getModel(); IMessageBuilder sb = null; while (isCapacityReached()) { if (sb == null) sb = Logger.messageBuilder(); else sb.clear(); /* * remove the first.. */ IChunk toRemove = getRemovalCandidate(); if (LOGGER.isDebugEnabled() || Logger.hasLoggers(model)) { sb.append(toRemove.toString()); sb.append(" is being removed because capacity has been reached"); String msg = sb.toString(); if (LOGGER.isDebugEnabled()) LOGGER.debug(msg); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.BUFFER, msg); } removeSourceChunk(toRemove); } if (sb != null) MessageBuilderFactory.recycle(sb); }
/** when a chunk is matched against, we modify its insertion time.. */ @Override protected boolean matchedInternal(IChunk chunk) { if (!_times.containsKey(chunk)) { if (LOGGER.isWarnEnabled()) LOGGER.warn(chunk + " was matched, but is not in the buffer?"); return false; } /* * if LRA, we've done all we need to */ EjectionPolicy policy = getEjectionPolicy(); if (policy == EjectionPolicy.LeastRecentlyAdded || policy == EjectionPolicy.MostRecentlyAdded) return true; /* * now we can tweak the access time, but only if the policy is LRU or LRM */ double oldTime = _times.get(chunk); double newTime = ACTRRuntime.getRuntime().getClock(getModel()).getTime(); _sourceChunks.remove(oldTime); /* * make sure there are no collisions */ while (_sourceChunks.containsKey(newTime) && !chunk.equals(_sourceChunks.get(newTime))) /* * problem of more than one chunk inserted at the same time (could happen * during path-integration) */ newTime += 0.000001; _times.put(chunk, newTime); _sourceChunks.put(newTime, chunk); if (LOGGER.isDebugEnabled()) LOGGER.debug(getName() + " Source Chunks & Times " + _sourceChunks); return true; }
@Override protected IChunk addSourceChunkInternal(IChunk chunkToInsert) { if (LOGGER.isDebugEnabled()) LOGGER.debug("attempting to insert " + chunkToInsert); /* * ok, something will be changing.. */ IChunk errorChunk = getErrorChunk(); /* * did something go wrong? set the states.. */ if (errorChunk.equals(chunkToInsert) || !isValidChunkType(chunkToInsert.getSymbolicChunk().getChunkType())) { if (LOGGER.isDebugEnabled()) LOGGER.debug(getName() + " : " + chunkToInsert + " was error or invalid of chunk type"); setStateChunk(errorChunk); chunkToInsert = null; } /* * all is good, let's set the chunk */ if (chunkToInsert != null) { /* * are we bumping up against the maximum capacity? */ ensureCapacity(); double now = ACTRRuntime.getRuntime().getClock(getModel()).getTime(); double time = Double.MIN_VALUE; /* * if LRA or LRU, time will be now, if modified, we set it as minimum * double value (can't be negative inf because of potential value * collisions, see below) */ switch (getEjectionPolicy()) { case LeastRecentlyAdded: case LeastRecentlyUsed: case MostRecentlyAdded: case MostRecentlyUsed: time = now; break; } /* * problem of more than one chunk inserted at the same time (could happen * if a production fires multiple adds) */ while (_sourceChunks.containsKey(time) && !chunkToInsert.equals(_sourceChunks.get(time))) time += 0.0000001; _sourceChunks.put(time, chunkToInsert); _times.put(chunkToInsert, time); if (LOGGER.isDebugEnabled()) LOGGER.debug(getName() + " Source Chunks & Times " + _sourceChunks); IModel model = getModel(); if (LOGGER.isDebugEnabled() || Logger.hasLoggers(model)) { IMessageBuilder sb = Logger.messageBuilder(); sb.append(getName()) .append(" inserted ") .append(chunkToInsert.getSymbolicChunk().getName()); if (LOGGER.isDebugEnabled()) LOGGER.debug(sb.toString()); Logger.log(model, Logger.Stream.BUFFER, sb); } chunkInserted(chunkToInsert); } return chunkToInsert; }
/** * handles the updating of associative links, references times, and context/needed tallies. should * also handle similarities, but that is not implemented yet and will be by the six version of * this.<br> * The updating is done here since the listener is removed after encoding, so the master chunk * will not have this listener attached * * @param event * @see * org.jactr.core.chunk.event.ChunkListenerAdaptor#mergingInto(org.jactr.core.chunk.event.ChunkEvent) */ @Override public void mergingInto(ChunkEvent event) { IChunk self = event.getSource(); IChunk master = event.getChunk(); ISubsymbolicChunk4 selfSSC = (ISubsymbolicChunk4) self.getSubsymbolicChunk(); ISubsymbolicChunk4 masterSSC = (ISubsymbolicChunk4) master.getSubsymbolicChunk(); // update the references for master masterSSC.accessed(event.getSimulationTime()); masterSSC.setTimesInContext(masterSSC.getTimesInContext() + selfSSC.getTimesInContext()); masterSSC.setTimesNeeded(masterSSC.getTimesNeeded() + selfSSC.getTimesNeeded()); /* * and refs */ IReferences refs = masterSSC.getReferences(); for (double refTime : selfSSC.getReferences().getTimes()) refs.addReferenceTime(refTime); // will allocate Collection<Link> links = selfSSC.getIAssociations(null); for (Link iLink : links) { IChunk iChunk = iLink.getIChunk(); Link masterLink = masterSSC.getIAssociation(iChunk); if (masterLink != null) { /** need to merge the links */ if (LOGGER.isDebugEnabled()) LOGGER.debug(master + " already linked to " + iChunk + ", merging"); masterLink.setCount(Math.max(masterLink.getCount(), iLink.getCount())); masterLink.setStrength(Math.max(masterLink.getStrength(), iLink.getStrength())); } else { /** add the link to master */ if (LOGGER.isDebugEnabled()) LOGGER.debug(master + " not already linked to " + iChunk + ", linking."); Link newLink = new Link(master, iChunk, iLink.getCount(), iLink.getStrength()); masterSSC.addLink(newLink); ((ISubsymbolicChunk4) iChunk.getSubsymbolicChunk()).addLink(newLink); } /* * reduce the count so that we are sure we're removing the link */ iLink.setCount(1); selfSSC.removeLink(iLink); ((ISubsymbolicChunk4) iChunk.getSubsymbolicChunk()).removeLink(iLink); } links.clear(); links = selfSSC.getJAssociations(links); for (Link jLink : links) { IChunk jChunk = jLink.getJChunk(); Link masterLink = masterSSC.getIAssociation(jChunk); if (masterLink != null) { /** need to merge the links */ if (LOGGER.isDebugEnabled()) LOGGER.debug(jChunk + " already linked to " + master + ", merging"); masterLink.setCount(Math.max(masterLink.getCount(), jLink.getCount())); masterLink.setStrength(Math.max(masterLink.getStrength(), jLink.getStrength())); } else { /** add the link to master */ if (LOGGER.isDebugEnabled()) LOGGER.debug(jChunk + " not already linked to " + master + ", linking."); Link newLink = new Link(jChunk, master, jLink.getCount(), jLink.getStrength()); masterSSC.addLink(newLink); ((ISubsymbolicChunk4) jChunk.getSubsymbolicChunk()).addLink(newLink); } /* * reduce the count so that we are sure we're removing the link */ jLink.setCount(1); selfSSC.removeLink(jLink); ((ISubsymbolicChunk4) jChunk.getSubsymbolicChunk()).removeLink(jLink); } }
@Override public void slotChanged(ChunkEvent ce) { IChunk iChunk = ce.getSource(); Object oldValue = ce.getOldSlotValue(); Object newValue = ce.getNewSlotValue(); if (LOGGER.isDebugEnabled()) LOGGER.debug(iChunk + "." + ce.getSlotName() + "=" + newValue + " (was " + oldValue + ")"); /* * we can only do this if ISubsymbolicChunk is ISubsymbolicChunk4 */ if (!(iChunk.getSubsymbolicChunk() instanceof ISubsymbolicChunk4)) { if (LOGGER.isWarnEnabled()) LOGGER.warn( "Can only adjust associative links if the chunk's subsymbolic is derived from ISubsymbolicChunk4"); return; } /* * I chunk is the owner that references J */ ISubsymbolicChunk4 sscI = (ISubsymbolicChunk4) iChunk.getSubsymbolicChunk(); /* * first the old chunk value.. */ if (oldValue instanceof IChunk) { IChunk jChunk = (IChunk) oldValue; if (jChunk.getSubsymbolicChunk() instanceof ISubsymbolicChunk4) { ISubsymbolicChunk4 sscJ = (ISubsymbolicChunk4) jChunk.getSubsymbolicChunk(); Link sJI = sscJ.getIAssociation(iChunk); if (sJI != null) { sJI.decrement(); if (sJI.getCount() == 0) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Removing link between " + iChunk + " and " + jChunk + " : " + sJI); sscI.removeLink(sJI); sscJ.removeLink(sJI); } else if (LOGGER.isDebugEnabled()) LOGGER.debug( "Multiple links established between " + iChunk + " and " + jChunk + " decrementing : " + sJI); } } else if (LOGGER.isWarnEnabled()) LOGGER.warn( "old value " + jChunk + " doesn't have a ISubsymbolicChunk4, nothing to be done"); } /* * now for the new one */ if (newValue instanceof IChunk) { IChunk jChunk = (IChunk) newValue; if (jChunk.getSubsymbolicChunk() instanceof ISubsymbolicChunk4) { ISubsymbolicChunk4 sscJ = (ISubsymbolicChunk4) jChunk.getSubsymbolicChunk(); Link sJI = sscJ.getIAssociation(iChunk); /* * is this a new linkage? */ if (sJI == null) { sJI = new Link(jChunk, iChunk); if (LOGGER.isDebugEnabled()) LOGGER.debug("Adding link between " + iChunk + " and " + jChunk + " : " + sJI); sscI.addLink(sJI); sscJ.addLink(sJI); } else { sJI.increment(); // not new, but we need to increment the link if (LOGGER.isDebugEnabled()) LOGGER.debug( "Link already established between " + iChunk + " and " + jChunk + " incrementing : " + sJI); } } else if (LOGGER.isWarnEnabled()) LOGGER.warn( "new value " + jChunk + " doesn't have a ISubsymbolicChunk4, nothing to be done"); } }
public void copy(IChunk source, IChunk destination) { for (String key : source.getMetaDataKeys()) destination.setMetaData(key, source.getMetaData(key)); destination.setMetaData(COPIED_FROM_KEY, source); }
public void dispose(IChunk chunk) { chunk.dispose(); }