All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.leialearns.command.encounter.Encounter Maven / Gradle / Ivy

The newest version!
package org.leialearns.command.encounter;

import org.leialearns.api.enumerations.AccessMode;
import org.leialearns.api.enumerations.Direction;
import org.leialearns.api.enumerations.ModelType;
import org.leialearns.api.interaction.Alphabet;
import org.leialearns.api.interaction.DirectedSymbol;
import org.leialearns.api.interaction.InteractionContext;
import org.leialearns.api.interaction.Symbol;
import org.leialearns.api.model.Counted;
import org.leialearns.api.model.Version;
import org.leialearns.api.model.histogram.Counter;
import org.leialearns.api.session.Root;
import org.leialearns.api.session.Session;
import org.leialearns.api.structure.Node;
import org.leialearns.api.structure.Structure;
import org.leialearns.common.ExceptionWrapper;
import org.leialearns.common.Setting;
import org.leialearns.common.TypedIterable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;

import static org.leialearns.common.Display.display;
import static org.leialearns.common.Display.show;
import static org.leialearns.common.Static.getLoggingClass;

/**
 * Connects the LEIA system to its environment by feeding it tokens from a file. This encounter
 * uses a trivial implementation of the active part of LEIA with a single symbol: '.', that means
 * 'no action'.
 */
public class Encounter implements org.leialearns.api.command.Encounter {
    private final Logger logger = LoggerFactory.getLogger(getLoggingClass(this));
    private final Setting limitFlag = new Setting<>("Limit flag", false);
    private final Setting streamAdapter = new Setting<>("Stream adapter");
    private final Setting interactionContextUri = new Setting<>("Interaction context URI");
    private final Setting autoExtendLimit = new Setting<>("Auto extend limit", -1);
    private Version lastVersion = null;

    @Autowired
    private Root root;

    /**
     * Sets the flag that indicates whether the encounter should stop after a fixed number of symbols.
     * @param limitFlag The limit flag
     */
    public void setLimitFlag(boolean limitFlag) {
        this.limitFlag.set(limitFlag);
    }

    /**
     * Sets the stream adapter that provides the symbols for this encounter.
     * @param streamAdapter The stream adapter
     */
    public void setStreamAdapter(StreamAdapter streamAdapter) {
        this.streamAdapter.set(streamAdapter);
    }

    /**
     * Sets the URI to use for the interaction context. If there is already an interaction context with this URI
     * in the data source, then is will be re-used and extended. If not, a new interaction context will be created.
     * @param interactionContextUri The URI of the interaction context to use
     */
    public void setInteractionContextUri(String interactionContextUri) {
        this.interactionContextUri.set(interactionContextUri);
    }

    /**
     * Creates a new session for this encounter.
     * @return A new session for this encounter
     */
    protected Session createSession() {
        return root.createSession(interactionContextUri.get());
    }

    /**
     * Sets the maximum depth of nodes that will be marked extensible.
     * (see {@link org.leialearns.api.structure.Node#getExtensible()}) by the encounter (rather than relying on the
     * optimizer to manage the extensibility of nodes).
     * @param autoExtendLimit The maximum depth of nodes that will be marked extensible
     */
    public void setAutoExtendLimit(int autoExtendLimit) {
        this.autoExtendLimit.set(autoExtendLimit);
    }

    /**
     * Returns the last {@link org.leialearns.api.enumerations.ModelType#COUNTED} version that was created by this encounter.
     * @return the last version that was created by this encounter
     */
    @Override
    public Version getLastVersion() {
        return lastVersion;
    }

    /**
     * Feeds the given files to the LEIA system.
     * @param args The paths of the files to feed
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
    public void command(String... args) {
        StringBuilder builder = new StringBuilder("Args");
        for (String arg : args) {
            builder.append(": ");
            builder.append(arg);
        }
        logger.info(builder.toString());

        Session session = createSession();
        InteractionContext interactionContext = session.getInteractionContext();
        Structure structure = interactionContext.getStructure();
        logger.debug("Structure: {}", structure);
        logger.debug("Interaction context: {}", interactionContext);
        Alphabet actions = interactionContext.getActions();
        logger.debug("Actions: {}", actions);
        Symbol nonAction = actions.internalize(".");
        logger.debug("Non-action: {}", nonAction);

        StreamAdapter adapter = streamAdapter.get();
        int a = 0;
        if (a + 1 < args.length && "-s".equals(args[a])) {
            adapter.setSkip(Long.parseLong(args[a + 1]));
            a += 2;
        }
        if (a + 1 < args.length && "-l".equals(args[a])) {
            adapter.setLimit(Long.parseLong(args[a + 1]));
            a += 2;
        }
        if (a < args.length && "--".equals(args[a])) {
            a++;
        }
        if (a > 0) {
            int l = args.length - a;
            String[] newArgs = new String[l];
            System.arraycopy(args, a, newArgs, 0, l);
            args = newArgs;
        }

        for (String sourceLocation : args) {
            Version version = session.createVersion(ModelType.COUNTED);
            version.setAccessMode(AccessMode.WRITABLE, session);
            Counted countedVersion = version.createCountedVersion();
            Deque state = new ArrayDeque<>();

            try {
                adapter.setInputStream(new URL(sourceLocation).openStream());
            } catch (IOException exception) {
                throw ExceptionWrapper.wrap(exception);
            }
            int i = 0;
            Alphabet responses = interactionContext.getResponses();
            while (adapter.hasNext()) {
                String token = adapter.next();
                logger.info("Token: " + show(token));
                Symbol symbol = responses.internalize(token);
                logger.debug("Symbol: " + symbol.toString(Direction.RESPONSE) + ": " + symbol.descriptionLength());
                DirectedSymbol directedSymbol = symbol.createDirectedSymbol(Direction.RESPONSE);
                logger.debug("Directed symbol: [" + directedSymbol + "]");

                logger.trace("State: " + display(state));
                Node node = structure.findOrCreateNode(nonAction, new TypedIterable<>(state, DirectedSymbol.class));
                if (node.getDepth() < autoExtendLimit.get()) {
                    logger.debug("Node structure: [" + node.getStructure() + "]");
                    structure.markExtensible(node);
                    logger.debug("Marked extensible: {}", node);
                }
                logger.debug("Node: [" + node + "]");
                Counter counter = countedVersion.getCounter(node, symbol);
                counter.increment();

                state.offerFirst(directedSymbol);
                logger.debug("Structure max depth: " + structure.getMaxDepth());
                while (state.size() > structure.getMaxDepth() + 1) {
                    state.pollLast();
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("State: [" + stateToString(state) + "]");
                }
                if (limitFlag.get() && ++i > 1000) {
                    break;
                }
            }
            logger.info("Finished source location: " + sourceLocation);

            try {
                version.waitForLock(session);
            } catch (InterruptedException exception) {
                throw ExceptionWrapper.wrap(exception);
            }
            version.setAccessMode(AccessMode.READABLE, session);

            lastVersion = version;
        }
    }

    /**
     * Returns a string representation of the given state
     * @param state The state to represent
     * @return The representation of the given state
     */
    public String stateToString(Collection state) {
        StringBuilder builder = new StringBuilder("{");
        boolean first = true;
        for (DirectedSymbol symbol : state) {
            if (first) {
                first = false;
            } else {
                builder.append(",");
            }
            builder.append(' ');
            builder.append(symbol.toString());
        }
        if (!first) {
            builder.append(' ');
        }
        builder.append("}");
        return builder.toString();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy